http://gcc.gnu.org/bugzilla/show_bug.cgi?id=46632
Summary: libjava: fortify catches memcpy overflow in parseAnnotationElement() for 64bit targets Product: gcc Version: 4.5.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: java AssignedTo: unassig...@gcc.gnu.org ReportedBy: vap...@gentoo.org when compiling gcc-4.5.1 with fortify enabled, we see the warnings: In file included from /usr/include/string.h:642:0, from libjava/java/lang/natClass.cc:15: In function ‘void* memcpy(void*, const void*, size_t)’, inlined from ‘java::lang::Object* parseAnnotationElement(java::lang::Class*, _Jv_Constants*, unsigned char*&, unsigned char*)’ at libjava/java/lang/natClass.cc:1168:60: /usr/include/bits/string3.h:52:71: warning: call to void* __builtin___memcpy_chk(void*, const void*, long unsigned int, long unsigned int) will always overflow destination buffer In function ‘void* memcpy(void*, const void*, size_t)’, inlined from ‘java::lang::Object* parseAnnotationElement(java::lang::Class*, _Jv_Constants*, unsigned char*&, unsigned char*)’ at libjava/java/lang/natClass.cc:1184:60: /usr/include/bits/string3.h:52:71: warning: call to void* __builtin___memcpy_chk(void*, const void*, long unsigned int, long unsigned int) will always overflow destination buffer if we look at the code in question: ... case 'D': { int cindex = read_u2 (bytes, last); check_constant (pool, cindex, JV_CONSTANT_Double); _Jv_word2 word; memcpy (&word, &pool->data[cindex], 2 * sizeof (_Jv_word)); result = Double::valueOf (word.d); } break; ... case 'J': { int cindex = read_u2 (bytes, last); check_constant (pool, cindex, JV_CONSTANT_Long); _Jv_word2 word; memcpy (&word, &pool->data[cindex], 2 * sizeof (_Jv_word)); result = Long::valueOf (word.l); } break; ... while it seems like _Jv_word2 would always be twice the size of _Jv_word, the libjava/include/jvm.h header implies otherwise: ... union _Jv_word { jobject o; jint i; // Also stores smaller integral types. jfloat f; jint ia[1]; // Half of _Jv_word2. void* p; #if SIZEOF_VOID_P == 8 // We can safely put a long or a double in here without increasing // the size of _Jv_Word; we take advantage of this in the interpreter. jlong l; jdouble d; #endif jclass clazz; jstring string; struct _Jv_Field *field; struct _Jv_Utf8Const *utf8; struct _Jv_ResolvedMethod *rmethod; }; union _Jv_word2 { jint ia[2]; jlong l; jdouble d; }; ... on a 32bit host, the _Jv_word2 probably is twice the size of _Jv_word (see the "jint ia[...]" lines). but on 64bit hosts, both unions include a single jlong/jdouble entry which means they're probably both 8 bytes. so the memcpy() in libjava overwrites 8 random bytes on the stack.