The problem is an interaction between the uncommon (to put it mildly) way zsnes calls memcpy to restore its global state from the "regsbackup" buffer, and _FORTIFY_SOURCE:
gcc -ggdb3 -pipe -I. -I/usr/local/include -I/usr/include -D__UNIXSDL__ -I/usr/include/SDL -D_GNU_SOURCE=1 -D_REENTRANT -DNO_DEBUGGER -D__LIBAO__ -D__OPENGL__ -march=i486 -O3 -fomit-frame-pointer -fprefetch-loop-arrays -fforce-addr -s -D__RELEASE__ -o initc.o -c initc.c
[...]
In function ‘memcpy’,
inlined from ‘powercycle’ at initc.c:2624:
/usr/include/bits/string3.h:52: warning: call to __builtin___memcpy_chk will always overflow destination buffer
The reason this strange memcpy call will always work correctly is that the storage for sndrot and the rest of the state variables is allocated in assembly (cpu/regs.inc, included from cpu/table.asm), in a way which guarantees that all the correct variables will be sequential in memory, with no padding (sndrot is just the first variable on that block). However, gcc cannot know that; it sees instead an attempt to write 3019 bytes to a single byte-sized variable, which will obviously overflow (and, in fact, overflowing is precisely the desired behaviour!).
The easiest way to fix this is to disable the extra security checks (via -D_FORTIFY_SOURCE=0). There might be other places which use that unusual "design pattern", so simply fixing that memcpy call might not be enough.
The problem is an interaction between the uncommon (to put it mildly) way zsnes calls memcpy to restore its global state from the "regsbackup" buffer, and _FORTIFY_SOURCE:
gcc -ggdb3 -pipe -I. -I/usr/ local/include -I/usr/include -D__UNIXSDL__ -I/usr/include/SDL -D_GNU_SOURCE=1 -D_REENTRANT -DNO_DEBUGGER -D__LIBAO__ -D__OPENGL__ -march=i486 -O3 -fomit- frame-pointer -fprefetch- loop-arrays -fforce-addr -s -D__RELEASE__ -o initc.o -c initc.c bits/string3. h:52: warning: call to __builtin_ __memcpy_ chk will always overflow destination buffer
[...]
In function ‘memcpy’,
inlined from ‘powercycle’ at initc.c:2624:
/usr/include/
The corresponding block of code is:
sramsavedis = 0;
memcpy(&sndrot, regsbackup, 3019);
And the declaration for the relevant variables, from the same file:
extern unsigned char NextLineCache, sramsavedis, sndrot, regsbackup[3019];
The reason this strange memcpy call will always work correctly is that the storage for sndrot and the rest of the state variables is allocated in assembly (cpu/regs.inc, included from cpu/table.asm), in a way which guarantees that all the correct variables will be sequential in memory, with no padding (sndrot is just the first variable on that block). However, gcc cannot know that; it sees instead an attempt to write 3019 bytes to a single byte-sized variable, which will obviously overflow (and, in fact, overflowing is precisely the desired behaviour!).
The easiest way to fix this is to disable the extra security checks (via -D_FORTIFY_ SOURCE= 0). There might be other places which use that unusual "design pattern", so simply fixing that memcpy call might not be enough.