// OutputPossibleOverflows - We've found a possible overflow earlier, // now check whether Body might contain a comparison which might be // preventing the overflow. // This doesn't do flow analysis, range analysis, or points-to analysis; it's // just a dumb "is there a comparison" scan. The aim here is to // detect the most blatent cases of overflow and educate the // programmer. void MallocOverflowSecurityChecker::OutputPossibleOverflows( llvm::SmallVectorImpl<MallocOverflowCheck> &PossibleMallocOverflows, const Decl *D, BugReporter &BR, AnalysisManager &mgr) const { // By far the most common case: nothing to check. if (PossibleMallocOverflows.empty()) return; // Delete any possible overflows which have a comparison. CheckOverflowOps c(PossibleMallocOverflows, BR.getContext()); c.Visit(mgr.getAnalysisContext(D)->getBody()); // Output warnings for all overflows that are left. for (CheckOverflowOps::theVecType::iterator i = PossibleMallocOverflows.begin(), e = PossibleMallocOverflows.end(); i != e; ++i) { SourceRange R = i->mulop->getSourceRange(); BR.EmitBasicReport("MallocOverflowSecurityChecker", "the computation of the size of the memory allocation may overflow", PathDiagnosticLocation::createOperatorLoc(i->mulop, BR.getSourceManager()), &R, 1); } }
static void orderEdges(const llvm::SmallPtrSetImpl<CallGraphEdge *> &Edges, llvm::SmallVectorImpl<CallGraphEdge *> &OrderedEdges) { for (auto *Edge : Edges) OrderedEdges.push_back(Edge); std::sort(OrderedEdges.begin(), OrderedEdges.end(), [](CallGraphEdge *left, CallGraphEdge *right) { return left->getOrdinal() < right->getOrdinal(); }); }
static SILValue allIncomingValuesEqual( llvm::SmallVectorImpl<std::pair<SILBasicBlock *, SILValue >> &IncomingValues) { SILValue First = stripRCIdentityPreservingInsts(IncomingValues[0].second); if (std::all_of(std::next(IncomingValues.begin()), IncomingValues.end(), [&First](std::pair<SILBasicBlock *, SILValue> P) -> bool { return stripRCIdentityPreservingInsts(P.second) == First; })) return First; return SILValue(); }
void DeclContext::collectAllContexts(llvm::SmallVectorImpl<DeclContext *> &Contexts){ Contexts.clear(); if (DeclKind != Decl::Namespace) { Contexts.push_back(this); return; } NamespaceDecl *Self = static_cast<NamespaceDecl *>(this); for (NamespaceDecl *N = Self->getMostRecentDecl(); N; N = N->getPreviousDecl()) Contexts.push_back(N); std::reverse(Contexts.begin(), Contexts.end()); }
/// ApplyQAOverride - Apply a list of edits to the input argument lists. /// /// The input string is a space separate list of edits to perform, /// they are applied in order to the input argument lists. Edits /// should be one of the following forms: /// /// '#': Silence information about the changes to the command line arguments. /// /// '^': Add FOO as a new argument at the beginning of the command line. /// /// '+': Add FOO as a new argument at the end of the command line. /// /// 's/XXX/YYY/': Substitute the regular expression XXX with YYY in the command /// line. /// /// 'xOPTION': Removes all instances of the literal argument OPTION. /// /// 'XOPTION': Removes all instances of the literal argument OPTION, /// and the following argument. /// /// 'Ox': Removes all flags matching 'O' or 'O[sz0-9]' and adds 'Ox' /// at the end of the command line. /// /// \param OS - The stream to write edit information to. /// \param Args - The vector of command line arguments. /// \param Edit - The override command to perform. /// \param SavedStrings - Set to use for storing string representations. static void ApplyOneQAOverride(llvm::raw_ostream &OS, llvm::SmallVectorImpl<const char*> &Args, llvm::StringRef Edit, std::set<std::string> &SavedStrings) { // This does not need to be efficient. if (Edit[0] == '^') { const char *Str = SaveStringInSet(SavedStrings, Edit.substr(1)); OS << "### Adding argument " << Str << " at beginning\n"; Args.insert(Args.begin() + 1, Str); } else if (Edit[0] == '+') { const char *Str = SaveStringInSet(SavedStrings, Edit.substr(1)); OS << "### Adding argument " << Str << " at end\n"; Args.push_back(Str); } else if (Edit[0] == 's' && Edit[1] == '/' && Edit.endswith("/") && Edit.slice(2, Edit.size()-1).find('/') != llvm::StringRef::npos) { llvm::StringRef MatchPattern = Edit.substr(2).split('/').first; llvm::StringRef ReplPattern = Edit.substr(2).split('/').second; ReplPattern = ReplPattern.slice(0, ReplPattern.size()-1); for (unsigned i = 1, e = Args.size(); i != e; ++i) { std::string Repl = llvm::Regex(MatchPattern).sub(ReplPattern, Args[i]); if (Repl != Args[i]) { OS << "### Replacing '" << Args[i] << "' with '" << Repl << "'\n"; Args[i] = SaveStringInSet(SavedStrings, Repl); } } } else if (Edit[0] == 'x' || Edit[0] == 'X') { std::string Option = Edit.substr(1, std::string::npos); for (unsigned i = 1; i < Args.size();) { if (Option == Args[i]) { OS << "### Deleting argument " << Args[i] << '\n'; Args.erase(Args.begin() + i); if (Edit[0] == 'X') { if (i < Args.size()) { OS << "### Deleting argument " << Args[i] << '\n'; Args.erase(Args.begin() + i); } else OS << "### Invalid X edit, end of command line!\n"; } } else ++i; } } else if (Edit[0] == 'O') { for (unsigned i = 1; i < Args.size();) { const char *A = Args[i]; if (A[0] == '-' && A[1] == 'O' && (A[2] == '\0' || (A[3] == '\0' && (A[2] == 's' || A[2] == 'z' || ('0' <= A[2] && A[2] <= '9'))))) { OS << "### Deleting argument " << Args[i] << '\n'; Args.erase(Args.begin() + i); } else ++i; } OS << "### Adding argument " << Edit << " at end\n"; Args.push_back(SaveStringInSet(SavedStrings, '-' + Edit.str())); } else { OS << "### Unrecognized edit: " << Edit << "\n"; } }
/// Parse an identifier in an MS-style inline assembly block. /// /// \param CastInfo - a void* so that we don't have to teach Parser.h /// about the actual type. ExprResult Parser::ParseMSAsmIdentifier(llvm::SmallVectorImpl<Token> &LineToks, unsigned &NumLineToksConsumed, void *CastInfo, bool IsUnevaluatedContext) { llvm::InlineAsmIdentifierInfo &Info = *(llvm::InlineAsmIdentifierInfo *)CastInfo; // Push a fake token on the end so that we don't overrun the token // stream. We use ';' because it expression-parsing should never // overrun it. const tok::TokenKind EndOfStream = tok::semi; Token EndOfStreamTok; EndOfStreamTok.startToken(); EndOfStreamTok.setKind(EndOfStream); LineToks.push_back(EndOfStreamTok); // Also copy the current token over. LineToks.push_back(Tok); PP.EnterTokenStream(LineToks.begin(), LineToks.size(), /*disable macros*/ true, /*owns tokens*/ false); // Clear the current token and advance to the first token in LineToks. ConsumeAnyToken(); // Parse an optional scope-specifier if we're in C++. CXXScopeSpec SS; if (getLangOpts().CPlusPlus) { ParseOptionalCXXScopeSpecifier(SS, ParsedType(), /*EnteringContext=*/false); } // Require an identifier here. SourceLocation TemplateKWLoc; UnqualifiedId Id; bool Invalid = true; ExprResult Result; if (Tok.is(tok::kw_this)) { Result = ParseCXXThis(); Invalid = false; } else { Invalid = ParseUnqualifiedId(SS, /*EnteringContext=*/false, /*AllowDestructorName=*/false, /*AllowConstructorName=*/false, /*ObjectType=*/ParsedType(), TemplateKWLoc, Id); // Perform the lookup. Result = Actions.LookupInlineAsmIdentifier(SS, TemplateKWLoc, Id, Info, IsUnevaluatedContext); } // While the next two tokens are 'period' 'identifier', repeatedly parse it as // a field access. We have to avoid consuming assembler directives that look // like '.' 'else'. while (Result.isUsable() && Tok.is(tok::period)) { Token IdTok = PP.LookAhead(0); if (IdTok.isNot(tok::identifier)) break; ConsumeToken(); // Consume the period. IdentifierInfo *Id = Tok.getIdentifierInfo(); ConsumeToken(); // Consume the identifier. Result = Actions.LookupInlineAsmVarDeclField(Result.get(), Id->getName(), Info, Tok.getLocation()); } // Figure out how many tokens we are into LineToks. unsigned LineIndex = 0; if (Tok.is(EndOfStream)) { LineIndex = LineToks.size() - 2; } else { while (LineToks[LineIndex].getLocation() != Tok.getLocation()) { LineIndex++; assert(LineIndex < LineToks.size() - 2); // we added two extra tokens } } // If we've run into the poison token we inserted before, or there // was a parsing error, then claim the entire line. if (Invalid || Tok.is(EndOfStream)) { NumLineToksConsumed = LineToks.size() - 2; } else { // Otherwise, claim up to the start of the next token. NumLineToksConsumed = LineIndex; } // Finally, restore the old parsing state by consuming all the tokens we // staged before, implicitly killing off the token-lexer we pushed. for (unsigned i = 0, e = LineToks.size() - LineIndex - 2; i != e; ++i) { ConsumeAnyToken(); } assert(Tok.is(EndOfStream)); ConsumeToken(); // Leave LineToks in its original state. LineToks.pop_back(); LineToks.pop_back(); return Result; }