This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug other/50610] New: G++ 4.4.3: Incorrect code at -O2 (-fwrapv, SafeInt, c++ templates, template class files)
- From: "noloader at gmail dot com" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: Tue, 04 Oct 2011 04:01:54 +0000
- Subject: [Bug other/50610] New: G++ 4.4.3: Incorrect code at -O2 (-fwrapv, SafeInt, c++ templates, template class files)
- Auto-submitted: auto-generated
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=50610
Bug #: 50610
Summary: G++ 4.4.3: Incorrect code at -O2 (-fwrapv, SafeInt,
c++ templates, template class files)
Classification: Unclassified
Product: gcc
Version: 4.4.3
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: other
AssignedTo: unassigned@gcc.gnu.org
ReportedBy: noloader@gmail.com
Created attachment 25407
--> http://gcc.gnu.org/bugzilla/attachment.cgi?id=25407
Test case for bad code generation at -O2
Attached is a test program which uses a secure vector. The secure vector 'has
a' standard vector, and attempts to do a few extra things to help ensure safe
use (such as check for pointer wrap and zeroization). In addition, the secure
vector uses LeBlanc's SafeInt class to check for wraps and overflows. (SafeInt
uses unsigned, so no undefined behavior should be present).
The test program incorrectly rejects a valid input:
$ g++ -g -O2 -fwrapv -I. TestMain.cpp SecureArray.cpp -o TestMain.exe
$ ./TestMain.exe
Array pointer wrap
$
TestMain is as follows:
try
{
const int arr[] = { 1, 1, 1, 1 };
SecureIntArray vv(arr, COUNTOF(arr));
assert(vv.size() == 4);
}
catch(const std::exception& ex)
{
cerr << ex.what() << endl;
}
The SecureIntArray ctor calls into a helper function:
template <typename T>
typename SecureArray<T>::SecureVector*
SecureArray<T>::create_secure_array(const T* ptr, size_t cnt)
{
try
{
const size_t base = (size_t)ptr;
SafeInt<size_t> si(cnt);
si *= sizeof(T);
si += base;
}
catch(const SafeIntException&)
{
throw InvalidArgumentException("Array pointer wrap");
}
return new SecureVector(ptr /*first*/, ptr+cnt /*last*/);
}
*If* I manually check for overflow (ie, no SafeInt use), I get expected
results:
$ g++ -g -O2 -DSECURE_ARRAY_NO_SAFE_INT=1 -I. TestMain.cpp SecureArray.cpp -o
TestMain.exe
$ ./TestMain.exe
$
Defining SECURE_ARRAY_NO_SAFE_INT uses the following rather than SafeInt
objects:
const size_t b = (size_t)ptr;
size_t p = cnt * sizeof(T) + b;
if(!(p >= b))
throw InvalidArgumentException("Array pointer wrap");
Finally, the issue is not present on other versions of GCC. Other versions
include 4.5 from F14 and 4.6 from F15.
I was not able to reduce the test program to something smaller (though I
tried). For example, I know the following will not help the problem: removing
namespaces, removing throws, removing explicit template instantiations, moving
bodies into the header, and a few other items.
I do know that removing everything except the ctor, size(), max_size(), and
operator[] will fix it, but it does not help with a minimum test case.