コード例 #1
0
// Try to retrieve the function declaration and find the function parameter
// types which are pointers/references to a non-pointer const.
// We do not invalidate the corresponding argument regions.
static void findPtrToConstParams(llvm::SmallSet<unsigned, 1> &PreserveArgs,
                       const CallOrObjCMessage &Call) {
  const Decl *CallDecl = Call.getDecl();
  if (!CallDecl)
    return;

  if (const FunctionDecl *FDecl = dyn_cast<FunctionDecl>(CallDecl)) {
    const IdentifierInfo *II = FDecl->getIdentifier();

    // List the cases, where the region should be invalidated even if the
    // argument is const.
    if (II) {
      StringRef FName = II->getName();
      //  - 'int pthread_setspecific(ptheread_key k, const void *)' stores a
      // value into thread local storage. The value can later be retrieved with
      // 'void *ptheread_getspecific(pthread_key)'. So even thought the
      // parameter is 'const void *', the region escapes through the call.
      //  - funopen - sets a buffer for future IO calls.
      //  - ObjC functions that end with "NoCopy" can free memory, of the passed
      // in buffer.
      // - Many CF containers allow objects to escape through custom
      // allocators/deallocators upon container construction.
      // - NSXXInsertXX, for example NSMapInsertIfAbsent, since they can
      // be deallocated by NSMapRemove.
      // - Any call that has a callback as one of the arguments.
      if (FName == "pthread_setspecific" ||
          FName == "funopen" ||
          FName.endswith("NoCopy") ||
          (FName.startswith("NS") &&
            (FName.find("Insert") != StringRef::npos)) ||
          Call.isCFCGAllowingEscape(FName) ||
          Call.hasNonZeroCallbackArg())
        return;
    }

    for (unsigned Idx = 0, E = Call.getNumArgs(); Idx != E; ++Idx) {
      if (FDecl && Idx < FDecl->getNumParams()) {
        if (isPointerToConst(FDecl->getParamDecl(Idx)))
          PreserveArgs.insert(Idx);
      }
    }
    return;
  }

  if (const ObjCMethodDecl *MDecl = dyn_cast<ObjCMethodDecl>(CallDecl)) {
    assert(MDecl->param_size() <= Call.getNumArgs());
    unsigned Idx = 0;

    if (Call.hasNonZeroCallbackArg())
      return;

    for (clang::ObjCMethodDecl::param_const_iterator
         I = MDecl->param_begin(), E = MDecl->param_end(); I != E; ++I, ++Idx) {
      if (isPointerToConst(*I))
        PreserveArgs.insert(Idx);
    }
    return;
  }
}
コード例 #2
0
void CallAndMessageChecker::PreVisitProcessArgs(CheckerContext &C,
                                                CallOrObjCMessage callOrMsg,
                                                const char *BT_desc,
                                                OwningPtr<BugType> &BT) {
  // Don't check for uninitialized field values in arguments if the
  // caller has a body that is available and we have the chance to inline it.
  // This is a hack, but is a reasonable compromise betweens sometimes warning
  // and sometimes not depending on if we decide to inline a function.
  const Decl *D = callOrMsg.getDecl();
  const bool checkUninitFields =
    !(C.getAnalysisManager().shouldInlineCall() &&
      (D && D->getBody()));
  
  for (unsigned i = 0, e = callOrMsg.getNumArgs(); i != e; ++i)
    if (PreVisitProcessArg(C, callOrMsg.getArgSVal(i),
                           callOrMsg.getArgSourceRange(i), callOrMsg.getArg(i),
                           checkUninitFields,
                           BT_desc, BT))
      return;
}