[cfe-commits] unix.Malloc static checker improvement: memory.LeakPtrValChanged
Anna Zaks
ganna at apple.com
Fri Jan 18 19:07:25 PST 2013
On Jan 18, 2013, at 7:02 PM, Jordan Rose <jordan_rose at apple.com> wrote:
> (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'.
>
In one of the later patches Branden does replace the loop with MR = MR->getBaseRegion(). I think he submitted it separately.
Branden, can you send us just the final 2 patches?
Thanks!
Anna.
> 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/9ff59e39/attachment.html>
More information about the cfe-commits
mailing list