Saturday, 31 May 2014

Please leave my source alone! bug in gcc - yes - a real one!

After adding hyperlink detection to my terminal emulator, I started seeing
strange problems in fcterm. fcterm is the terminal emulator - it has many features,
and works well with 'cr' - the character mode version of CRiSP.

I added hyperlink detection the other day, because I was bored. (I need
to implement hyperlink clicking, next).

I was having problems with my Ubuntu 14.04 - the cpus had been spinning for
many days due to issues with khubd kernel process. After the reboot, I was
running the new fcterm. But ALT key processing was broken. Weird.

After investigation, it turns out that gcc wants to convert strcpy() calls
into stpcpy() calls. Ok, that may be fair.

Heres the source code:

strcpy(rp, keymapping[k].k_value);

Heres the assembler:

.loc 1 1918 0
movq %r15, %rsi
movq %r12, %rdi
call stpcpy

Why is it converting strcpy to stpcpy ? Because its trying to be clever. stpcpy is like strcpy,
but returns the end of the copied string, not the start.

Unfortunately, this version of glibc seems to be broken. strcpy and stpcpy - at best, will do
a single strlen() over the src argument. Heres the disassembly.

disass stpcpy
Dump of assembler code for function stpcpy:
0x0000000000427150 <+0>: push %r12
0x0000000000427152 <+2>: mov %rsi,%r12
0x0000000000427155 <+5>: push %rbp
0x0000000000427156 <+6>: mov %rdi,%rbp
0x0000000000427159 <+9>: mov %rsi,%rdi
0x000000000042715c <+12>: push %rbx
0x000000000042715d <+13>: callq 0x404ff0 <strlen@plt>
0x0000000000427162 <+18>: mov %rbp,%rdi
0x0000000000427165 <+21>: mov %rax,%rbx
0x0000000000427168 <+24>: callq 0x404ff0 <strlen@plt>
0x000000000042716d <+29>: lea 0x1(%rbx),%edx
0x0000000000427170 <+32>: add %rax,%rbp
0x0000000000427173 <+35>: mov %r12,%rsi
0x0000000000427176 <+38>: mov %rbp,%rdi
0x0000000000427179 <+41>: movslq %ebx,%rbx
0x000000000042717c <+44>: movslq %edx,%rdx
0x000000000042717f <+47>: callq 0x405440 <memcpy@plt>
0x0000000000427184 <+52>: lea 0x0(%rbp,%rbx,1),%rax
0x0000000000427189 <+57>: pop %rbx
0x000000000042718a <+58>: pop %rbp
0x000000000042718b <+59>: pop %r12
0x000000000042718d <+61>: retq
End of assembler dump.

See the two calls to strlen? I believe that to be the problem. Now I need to stop strcpy being converted
to stpcpy (which is not easy - there is a gcc compiler option to do this, but now I would have to sprinkle
this everywhere - for all build tools). Worse, I now know there is a rogue stpcpy on other peoples systems,
so CRiSP could be affected if they download my binaries.

I havent suffered a compiler bug in nearly 20y - exactly because my coding style and idioms is trained
to avoid complex stuff, and the compilers have become more reliable. But now, that seems to be at an

Post created by CRiSP v11.0.32a-b6738

No comments:

Post a Comment