[LLVMbugs] [Bug 21326] New: False position CERT MEM04 zero-length allocation error

bugzilla-daemon at llvm.org bugzilla-daemon at llvm.org
Tue Oct 21 10:02:04 PDT 2014


http://llvm.org/bugs/show_bug.cgi?id=21326

            Bug ID: 21326
           Summary: False position CERT MEM04 zero-length allocation error
           Product: clang
           Version: trunk
          Hardware: PC
                OS: Linux
            Status: NEW
          Severity: normal
          Priority: P
         Component: Static Analyzer
          Assignee: kremenek at apple.com
          Reporter: stevemac321 at live.com
                CC: llvmbugs at cs.uiuc.edu
    Classification: Unclassified

in <locale> __double_or_nothing line 2974 calls realloc; scan-build reports
that __new_cap can return zero which triggers the error, which seems correct
based on N1225 section on MEM04, collaborated with C99 N1570 clause 7.22.3, so
I opened a bug against libc++, but Marshall pulled up clause 3.7.4.1 from C++
standard N3797.

So here is the bug as I entered it, with Marshall's comment following.


>From N1225 (CERT)
"If the value of nsize in this example is 0, the standard allows the option of
either returning a null pointer or returning a pointer to an invalid (e.g.,
zero-length) object. In cases where the realloc() function frees the memory but
returns a null pointer, execution of the code in this example results in a
double free."

See N1570 (C99) 7.22.3 for collaboration:
If the space cannot be allocated, a null pointer is returned. If the size of
the space requested is zero, the behavior is implementation-defined: either a
null pointer is returned, or the behavior is as if the size were some nonzero
value, except that the returned pointer shall not be used to access an object.

Here is a proposed fix, although it might be naive because it assumes that
__new_cap is never intended to have a zero value.  

    _Tp* __t = nullptr;
    if(__new_cap != 0) // just add this check
        __t = (_Tp*)realloc(__owns ? __b.get() : 0, __new_cap);
    if (__t == 0)
        __throw_bad_alloc();

I applied this fix locally with a freshly synced libcxx.  There is a locale.cpp
source file, so I rebuilt the library with the patch.

I am on Ubuntu 14.4 x64
clang version 3.6.0 (trunk 217475)
Target: x86_64-unknown-linux-gnu
Thread model: posix


Let me know if you have other questions
Steve MacKenzie
stevemac321 at live.com
[reply] [-] Comment 1 Marshall Clow (home) 2014-10-21 11:34:48 CDT
The C++ standard explicitly allows zero-sized allocations
(Quoting from N3937, but it's the same in C++03 and C++11)

See 3.7.4.1/2:

Even if the size of the space requested is zero, the request can fail. If the
request succeeds, the value returned shall be a non-null pointer value (4.10)
p0 different from any previously returned value p1, unless that value p1 was
subsequently passed to an operator delete. The effect of indirecting through a
pointer returned as a request for zero size is undefined. (36)

[ bottom of page ]
36) The intent is to have operator new() implementable by calling std::malloc()
or std::calloc(), so the rules are sub-stantially the same. C++ differs from C
in requiring a zero request to return a non-null pointer.


Note: I'd be happy if you were to open a bug against scan-build for this issue
:-)

-- 
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20141021/2b855498/attachment.html>


More information about the llvm-bugs mailing list