[cfe-commits] unix.Malloc static checker improvement: memory.LeakPtrValChanged
Jordan Rose
jordan_rose at apple.com
Fri Jan 18 19:02:45 PST 2013
(see previous e-mail, "Re: Add PointerEscapeKind to checkPointerEscape callback")
I'd definitely like to see this improvement to MallocChecker! Let's see...
+
+ const MemRegion *Rbase = R->getBaseRegion();
- const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R);
+ const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(Rbase);
I would just collapse these into one line. More importantly, I think you should rename SR and possibly Sym to indicate that they're the base region/symbol, which isn't the same as the region actually passed to free.
+ // Check if the memory location being freed is the actual location
+ // allocated, or an offset.
+ RegionOffset offset = R->getAsOffset();
LLVM style guide is Germanic; all nouns are capitalized, even local variables.
+ if ( RS && RS->isAllocated() &&
Conventionally we have no space after the open paren for an 'if'.
+ offset.isValid() &&
+ offset.hasSymbolicOffset() == false &&
Conventionally written "!offset.hasSymbolicOffset()"
+ // Get the offset into the memory region before
+ // getting the super region, as retrieving the
+ // super region will ignore the offset.
+ RegionOffset offset = MR->getAsOffset();
Capital letter, again, but...
+
+ if ( offset.isValid()
+ && !offset.hasSymbolicOffset()
+ && offset.getOffset() != 0) {
+ os << "; the memory location passed is an offset of an allocated location";
+ }
+
...this test is not correct; it will fire for free(&local[1]). Given that the message isn't great either, and that you've already established what kind of value is being freed, I think you should just make a new helper function to report the error, ReportOffsetFree or something. Then you can make a nicer error message, like "Argument to free() is an offset of an allocation". (I don't think this message is perfect either -- it doesn't mention malloc(), "an offset" isn't really the correct term -- but at least it's more concise.)
Also, please put the && at the end of the line, not the start.
And while you're in there...
while (const ElementRegion *ER = dyn_cast<ElementRegion>(MR))
MR = ER->getSuperRegion();
...this should probably be replaced by either MR->getBaseRegion(), so that we strip off struct field layers as well, or MR->StripCasts(), so that we don't say that '&x[1]' is the address of 'x'.
Okay, I guess you're not in there anymore. I'll file a bug.
+void freeOffsetPointerPassedToFunction()
+{
+ int *p = malloc(sizeof(int)*2);
+ p[1] = 0;
+ p += 1;
+ myfooint(*p); // not passing the pointer, only a value pointed by pointer
+ free(p); // expected-warning {{Argument to free() is not memory allocated by malloc(); the memory location passed is an offset of an allocated location}}
+}
A better test would be to pass 'p' as a const pointer, which means the contents of the region get invalidated but 'p' itself will not.
Okay, I think that's it! Thanks, Branden.
Jordan
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20130118/32a7d606/attachment.html>
More information about the cfe-commits
mailing list