From 56a938ff85a444eb3d30d2634d92ce5b1f6fae56 Mon Sep 17 00:00:00 2001 From: Anna Zaks Date: Fri, 16 Mar 2012 23:24:20 +0000 Subject: [PATCH] [analyzer] Create symbol-aware stack hints (building upon r152837). The symbol-aware stack hint combines the checker-provided message with the information about how the symbol was passed to the callee: as a parameter or a return value. For malloc, the generated messages look like this : "Returning from 'foo'; released memory via 1st parameter" "Returning from 'foo'; allocated memory via 1st parameter" "Returning from 'foo'; allocated memory returned" "Returning from 'foo'; reallocation of 1st parameter failed" (We are yet to handle cases when the symbol is a field in a struct or an array element.) git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@152962 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Core/BugReporter/PathDiagnostic.h | 71 +- lib/StaticAnalyzer/Checkers/MallocChecker.cpp | 38 +- lib/StaticAnalyzer/Core/BugReporter.cpp | 33 +- lib/StaticAnalyzer/Core/PathDiagnostic.cpp | 91 ++ test/Analysis/malloc-plist.c | 922 ++++++++++++++++-- 5 files changed, 1063 insertions(+), 92 deletions(-) diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h b/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h index fea02caafd..b40bc71010 100644 --- a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h +++ b/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h @@ -41,6 +41,8 @@ class Stmt; namespace ento { class ExplodedNode; +class SymExpr; +typedef const SymExpr* SymbolRef; //===----------------------------------------------------------------------===// // High-level interface for handlers of path-sensitive diagnostics. @@ -357,6 +359,52 @@ public: virtual void Profile(llvm::FoldingSetNodeID &ID) const; }; +/// \brief Interface for classes constructing Stack hints. +/// +/// If a PathDiagnosticEvent occurs in a different frame than the final +/// diagnostic the hints can be used to summarise the effect of the call. +class StackHintGenerator { +public: + virtual ~StackHintGenerator() = 0; + + /// \brief Construct the Diagnostic message for the given ExplodedNode. + virtual std::string getMessage(const ExplodedNode *N) = 0; +}; + +/// \brief Constructs a Stack hint for the given symbol. +/// +/// The class knows how to construct the stack hint message based on +/// traversing the CallExpr associated with the call and checking if the given +/// symbol is returned or is one of the arguments. +/// The hint can be customized by redefining 'getMessageForX()' methods. +class StackHintGeneratorForSymbol : public StackHintGenerator { +private: + SymbolRef Sym; + std::string Msg; + +public: + StackHintGeneratorForSymbol(SymbolRef S, StringRef M) : Sym(S), Msg(M) {} + virtual ~StackHintGeneratorForSymbol() {} + + /// \brief Search the call expression for the symbol Sym and dispatch the + /// 'getMessageForX()' methods to construct a specific message. + virtual std::string getMessage(const ExplodedNode *N); + + /// Prints the ordinal form of the given integer, + /// only valid for ValNo : ValNo > 0. + void printOrdinal(unsigned ValNo, llvm::raw_svector_ostream &Out); + + /// Produces the message of the following form: + /// 'Msg via Nth parameter' + virtual std::string getMessageForArg(const Expr *ArgE, unsigned ArgIndex); + virtual std::string getMessageForReturn(const CallExpr *CallExpr) { + return Msg + " returned"; + } + virtual std::string getMessageForSymbolNotFound() { + return Msg; + } +}; + class PathDiagnosticEventPiece : public PathDiagnosticSpotPiece { llvm::Optional IsPrunable; @@ -364,16 +412,14 @@ class PathDiagnosticEventPiece : public PathDiagnosticSpotPiece { /// supply a message that will be used to construct an extra hint on the /// returns from all the calls on the stack from this event to the final /// diagnostic. - /// TODO: This should be a callback that constructs a string given the - /// ExplodedNode, which would allow the checkers to refer to the expression. - std::string CallStackMessage; + llvm::OwningPtr CallStackHint; public: PathDiagnosticEventPiece(const PathDiagnosticLocation &pos, StringRef s, bool addPosRange = true, - StringRef callStackMsg = "") + StackHintGenerator *stackHint = 0) : PathDiagnosticSpotPiece(pos, s, Event, addPosRange), - CallStackMessage(callStackMsg) {} + CallStackHint(stackHint) {} ~PathDiagnosticEventPiece(); @@ -391,11 +437,16 @@ public: return IsPrunable.hasValue() ? IsPrunable.getValue() : false; } - StringRef getCallStackMessage() { - if (!CallStackMessage.empty()) - return CallStackMessage; - else - return StringRef(); + bool hasCallStackHint() { + return (CallStackHint != 0); + } + + /// Produce the hint for the given node. The node contains + /// information about the call for which the diagnostic can be generated. + StringRef getCallStackMessage(const ExplodedNode *N) { + if (CallStackHint) + return CallStackHint->getMessage(N); + return ""; } static inline bool classof(const PathDiagnosticPiece *P) { diff --git a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp index e071626eb6..2926fd5c04 100644 --- a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp @@ -243,6 +243,29 @@ private: const ExplodedNode *PrevN, BugReporterContext &BRC, BugReport &BR); + private: + class StackHintGeneratorForReallocationFailed + : public StackHintGeneratorForSymbol { + public: + StackHintGeneratorForReallocationFailed(SymbolRef S, StringRef M) + : StackHintGeneratorForSymbol(S, M) {} + + virtual std::string getMessageForArg(const Expr *ArgE, unsigned ArgIndex) { + SmallString<200> buf; + llvm::raw_svector_ostream os(buf); + + os << "; reallocation of "; + // Printed parameters start at 1, not 0. + printOrdinal(++ArgIndex, os); + os << " parameter failed"; + + return os.str(); + } + + virtual std::string getMessageForReturn(const CallExpr *CallExpr) { + return "; reallocation of returned value failed"; + } + }; }; }; } // end anonymous namespace @@ -1249,7 +1272,7 @@ MallocChecker::MallocBugVisitor::VisitNode(const ExplodedNode *N, const Stmt *S = 0; const char *Msg = 0; - const char *StackMsg = 0; + StackHintGeneratorForSymbol *StackHint = 0; // Retrieve the associated statement. ProgramPoint ProgLoc = N->getLocation(); @@ -1269,14 +1292,15 @@ MallocChecker::MallocBugVisitor::VisitNode(const ExplodedNode *N, if (Mode == Normal) { if (isAllocated(RS, RSPrev, S)) { Msg = "Memory is allocated"; - StackMsg = ", which allocated memory"; + StackHint = new StackHintGeneratorForSymbol(Sym, "; allocated memory"); } else if (isReleased(RS, RSPrev, S)) { Msg = "Memory is released"; - StackMsg = ", which released memory"; + StackHint = new StackHintGeneratorForSymbol(Sym, "; released memory"); } else if (isReallocFailedCheck(RS, RSPrev, S)) { Mode = ReallocationFailed; Msg = "Reallocation failed"; - StackMsg = ", where reallocation failed"; + StackHint = new StackHintGeneratorForReallocationFailed(Sym, + "; reallocation failed"); } // We are in a special mode if a reallocation failed later in the path. @@ -1296,18 +1320,18 @@ MallocChecker::MallocBugVisitor::VisitNode(const ExplodedNode *N, if (!(FunName.equals("realloc") || FunName.equals("reallocf"))) return 0; Msg = "Attempt to reallocate memory"; - StackMsg = ", which attempted to reallocate memory"; + StackHint = new StackHintGeneratorForSymbol(Sym, "; reallocated memory"); Mode = Normal; } if (!Msg) return 0; - assert(StackMsg); + assert(StackHint); // Generate the extra diagnostic. PathDiagnosticLocation Pos(S, BRC.getSourceManager(), N->getLocationContext()); - return new PathDiagnosticEventPiece(Pos, Msg, true, StackMsg); + return new PathDiagnosticEventPiece(Pos, Msg, true, StackHint); } diff --git a/lib/StaticAnalyzer/Core/BugReporter.cpp b/lib/StaticAnalyzer/Core/BugReporter.cpp index b59405bcd2..363a6dffee 100644 --- a/lib/StaticAnalyzer/Core/BugReporter.cpp +++ b/lib/StaticAnalyzer/Core/BugReporter.cpp @@ -380,22 +380,29 @@ PathDiagnosticBuilder::getEnclosingStmtLocation(const Stmt *S) { //===----------------------------------------------------------------------===// // "Minimal" path diagnostic generation algorithm. //===----------------------------------------------------------------------===// +typedef std::pair StackDiagPair; +typedef SmallVector StackDiagVector; + static void updateStackPiecesWithMessage(PathDiagnosticPiece *P, - llvm::SmallVector &CallStack) { + StackDiagVector &CallStack) { // If the piece contains a special message, add it to all the call // pieces on the active stack. if (PathDiagnosticEventPiece *ep = dyn_cast(P)) { - StringRef stackMsg = ep->getCallStackMessage(); - if (!stackMsg.empty()) - for (llvm::SmallVector::iterator - I = CallStack.begin(), E = CallStack.end(); I != E; ++I) + if (ep->hasCallStackHint()) + for (StackDiagVector::iterator I = CallStack.begin(), + E = CallStack.end(); I != E; ++I) { + PathDiagnosticCallPiece *CP = I->first; + const ExplodedNode *N = I->second; + StringRef stackMsg = ep->getCallStackMessage(N); + // The last message on the path to final bug is the most important // one. Since we traverse the path backwards, do not add the message // if one has been previously added. - if (!(*I)->hasCallStackMessage()) - (*I)->setCallStackMessage(stackMsg); + if (!CP->hasCallStackMessage()) + CP->setCallStackMessage(stackMsg); + } } } @@ -410,7 +417,7 @@ static void GenerateMinimalPathDiagnostic(PathDiagnostic& PD, const ExplodedNode *NextNode = N->pred_empty() ? NULL : *(N->pred_begin()); - llvm::SmallVector CallStack; + StackDiagVector CallStack; while (NextNode) { N = NextNode; @@ -424,7 +431,7 @@ static void GenerateMinimalPathDiagnostic(PathDiagnostic& PD, PathDiagnosticCallPiece::construct(N, *CE, SMgr); PD.getActivePath().push_front(C); PD.pushActivePath(&C->path); - CallStack.push_back(C); + CallStack.push_back(StackDiagPair(C, N)); continue; } @@ -446,7 +453,7 @@ static void GenerateMinimalPathDiagnostic(PathDiagnostic& PD, } C->setCallee(*CE, SMgr); if (!CallStack.empty()) { - assert(CallStack.back() == C); + assert(CallStack.back().first == C); CallStack.pop_back(); } continue; @@ -1047,7 +1054,7 @@ static void GenerateExtensivePathDiagnostic(PathDiagnostic& PD, const ExplodedNode *N) { EdgeBuilder EB(PD, PDB); const SourceManager& SM = PDB.getSourceManager(); - llvm::SmallVector CallStack; + StackDiagVector CallStack; const ExplodedNode *NextNode = N->pred_empty() ? NULL : *(N->pred_begin()); while (NextNode) { @@ -1068,7 +1075,7 @@ static void GenerateExtensivePathDiagnostic(PathDiagnostic& PD, PathDiagnosticCallPiece::construct(N, *CE, SM); PD.getActivePath().push_front(C); PD.pushActivePath(&C->path); - CallStack.push_back(C); + CallStack.push_back(StackDiagPair(C, N)); break; } @@ -1104,7 +1111,7 @@ static void GenerateExtensivePathDiagnostic(PathDiagnostic& PD, EB.addContext(CE->getCallExpr()); if (!CallStack.empty()) { - assert(CallStack.back() == C); + assert(CallStack.back().first == C); CallStack.pop_back(); } break; diff --git a/lib/StaticAnalyzer/Core/PathDiagnostic.cpp b/lib/StaticAnalyzer/Core/PathDiagnostic.cpp index cd08f9ceb7..2a2b9c615e 100644 --- a/lib/StaticAnalyzer/Core/PathDiagnostic.cpp +++ b/lib/StaticAnalyzer/Core/PathDiagnostic.cpp @@ -659,3 +659,94 @@ void PathDiagnostic::FullProfile(llvm::FoldingSetNodeID &ID) const { for (meta_iterator I = meta_begin(), E = meta_end(); I != E; ++I) ID.AddString(*I); } + +StackHintGenerator::~StackHintGenerator() {} + +std::string StackHintGeneratorForSymbol::getMessage(const ExplodedNode *N){ + ProgramPoint P = N->getLocation(); + const CallExit *CExit = dyn_cast(&P); + assert(CExit && "Stack Hints should be constructed at CallExit points."); + + const CallExpr *CE = dyn_cast_or_null(CExit->getStmt()); + if (!CE) + return ""; + + // Get the successor node to make sure the return statement is evaluated and + // CE is set to the result value. + N = *N->succ_begin(); + if (!N) + return getMessageForSymbolNotFound(); + + // Check if one of the parameters are set to the interesting symbol. + ProgramStateRef State = N->getState(); + const LocationContext *LCtx = N->getLocationContext(); + unsigned ArgIndex = 0; + for (CallExpr::const_arg_iterator I = CE->arg_begin(), + E = CE->arg_end(); I != E; ++I, ++ArgIndex){ + SVal SV = State->getSVal(*I, LCtx); + + // Check if the variable corresponding to the symbol is passed by value. + SymbolRef AS = SV.getAsLocSymbol(); + if (AS == Sym) { + return getMessageForArg(*I, ArgIndex); + } + + // Check if the parameter is a pointer to the symbol. + if (const loc::MemRegionVal *Reg = dyn_cast(&SV)) { + SVal PSV = State->getSVal(Reg->getRegion()); + SymbolRef AS = PSV.getAsLocSymbol(); + if (AS == Sym) { + return getMessageForArg(*I, ArgIndex); + } + } + } + + // Check if we are returning the interesting symbol. + SVal SV = State->getSVal(CE, LCtx); + SymbolRef RetSym = SV.getAsLocSymbol(); + if (RetSym == Sym) { + return getMessageForReturn(CE); + } + + return getMessageForSymbolNotFound(); +} + +/// TODO: This is copied from clang diagnostics. Maybe we could just move it to +/// some common place. (Same as HandleOrdinalModifier.) +void StackHintGeneratorForSymbol::printOrdinal(unsigned ValNo, + llvm::raw_svector_ostream &Out) { + assert(ValNo != 0 && "ValNo must be strictly positive!"); + + // We could use text forms for the first N ordinals, but the numeric + // forms are actually nicer in diagnostics because they stand out. + Out << ValNo; + + // It is critically important that we do this perfectly for + // user-written sequences with over 100 elements. + switch (ValNo % 100) { + case 11: + case 12: + case 13: + Out << "th"; return; + default: + switch (ValNo % 10) { + case 1: Out << "st"; return; + case 2: Out << "nd"; return; + case 3: Out << "rd"; return; + default: Out << "th"; return; + } + } +} + +std::string StackHintGeneratorForSymbol::getMessageForArg(const Expr *ArgE, + unsigned ArgIndex) { + SmallString<200> buf; + llvm::raw_svector_ostream os(buf); + + os << Msg << " via "; + // Printed parameters start at 1, not 0. + printOrdinal(++ArgIndex, os); + os << " parameter"; + + return os.str(); +} diff --git a/test/Analysis/malloc-plist.c b/test/Analysis/malloc-plist.c index f41c0c3a5b..d08ed07d18 100644 --- a/test/Analysis/malloc-plist.c +++ b/test/Analysis/malloc-plist.c @@ -47,6 +47,7 @@ void test_wrapper() { } // Test what happens when the same call frees and allocated memory. +// Also tests the stack hint for parameters, when they are passed directly or via pointer. void my_free(void *x) { free(x); } @@ -62,6 +63,30 @@ void *test_double_action_call() { return buf; } +// Test stack hint for 'reallocation failed'. +char *my_realloc(char *buf) { + char *tmp; + tmp = (char*)realloc(buf, 0x1000000); + if (!tmp) { + return tmp; + } + return tmp; +} +void reallocIntra() { + char *buf = (char *)malloc(100); + buf = my_realloc(buf); + free(buf); +} + +// Test stack hint when returning a result. +static char *malloc_wrapper_ret() { + return (char*)malloc(12); +} +void use_ret() { + char *v; + v = malloc_wrapper_ret(); +} + // CHECK: // CHECK: // CHECK: @@ -1104,9 +1129,9 @@ void *test_double_action_call() { // CHECK: // CHECK: depth1 // CHECK: extended_message -// CHECK: Returning from 'wrapper', which allocated memory +// CHECK: Returning from 'wrapper'; allocated memory returned // CHECK: message -// CHECK: Returning from 'wrapper', which allocated memory +// CHECK: Returning from 'wrapper'; allocated memory returned // CHECK: // CHECK: // CHECK: kindcontrol @@ -1178,12 +1203,12 @@ void *test_double_action_call() { // CHECK: start // CHECK: // CHECK: -// CHECK: line60 +// CHECK: line61 // CHECK: col5 // CHECK: file0 // CHECK: // CHECK: -// CHECK: line60 +// CHECK: line61 // CHECK: col5 // CHECK: file0 // CHECK: @@ -1191,12 +1216,12 @@ void *test_double_action_call() { // CHECK: end // CHECK: // CHECK: -// CHECK: line61 +// CHECK: line62 // CHECK: col5 // CHECK: file0 // CHECK: // CHECK: -// CHECK: line61 +// CHECK: line62 // CHECK: col5 // CHECK: file0 // CHECK: @@ -1208,7 +1233,7 @@ void *test_double_action_call() { // CHECK: kindevent // CHECK: location // CHECK: -// CHECK: line61 +// CHECK: line62 // CHECK: col5 // CHECK: file0 // CHECK: @@ -1216,12 +1241,12 @@ void *test_double_action_call() { // CHECK: // CHECK: // CHECK: -// CHECK: line61 +// CHECK: line62 // CHECK: col5 // CHECK: file0 // CHECK: // CHECK: -// CHECK: line61 +// CHECK: line62 // CHECK: col28 // CHECK: file0 // CHECK: @@ -1237,7 +1262,7 @@ void *test_double_action_call() { // CHECK: kindevent // CHECK: location // CHECK: -// CHECK: line53 +// CHECK: line54 // CHECK: col1 // CHECK: file0 // CHECK: @@ -1255,12 +1280,12 @@ void *test_double_action_call() { // CHECK: start // CHECK: // CHECK: -// CHECK: line53 +// CHECK: line54 // CHECK: col1 // CHECK: file0 // CHECK: // CHECK: -// CHECK: line53 +// CHECK: line54 // CHECK: col1 // CHECK: file0 // CHECK: @@ -1268,12 +1293,12 @@ void *test_double_action_call() { // CHECK: end // CHECK: // CHECK: -// CHECK: line54 +// CHECK: line55 // CHECK: col5 // CHECK: file0 // CHECK: // CHECK: -// CHECK: line54 +// CHECK: line55 // CHECK: col5 // CHECK: file0 // CHECK: @@ -1289,12 +1314,12 @@ void *test_double_action_call() { // CHECK: start // CHECK: // CHECK: -// CHECK: line54 +// CHECK: line55 // CHECK: col5 // CHECK: file0 // CHECK: // CHECK: -// CHECK: line54 +// CHECK: line55 // CHECK: col5 // CHECK: file0 // CHECK: @@ -1302,12 +1327,12 @@ void *test_double_action_call() { // CHECK: end // CHECK: // CHECK: -// CHECK: line54 +// CHECK: line55 // CHECK: col10 // CHECK: file0 // CHECK: // CHECK: -// CHECK: line54 +// CHECK: line55 // CHECK: col20 // CHECK: file0 // CHECK: @@ -1319,7 +1344,7 @@ void *test_double_action_call() { // CHECK: kindevent // CHECK: location // CHECK: -// CHECK: line54 +// CHECK: line55 // CHECK: col10 // CHECK: file0 // CHECK: @@ -1327,12 +1352,12 @@ void *test_double_action_call() { // CHECK: // CHECK: // CHECK: -// CHECK: line54 +// CHECK: line55 // CHECK: col10 // CHECK: file0 // CHECK: // CHECK: -// CHECK: line54 +// CHECK: line55 // CHECK: col20 // CHECK: file0 // CHECK: @@ -1352,12 +1377,12 @@ void *test_double_action_call() { // CHECK: start // CHECK: // CHECK: -// CHECK: line54 +// CHECK: line55 // CHECK: col10 // CHECK: file0 // CHECK: // CHECK: -// CHECK: line54 +// CHECK: line55 // CHECK: col20 // CHECK: file0 // CHECK: @@ -1365,12 +1390,12 @@ void *test_double_action_call() { // CHECK: end // CHECK: // CHECK: -// CHECK: line55 +// CHECK: line56 // CHECK: col5 // CHECK: file0 // CHECK: // CHECK: -// CHECK: line55 +// CHECK: line56 // CHECK: col5 // CHECK: file0 // CHECK: @@ -1386,12 +1411,12 @@ void *test_double_action_call() { // CHECK: start // CHECK: // CHECK: -// CHECK: line55 +// CHECK: line56 // CHECK: col5 // CHECK: file0 // CHECK: // CHECK: -// CHECK: line55 +// CHECK: line56 // CHECK: col5 // CHECK: file0 // CHECK: @@ -1399,12 +1424,12 @@ void *test_double_action_call() { // CHECK: end // CHECK: // CHECK: -// CHECK: line56 +// CHECK: line57 // CHECK: col7 // CHECK: file0 // CHECK: // CHECK: -// CHECK: line56 +// CHECK: line57 // CHECK: col7 // CHECK: file0 // CHECK: @@ -1416,7 +1441,7 @@ void *test_double_action_call() { // CHECK: kindevent // CHECK: location // CHECK: -// CHECK: line56 +// CHECK: line57 // CHECK: col7 // CHECK: file0 // CHECK: @@ -1424,12 +1449,12 @@ void *test_double_action_call() { // CHECK: // CHECK: // CHECK: -// CHECK: line56 +// CHECK: line57 // CHECK: col7 // CHECK: file0 // CHECK: // CHECK: -// CHECK: line56 +// CHECK: line57 // CHECK: col17 // CHECK: file0 // CHECK: @@ -1445,7 +1470,7 @@ void *test_double_action_call() { // CHECK: kindevent // CHECK: location // CHECK: -// CHECK: line50 +// CHECK: line51 // CHECK: col1 // CHECK: file0 // CHECK: @@ -1463,12 +1488,12 @@ void *test_double_action_call() { // CHECK: start // CHECK: // CHECK: -// CHECK: line50 +// CHECK: line51 // CHECK: col1 // CHECK: file0 // CHECK: // CHECK: -// CHECK: line50 +// CHECK: line51 // CHECK: col1 // CHECK: file0 // CHECK: @@ -1476,12 +1501,12 @@ void *test_double_action_call() { // CHECK: end // CHECK: // CHECK: -// CHECK: line51 +// CHECK: line52 // CHECK: col5 // CHECK: file0 // CHECK: // CHECK: -// CHECK: line51 +// CHECK: line52 // CHECK: col11 // CHECK: file0 // CHECK: @@ -1493,7 +1518,7 @@ void *test_double_action_call() { // CHECK: kindevent // CHECK: location // CHECK: -// CHECK: line51 +// CHECK: line52 // CHECK: col5 // CHECK: file0 // CHECK: @@ -1501,12 +1526,12 @@ void *test_double_action_call() { // CHECK: // CHECK: // CHECK: -// CHECK: line51 +// CHECK: line52 // CHECK: col5 // CHECK: file0 // CHECK: // CHECK: -// CHECK: line51 +// CHECK: line52 // CHECK: col11 // CHECK: file0 // CHECK: @@ -1522,7 +1547,7 @@ void *test_double_action_call() { // CHECK: kindevent // CHECK: location // CHECK: -// CHECK: line56 +// CHECK: line57 // CHECK: col7 // CHECK: file0 // CHECK: @@ -1530,12 +1555,12 @@ void *test_double_action_call() { // CHECK: // CHECK: // CHECK: -// CHECK: line56 +// CHECK: line57 // CHECK: col7 // CHECK: file0 // CHECK: // CHECK: -// CHECK: line56 +// CHECK: line57 // CHECK: col17 // CHECK: file0 // CHECK: @@ -1543,9 +1568,9 @@ void *test_double_action_call() { // CHECK: // CHECK: depth2 // CHECK: extended_message -// CHECK: Returning from 'my_free', which released memory +// CHECK: Returning from 'my_free'; released memory via 1st parameter // CHECK: message -// CHECK: Returning from 'my_free', which released memory +// CHECK: Returning from 'my_free'; released memory via 1st parameter // CHECK: // CHECK: // CHECK: kindcontrol @@ -1555,12 +1580,12 @@ void *test_double_action_call() { // CHECK: start // CHECK: // CHECK: -// CHECK: line56 +// CHECK: line57 // CHECK: col7 // CHECK: file0 // CHECK: // CHECK: -// CHECK: line56 +// CHECK: line57 // CHECK: col17 // CHECK: file0 // CHECK: @@ -1568,12 +1593,12 @@ void *test_double_action_call() { // CHECK: end // CHECK: // CHECK: -// CHECK: line57 +// CHECK: line58 // CHECK: col5 // CHECK: file0 // CHECK: // CHECK: -// CHECK: line57 +// CHECK: line58 // CHECK: col5 // CHECK: file0 // CHECK: @@ -1585,7 +1610,7 @@ void *test_double_action_call() { // CHECK: kindevent // CHECK: location // CHECK: -// CHECK: line61 +// CHECK: line62 // CHECK: col5 // CHECK: file0 // CHECK: @@ -1593,12 +1618,12 @@ void *test_double_action_call() { // CHECK: // CHECK: // CHECK: -// CHECK: line61 +// CHECK: line62 // CHECK: col5 // CHECK: file0 // CHECK: // CHECK: -// CHECK: line61 +// CHECK: line62 // CHECK: col28 // CHECK: file0 // CHECK: @@ -1606,9 +1631,9 @@ void *test_double_action_call() { // CHECK: // CHECK: depth1 // CHECK: extended_message -// CHECK: Returning from 'my_malloc_and_free', which released memory +// CHECK: Returning from 'my_malloc_and_free'; released memory via 1st parameter // CHECK: message -// CHECK: Returning from 'my_malloc_and_free', which released memory +// CHECK: Returning from 'my_malloc_and_free'; released memory via 1st parameter // CHECK: // CHECK: // CHECK: kindcontrol @@ -1618,12 +1643,12 @@ void *test_double_action_call() { // CHECK: start // CHECK: // CHECK: -// CHECK: line61 +// CHECK: line62 // CHECK: col5 // CHECK: file0 // CHECK: // CHECK: -// CHECK: line61 +// CHECK: line62 // CHECK: col28 // CHECK: file0 // CHECK: @@ -1631,12 +1656,12 @@ void *test_double_action_call() { // CHECK: end // CHECK: // CHECK: -// CHECK: line62 +// CHECK: line63 // CHECK: col5 // CHECK: file0 // CHECK: // CHECK: -// CHECK: line62 +// CHECK: line63 // CHECK: col14 // CHECK: file0 // CHECK: @@ -1648,7 +1673,7 @@ void *test_double_action_call() { // CHECK: kindevent // CHECK: location // CHECK: -// CHECK: line62 +// CHECK: line63 // CHECK: col5 // CHECK: file0 // CHECK: @@ -1656,12 +1681,12 @@ void *test_double_action_call() { // CHECK: // CHECK: // CHECK: -// CHECK: line62 +// CHECK: line63 // CHECK: col12 // CHECK: file0 // CHECK: // CHECK: -// CHECK: line62 +// CHECK: line63 // CHECK: col14 // CHECK: file0 // CHECK: @@ -1679,11 +1704,784 @@ void *test_double_action_call() { // CHECK: typeUse-after-free // CHECK: location // CHECK: -// CHECK: line62 +// CHECK: line63 // CHECK: col5 // CHECK: file0 // CHECK: // CHECK: +// CHECK: +// CHECK: path +// CHECK: +// CHECK: +// CHECK: kindcontrol +// CHECK: edges +// CHECK: +// CHECK: +// CHECK: start +// CHECK: +// CHECK: +// CHECK: line76 +// CHECK: col5 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: line76 +// CHECK: col5 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: end +// CHECK: +// CHECK: +// CHECK: line76 +// CHECK: col25 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: line76 +// CHECK: col35 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: +// CHECK: +// CHECK: +// CHECK: +// CHECK: kindevent +// CHECK: location +// CHECK: +// CHECK: line76 +// CHECK: col25 +// CHECK: file0 +// CHECK: +// CHECK: ranges +// CHECK: +// CHECK: +// CHECK: +// CHECK: line76 +// CHECK: col25 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: line76 +// CHECK: col35 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: +// CHECK: depth0 +// CHECK: extended_message +// CHECK: Memory is allocated +// CHECK: message +// CHECK: Memory is allocated +// CHECK: +// CHECK: +// CHECK: kindcontrol +// CHECK: edges +// CHECK: +// CHECK: +// CHECK: start +// CHECK: +// CHECK: +// CHECK: line76 +// CHECK: col25 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: line76 +// CHECK: col35 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: end +// CHECK: +// CHECK: +// CHECK: line77 +// CHECK: col11 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: line77 +// CHECK: col11 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: +// CHECK: +// CHECK: +// CHECK: +// CHECK: kindevent +// CHECK: location +// CHECK: +// CHECK: line77 +// CHECK: col11 +// CHECK: file0 +// CHECK: +// CHECK: ranges +// CHECK: +// CHECK: +// CHECK: +// CHECK: line77 +// CHECK: col11 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: line77 +// CHECK: col25 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: +// CHECK: depth0 +// CHECK: extended_message +// CHECK: Calling 'my_realloc' +// CHECK: message +// CHECK: Calling 'my_realloc' +// CHECK: +// CHECK: +// CHECK: kindevent +// CHECK: location +// CHECK: +// CHECK: line67 +// CHECK: col1 +// CHECK: file0 +// CHECK: +// CHECK: depth1 +// CHECK: extended_message +// CHECK: Entered call from 'reallocIntra' +// CHECK: message +// CHECK: Entered call from 'reallocIntra' +// CHECK: +// CHECK: +// CHECK: kindcontrol +// CHECK: edges +// CHECK: +// CHECK: +// CHECK: start +// CHECK: +// CHECK: +// CHECK: line67 +// CHECK: col1 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: line67 +// CHECK: col1 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: end +// CHECK: +// CHECK: +// CHECK: line68 +// CHECK: col5 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: line68 +// CHECK: col5 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: +// CHECK: +// CHECK: +// CHECK: +// CHECK: kindcontrol +// CHECK: edges +// CHECK: +// CHECK: +// CHECK: start +// CHECK: +// CHECK: +// CHECK: line68 +// CHECK: col5 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: line68 +// CHECK: col5 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: end +// CHECK: +// CHECK: +// CHECK: line69 +// CHECK: col5 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: line69 +// CHECK: col5 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: +// CHECK: +// CHECK: +// CHECK: +// CHECK: kindcontrol +// CHECK: edges +// CHECK: +// CHECK: +// CHECK: start +// CHECK: +// CHECK: +// CHECK: line69 +// CHECK: col5 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: line69 +// CHECK: col5 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: end +// CHECK: +// CHECK: +// CHECK: line69 +// CHECK: col18 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: line69 +// CHECK: col40 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: +// CHECK: +// CHECK: +// CHECK: +// CHECK: kindevent +// CHECK: location +// CHECK: +// CHECK: line69 +// CHECK: col18 +// CHECK: file0 +// CHECK: +// CHECK: ranges +// CHECK: +// CHECK: +// CHECK: +// CHECK: line69 +// CHECK: col18 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: line69 +// CHECK: col40 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: +// CHECK: depth1 +// CHECK: extended_message +// CHECK: Attempt to reallocate memory +// CHECK: message +// CHECK: Attempt to reallocate memory +// CHECK: +// CHECK: +// CHECK: kindcontrol +// CHECK: edges +// CHECK: +// CHECK: +// CHECK: start +// CHECK: +// CHECK: +// CHECK: line69 +// CHECK: col18 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: line69 +// CHECK: col40 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: end +// CHECK: +// CHECK: +// CHECK: line70 +// CHECK: col5 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: line70 +// CHECK: col6 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: +// CHECK: +// CHECK: +// CHECK: +// CHECK: kindevent +// CHECK: location +// CHECK: +// CHECK: line70 +// CHECK: col5 +// CHECK: file0 +// CHECK: +// CHECK: ranges +// CHECK: +// CHECK: +// CHECK: +// CHECK: line70 +// CHECK: col5 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: line70 +// CHECK: col6 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: +// CHECK: depth1 +// CHECK: extended_message +// CHECK: Reallocation failed +// CHECK: message +// CHECK: Reallocation failed +// CHECK: +// CHECK: +// CHECK: kindcontrol +// CHECK: edges +// CHECK: +// CHECK: +// CHECK: start +// CHECK: +// CHECK: +// CHECK: line70 +// CHECK: col5 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: line70 +// CHECK: col6 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: end +// CHECK: +// CHECK: +// CHECK: line70 +// CHECK: col9 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: line70 +// CHECK: col12 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: +// CHECK: +// CHECK: +// CHECK: +// CHECK: kindcontrol +// CHECK: edges +// CHECK: +// CHECK: +// CHECK: start +// CHECK: +// CHECK: +// CHECK: line70 +// CHECK: col9 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: line70 +// CHECK: col12 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: end +// CHECK: +// CHECK: +// CHECK: line71 +// CHECK: col9 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: line71 +// CHECK: col9 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: +// CHECK: +// CHECK: +// CHECK: +// CHECK: kindevent +// CHECK: location +// CHECK: +// CHECK: line77 +// CHECK: col11 +// CHECK: file0 +// CHECK: +// CHECK: ranges +// CHECK: +// CHECK: +// CHECK: +// CHECK: line77 +// CHECK: col11 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: line77 +// CHECK: col25 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: +// CHECK: depth1 +// CHECK: extended_message +// CHECK: Returning from 'my_realloc'; reallocation of 1st parameter failed +// CHECK: message +// CHECK: Returning from 'my_realloc'; reallocation of 1st parameter failed +// CHECK: +// CHECK: +// CHECK: kindcontrol +// CHECK: edges +// CHECK: +// CHECK: +// CHECK: start +// CHECK: +// CHECK: +// CHECK: line77 +// CHECK: col11 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: line77 +// CHECK: col25 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: end +// CHECK: +// CHECK: +// CHECK: line78 +// CHECK: col5 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: line78 +// CHECK: col13 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: +// CHECK: +// CHECK: +// CHECK: +// CHECK: kindevent +// CHECK: location +// CHECK: +// CHECK: line78 +// CHECK: col5 +// CHECK: file0 +// CHECK: +// CHECK: ranges +// CHECK: +// CHECK: +// CHECK: +// CHECK: line78 +// CHECK: col5 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: line78 +// CHECK: col13 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: +// CHECK: depth0 +// CHECK: extended_message +// CHECK: Memory is never released; potential memory leak +// CHECK: message +// CHECK: Memory is never released; potential memory leak +// CHECK: +// CHECK: +// CHECK: descriptionMemory is never released; potential memory leak +// CHECK: categoryMemory Error +// CHECK: typeMemory leak +// CHECK: location +// CHECK: +// CHECK: line78 +// CHECK: col5 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: +// CHECK: path +// CHECK: +// CHECK: +// CHECK: kindcontrol +// CHECK: edges +// CHECK: +// CHECK: +// CHECK: start +// CHECK: +// CHECK: +// CHECK: line86 +// CHECK: col5 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: line86 +// CHECK: col5 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: end +// CHECK: +// CHECK: +// CHECK: line87 +// CHECK: col9 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: line87 +// CHECK: col9 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: +// CHECK: +// CHECK: +// CHECK: +// CHECK: kindevent +// CHECK: location +// CHECK: +// CHECK: line87 +// CHECK: col9 +// CHECK: file0 +// CHECK: +// CHECK: ranges +// CHECK: +// CHECK: +// CHECK: +// CHECK: line87 +// CHECK: col9 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: line87 +// CHECK: col28 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: +// CHECK: depth0 +// CHECK: extended_message +// CHECK: Calling 'malloc_wrapper_ret' +// CHECK: message +// CHECK: Calling 'malloc_wrapper_ret' +// CHECK: +// CHECK: +// CHECK: kindevent +// CHECK: location +// CHECK: +// CHECK: line82 +// CHECK: col1 +// CHECK: file0 +// CHECK: +// CHECK: depth1 +// CHECK: extended_message +// CHECK: Entered call from 'use_ret' +// CHECK: message +// CHECK: Entered call from 'use_ret' +// CHECK: +// CHECK: +// CHECK: kindcontrol +// CHECK: edges +// CHECK: +// CHECK: +// CHECK: start +// CHECK: +// CHECK: +// CHECK: line82 +// CHECK: col1 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: line82 +// CHECK: col1 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: end +// CHECK: +// CHECK: +// CHECK: line83 +// CHECK: col5 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: line83 +// CHECK: col5 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: +// CHECK: +// CHECK: +// CHECK: +// CHECK: kindcontrol +// CHECK: edges +// CHECK: +// CHECK: +// CHECK: start +// CHECK: +// CHECK: +// CHECK: line83 +// CHECK: col5 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: line83 +// CHECK: col5 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: end +// CHECK: +// CHECK: +// CHECK: line83 +// CHECK: col19 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: line83 +// CHECK: col28 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: +// CHECK: +// CHECK: +// CHECK: +// CHECK: kindevent +// CHECK: location +// CHECK: +// CHECK: line83 +// CHECK: col19 +// CHECK: file0 +// CHECK: +// CHECK: ranges +// CHECK: +// CHECK: +// CHECK: +// CHECK: line83 +// CHECK: col19 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: line83 +// CHECK: col28 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: +// CHECK: depth1 +// CHECK: extended_message +// CHECK: Memory is allocated +// CHECK: message +// CHECK: Memory is allocated +// CHECK: +// CHECK: +// CHECK: kindevent +// CHECK: location +// CHECK: +// CHECK: line87 +// CHECK: col9 +// CHECK: file0 +// CHECK: +// CHECK: ranges +// CHECK: +// CHECK: +// CHECK: +// CHECK: line87 +// CHECK: col9 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: line87 +// CHECK: col28 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: +// CHECK: depth1 +// CHECK: extended_message +// CHECK: Returning from 'malloc_wrapper_ret'; allocated memory returned +// CHECK: message +// CHECK: Returning from 'malloc_wrapper_ret'; allocated memory returned +// CHECK: +// CHECK: +// CHECK: kindcontrol +// CHECK: edges +// CHECK: +// CHECK: +// CHECK: start +// CHECK: +// CHECK: +// CHECK: line87 +// CHECK: col9 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: line87 +// CHECK: col28 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: end +// CHECK: +// CHECK: +// CHECK: line88 +// CHECK: col1 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: line88 +// CHECK: col1 +// CHECK: file0 +// CHECK: +// CHECK: +// CHECK: +// CHECK: +// CHECK: +// CHECK: +// CHECK: kindevent +// CHECK: location +// CHECK: +// CHECK: line88 +// CHECK: col1 +// CHECK: file0 +// CHECK: +// CHECK: depth0 +// CHECK: extended_message +// CHECK: Memory is never released; potential memory leak +// CHECK: message +// CHECK: Memory is never released; potential memory leak +// CHECK: +// CHECK: +// CHECK: descriptionMemory is never released; potential memory leak +// CHECK: categoryMemory Error +// CHECK: typeMemory leak +// CHECK: location +// CHECK: +// CHECK: line88 +// CHECK: col1 +// CHECK: file0 +// CHECK: +// CHECK: // CHECK: // CHECK: // CHECK: -- 2.40.0