[Bug tree-optimization/94335] New: False positive -Wstringop-overflow warning with -O2
romain.geissler at amadeus dot com
gcc-bugzilla@gcc.gnu.org
Wed Mar 25 22:35:38 GMT 2020
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94335
Bug ID: 94335
Summary: False positive -Wstringop-overflow warning with -O2
Product: gcc
Version: 10.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: tree-optimization
Assignee: unassigned at gcc dot gnu.org
Reporter: romain.geissler at amadeus dot com
Target Milestone: ---
Hi,
The following code emits a false positive -Wstringop-overflow warning with gcc
trunk with -O2 and -O3.
It's reduced manually from a much more complex scenario, where we try to define
an iterator that can be stored in shared memory, thus referencing object
through relative addresses rather than absolute addresses. In the warning of
this scenario, I don't see how we can access offset -424242 as the initial
pointed address is never nullptr.
Note: gcc 8/9 do not emit such warning.
#include <iterator>
#include <memory>
#include <cassert>
#include <limits>
#include <cstring>
template <class T>
struct relative_address_iterator {
typedef T value;
typedef T *pointer;
typedef const T *const_pointer;
typedef T &reference;
typedef const T &const_reference;
typedef T value_type;
typedef ptrdiff_t difference_type;
typedef std::forward_iterator_tag iterator_category;
off_t d;
static constexpr off_t kEmptyPointer = std::numeric_limits<off_t>::min();
/** Constructs the object from a pointer.
*/
relative_address_iterator(pointer t)
{
if (t)
{
d = (char *)t - (char *)this;
}
else
{
d = kEmptyPointer;
}
}
/** Copy constructor.
*/
relative_address_iterator(const relative_address_iterator &r)
{
if (r.d != kEmptyPointer)
{
d = (char *)&r - (char *)this + r.d;
}
else
{
// Normally this should not happen in this example, but gcc thinks
it does,
// as the error message references the special value -424242.
// d = kEmptyPointer;
d = -424242;
}
}
/** Initializes the pointee with the given value.
*/
void setVal(const_reference value) { *(pointer)((char *)this + d) = value;
}
/** Dereferences the object.
*/
operator pointer()
{
if (d == kEmptyPointer) return nullptr;
return ((pointer)((char *)this + d));
}
/** Preincrement operator.
*/
relative_address_iterator &operator++()
{
d += sizeof(value);
return (*this);
}
};
void f()
{
char* aDummyBuffer = static_cast<char*>(malloc(10));
memset(aDummyBuffer, 10, 0);
relative_address_iterator<char> it(aDummyBuffer);
relative_address_iterator<char> itCopy(it);
itCopy.setVal('A');
char* aDummySource = static_cast<char*>(malloc(10));
memset(aDummySource, 10, 0);
std::copy(relative_address_iterator<char>(aDummySource),
relative_address_iterator<char>(aDummySource + 5),
it);
}
int main()
{
f();
}
In member function 'void
relative_address_iterator<T>::setVal(relative_address_iterator<T>::const_reference)
[with T = char]',
inlined from 'void f()' at <source>:82:18:
<source>:56:71: warning: writing 1 byte into a region of size 0
[-Wstringop-overflow=]
56 | void setVal(const_reference value) { *(pointer)((char *)this + d) =
value; }
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~
<source>: In function 'void f()':
<source>:80:37: note: at offset -424242 to object 'itCopy' with size 8 declared
here
80 | relative_address_iterator<char> itCopy(it);
| ^~~~~~
Compiler returned: 0
Cheers,
Romain
More information about the Gcc-bugs
mailing list