[PATCH][Review request] unix.Malloc checker improvement: +handling new/delete, +memory.MismatchedFree, +memory.MismatchedDelete, +improved display names for allocators/deallocators
Anton Yartsev
anton.yartsev at gmail.com
Wed Mar 27 05:32:41 PDT 2013
On 27.03.2013 5:23, Jordan Rose wrote:
>
> On Mar 26, 2013, at 17:10 , Anton Yartsev <anton.yartsev at gmail.com
> <mailto:anton.yartsev at gmail.com>> wrote:
>
>> On 25.03.2013 21:39, Anna Zaks wrote:
>>> On Mar 25, 2013, at 9:30 AM, Jordan Rose <jordan_rose at apple.com
>>> <mailto:jordan_rose at apple.com>> wrote:
>>>
>>>>
>>>> On Mar 25, 2013, at 8:01 , Anton Yartsev <anton.yartsev at gmail.com
>>>> <mailto:anton.yartsev at gmail.com>> wrote:
>>>>
>>>>> Committed as r177849
>>>>>
>>>>> Manage to find several random real bugs (report-843813.html,
>>>>> report-230257.html, recursive case in report-727931.html), but for
>>>>> now it is hard to detect real bugs among tons of false-positives.
>>>>>
>>>>> There are two types of false-positives that form the majority of
>>>>> reports:
>>>>> 1) Illustrated by the following test (added similar test to
>>>>> NewDelete-checker-test.mm):
>>>>> int *global;
>>>>> void testMemIsOnHeap() {
>>>>> int *p = new int; // FIXME: currently not heap allocated!
>>>>> if (global != p) // evaluates to UnknownVal() rather then 'true'
>>>>> global = p;
>>>>> } // report false-positive leak
>>>>>
>>>>> As I understand the problem is that currently a memory region for
>>>>> 'new' is not a heap region and this lead to false-positives like
>>>>> report-863595.html and others. (e.g. that causes 'global != p'
>>>>> evaluate to UnknownVal() rather then 'true' (logic of
>>>>> SimpleSValBuilder::evalBinOpLL))
>>>>>
>>>>> Attached is the proposed patch that fixes these issues.
>>>>
>>>> There are two reasons I didn't use getConjuredHeapSymbol when I
>>>> originally put in this code:
>>>> (1) It handles all CXXNewExprs, even if the allocator is not one of
>>>> the global ones.
>>>> (2) Heap symbols weren't used yet (Anna added them later for
>>>> MallocChecker).
>>>>
>>>> Obviously #2 is bogus now. #1 worries me a bit because it requires
>>>> duplicating some of the checks you just added to MallocChecker.
>>>>
>>>> In the long run, the design would be to get the appropriate memory
>>>> from the allocator call, and we have PR12014's restructuring of the
>>>> CFG blocking that. I'm not sure if we'd then move the heap symbol
>>>> logic into a checker, or if it would still stay in Core.
>>>>
>>>> In the short term, I guess the best idea is to duplicate some of
>>>> the checks (or refactor them to a helper function
>>>> somewhere...though probably/not/ into AST) and then conjure a heap
>>>> symbol if we know we can.
>> Failed to find any suitable place other then AST :) Eventually
>> noticed, that actually only a single check should be duplicated.
>> Decided to leave the wide comment added when I tried to find the
>> proper place for isStandardNewDelete().
>> New fix attached.
>
> I don't think this is safe -- what if the user has custom libraries in
> their system include path? We can really only assume heap allocation
> for the implicit case and for ::operator new(std::size_t) and
> ::operator new(std::size_t, std::nothrow_t).
>
> However, I think just checking "global namespace" might be a good
> enough approximation. If the user overrides one of the default
> allocators, it ought to behave like the real one, so we'd only be
> messing up if they had a new global "allocate from pool" or something.
>
> Also, in theory we'd have to check placement new, but that's handled
> specially below anyway.
Updated the logic, improved test coverage.
Evolved one more problem to solve: if overloaded standard operator new
is defined and is called as a function, then it is not recognized as
overloaded operator for some reason. Tests testOpNewArray() and
testOpNew() in NewDelete-custom.cpp cover these issue.
>
>
>>
>> Evolved another issue, that I first thought to be related to case 1),
>> here is the minimal test:
>> struct S {
>> int **p;
>> };
>> void testOk(S &s) {
>> new(s.p) (int*)(new int); // false-positive leak
>> }
>> void testLeak() {
>> S s;
>> new(s.p) (int*)(new int); // real leak
>> }
>
> Ha. I would guess this is because VisitCXXNewExpr calls directly
> to bindLoc instead of going through evalBind, and so we miss the
> pointer-escape-on-bind callback. I can reproduce this with the
> existing MallocChecker by changing the inner 'new' to a malloc.
>
>> Haven't addressed these yet. The leak is reported for cases of the
>> form 'small_vector.push_back(new Something)', where push_back() uses
>> placement new to store data.
>
> I'll get to this case soon if you don't.
>
> Jordan
--
Anton
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20130327/cfa89f6b/attachment.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: FixForCase1.patch
Type: text/x-diff
Size: 10575 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20130327/cfa89f6b/attachment.patch>
More information about the cfe-commits
mailing list