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()); }
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); } }