예제 #1
0
void CallDumper::checkPreCall(const CallEvent &Call, CheckerContext &C) const {
  unsigned Indentation = 0;
  for (const LocationContext *LC = C.getLocationContext()->getParent();
       LC != nullptr; LC = LC->getParent())
    ++Indentation;

  // It is mildly evil to print directly to llvm::outs() rather than emitting
  // warnings, but this ensures things do not get filtered out by the rest of
  // the static analyzer machinery.
  llvm::outs().indent(Indentation);
  Call.dump(llvm::outs());
}
예제 #2
0
void PHPZPPCheckerImpl::checkPreCall(const CallEvent &Call,
                                     CheckerContext &C) const {
  initIdentifierInfo(C.getASTContext());

  unsigned offset;

  if (!Call.isGlobalCFunction())
    return;

  if (Call.getCalleeIdentifier() == IIzpp) {
    offset = 1;
  } else if (Call.getCalleeIdentifier() == IIzpp_ex) {
    offset = 2;
  } else if (Call.getCalleeIdentifier() == IIzpmp) {
    offset = 2;
  } else if (Call.getCalleeIdentifier() == IIzpmp_ex) {
    offset = 3;
  } else {
    return;
  }

  if (TSRMBuild) {
    ++offset;
  }

  if (Call.getNumArgs() <= offset)
    // Something is really weird - this should be caught by the compiler
    return;

  const StringLiteral *format_spec_sl =
      getCStringLiteral(Call.getArgSVal(offset));
  if (!format_spec_sl) {
    // TODO need a good way to report this, even though this is no error
    std::cout << "Couldn't get format string looked at offset " << offset << std::endl;
    Call.dump();
    return;
  }
  const StringRef format_spec = format_spec_sl->getBytes();

  // Call.dump();
  for (StringRef::const_iterator modifier = format_spec.begin(),
                                 last_mod = format_spec.end();
       modifier != last_mod; ++modifier) {
//std::cout << "  I am checking for " << *modifier << std::endl;
    const PHPTypeRange range = map.equal_range(*modifier);

    if (range.first == range.second) {
      BugReport *R = new BugReport(
          *InvalidModifierBugType,
          std::string("Unknown modifier '") + *modifier + "'", C.addTransition());
      C.emitReport(R);
      return;
    }

    for (PHPTypeMap::const_iterator type = range.first; type != range.second;
         ++type) {
      if (!type->second) {
        // Current modifier doesn't need an argument, these are special things
        // like |, ! or /
        continue;
      }
      ++offset;
//std::cout << "    I need a " << *type->second << " (" << offset << ")" << std::endl;
      if (Call.getNumArgs() <= offset) {
        BugReport *R = new BugReport(*WrongArgumentNumberBugType,
                                     "Too few arguments for format specified",
                                     C.addTransition());
        C.emitReport(R);
//std::cout << "!!!!I am missing args! " << Call.getNumArgs() << "<=" << offset << std::endl;
        return;
      }

      SVal val = Call.getArgSVal(offset);
      if (!compareTypeWithSVal(val, *type->second, C)) {
        // TODO: Move error reporting here?

        // Even if there is a type mismatch we can continue, most of the time
        // this should be a simple mistake by the user, in rare cases the user
        // missed an argument and will get many subsequent errors
      }
    }
  }

  if (Call.getNumArgs() > 1 + offset) {
    BugReport *R = new BugReport(*WrongArgumentNumberBugType,
                                 "Too many arguments for format specified",
                                 C.addTransition());
    R->markInteresting(Call.getArgSVal(offset));
    C.emitReport(R);
  }
}