private void checkStateForLeakedObligations(
        State state, Map<Obligation, State> leakedObligationMap) throws IllegalStateException {
      if (DEBUG) {
        Path path = state.getPath();
        if (path.getLength() > 0
            && path.getBlockIdAt(path.getLength() - 1) != cfg.getExit().getLabel()) {
          throw new IllegalStateException(
              "path " + path + " at cfg exit has no label for exit block");
        }
      }

      for (int id = 0; id < database.getFactory().getMaxObligationTypes(); ++id) {
        Obligation obligation = database.getFactory().getObligationById(id);
        // If the raw count produced by the analysis
        // for this obligation type is 0,
        // assume everything is ok on this state's path.
        int rawLeakCount = state.getObligationSet().getCount(id);
        if (rawLeakCount == 0) {
          continue;
        }

        // Apply the false-positive suppression heuristics
        int leakCount = getAdjustedLeakCount(state, id);

        if (leakCount > 0) {
          leakedObligationMap.put(obligation, state);
        }
        // TODO: if the leak count is less than 0, then a nonexistent
        // resource was closed
      }
    }
 public PostProcessingPathVisitor(Obligation possiblyLeakedObligation /*
                                                                            * ,
                                                                            * int
                                                                            * initialLeakCount
                                                                            */, State state) {
   this.possiblyLeakedObligation = possiblyLeakedObligation;
   this.state = state;
   this.adjustedLeakCount =
       state.getObligationSet().getCount(possiblyLeakedObligation.getId());
   if (COMPUTE_TRANSFERS) {
     this.transferList = new LinkedList<PossibleObligationTransfer>();
   }
 }
    private void reportWarning(Obligation obligation, State state, StateSet factAtExit) {
      String className = obligation.getClassName();

      if (methodDescriptor.isStatic()
          && methodDescriptor.getName().equals("main")
          && methodDescriptor.getSignature().equals("([Ljava/lang/String;)V")
          && (className.contains("InputStream")
              || className.contains("Reader")
              || factAtExit.isOnExceptionPath())) {
        // Don't report unclosed input streams and readers in main()
        // methods
        return;
      }
      String bugPattern =
          factAtExit.isOnExceptionPath()
              ? "OBL_UNSATISFIED_OBLIGATION_EXCEPTION_EDGE"
              : "OBL_UNSATISFIED_OBLIGATION";
      BugInstance bugInstance =
          new BugInstance(FindUnsatisfiedObligation.this, bugPattern, NORMAL_PRIORITY)
              .addClassAndMethod(methodDescriptor)
              .addClass(className)
              .describe("CLASS_REFTYPE");

      // Report how many instances of the obligation are remaining
      bugInstance
          .addInt(state.getObligationSet().getCount(obligation.getId()))
          .describe(IntAnnotation.INT_OBLIGATIONS_REMAINING);

      // Add source line information
      annotateWarningWithSourceLineInformation(state, obligation, bugInstance);

      if (REPORT_OBLIGATION_SET) {
        bugInstance
            .addString(state.getObligationSet().toString())
            .describe(StringAnnotation.REMAINING_OBLIGATIONS_ROLE);
      }

      bugReporter.reportBug(bugInstance);
    }
      private void applyPossibleObligationTransfers() {
        //
        // See if we recorded any possible obligation transfers
        // that might have created a "wrapper" object.
        // In many cases, it is correct to close either
        // the "wrapped" or "wrapper" object.
        // So, if we see a possible transfer, and we see
        // a +1/-1 obligation count for the pair
        // (consumed and produced obligation types),
        // rather than 0/0,
        // then we will assume that which resource was closed
        // (wrapper or wrapped) was the opposite of what
        // we expected.
        //
        for (PossibleObligationTransfer transfer : transferList) {
          if (DEBUG_FP) {
            System.out.println("Checking possible transfer " + transfer + "...");
          }

          boolean matches = transfer.matches(possiblyLeakedObligation);

          if (DEBUG_FP) {
            System.out.println("  matches: " + possiblyLeakedObligation);
          }

          if (matches) {
            boolean balanced = transfer.balanced(state);
            if (DEBUG_FP) {
              System.out.println("  balanced: " + balanced + " in " + state.getObligationSet());
            }
            if (balanced) {
              if (DEBUG_FP) {
                System.out.println(
                    "  Suppressing path because "
                        + "a transfer appears to result in balanced "
                        + "outstanding obligations");
              }

              adjustedLeakCount = 0;
              break;
            }
          }
        }
      }
      private void checkForPossibleObligationTransfer(
          InvokeInstruction inv, InstructionHandle handle) throws ClassNotFoundException {
        //
        // We will assume that a method invocation might transfer
        // an obligation from one type to another if
        // 1. either
        // - it's a constructor where the constructed
        // type and exactly one param type
        // are obligation types, or
        // - it's a method where the return type and
        // exactly one param type are obligation types
        // 2. at least one instance of the resource "consumed"
        // by the transfer exists at the point of the transfer.
        // E.g., if we see a transfer of InputStream->Reader,
        // there must be an instance of InputStream at
        // the transfer point.
        //

        if (DEBUG_FP) {
          System.out.println("Checking " + handle + " as possible obligation transfer...:");
        }

        // Find the State which is a prefix of the error state
        // at the location of this (possible) transfer.
        State transferState = getTransferState(handle);
        if (transferState == null) {
          if (DEBUG_FP) {
            System.out.println("No transfer state???");
          }
          return;
        }

        String methodName = inv.getMethodName(cpg);
        Type producedType =
            methodName.equals("<init>") ? inv.getReferenceType(cpg) : inv.getReturnType(cpg);

        if (DEBUG_FP && !(producedType instanceof ObjectType)) {
          System.out.println("Produced type " + producedType + " not an ObjectType");
        }

        if (producedType instanceof ObjectType) {
          Obligation produced =
              database.getFactory().getObligationByType((ObjectType) producedType);

          if (DEBUG_FP && produced == null) {
            System.out.println("Produced type  " + producedType + " not an obligation type");
          }

          if (produced != null) {
            XMethod calledMethod = XFactory.createXMethod(inv, cpg);
            Obligation[] params = database.getFactory().getParameterObligationTypes(calledMethod);

            for (int i = 0; i < params.length; i++) {
              Obligation consumed = params[i];

              if (DEBUG_FP && consumed == null) {
                System.out.println("Param " + i + " not an obligation type");
              }

              if (DEBUG_FP && consumed != null && consumed.equals(produced)) {
                System.out.println("Consumed type is the same as produced type");
              }

              if (consumed != null && !consumed.equals(produced)) {
                // See if an instance of the consumed obligation
                // type
                // exists here.
                if (transferState.getObligationSet().getCount(consumed.getId()) > 0) {
                  transferList.add(new PossibleObligationTransfer(consumed, produced));
                  if (DEBUG_FP) {
                    System.out.println(
                        "===> Possible transfer of "
                            + consumed
                            + " to "
                            + produced
                            + " at "
                            + handle);
                  }
                } else if (DEBUG_FP) {
                  System.out.println(
                      handle
                          + " not a transfer "
                          + "of "
                          + consumed
                          + "->"
                          + produced
                          + " because no instances of "
                          + consumed);
                  System.out.println("I see " + transferState.getObligationSet());
                }
              }
            }
          }
        }
      }
 /**
  * Determine whether the state has "balanced" obligation counts for the consumed and produced
  * Obligation types.
  *
  * @param state a State
  * @return true if the obligation counts are balanced, false otherwise
  */
 private boolean balanced(State state) {
   int consumedCount = state.getObligationSet().getCount(consumed.getId());
   int producedCount = state.getObligationSet().getCount(produced.getId());
   return (consumedCount + producedCount == 0) && (consumedCount == 1 || producedCount == 1);
 }