0

I have an executable that is segfaulting in release but not in debug. I assume it's a wrong call to a printf-family function.

When running i get this:

*** buffer overflow detected ***: ./mybin terminated
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x777f5)[0x7f3a8914d7f5]
/lib/x86_64-linux-gnu/libc.so.6(__fortify_fail+0x5c)[0x7f3a891ef21c]
/lib/x86_64-linux-gnu/libc.so.6(+0x117220)[0x7f3a891ed220]
/lib/x86_64-linux-gnu/libc.so.6(+0x116789)[0x7f3a891ec789]
/lib/x86_64-linux-gnu/libc.so.6(_IO_default_xsputn+0x80)[0x7f3a891516c0]
/lib/x86_64-linux-gnu/libc.so.6(_IO_vfprintf+0xc90)[0x7f3a89123e10]
/lib/x86_64-linux-gnu/libc.so.6(__vsprintf_chk+0x84)[0x7f3a891ec814]
/lib/x86_64-linux-gnu/libc.so.6(__sprintf_chk+0x7d)[0x7f3a891ec76d]
./mybin[0x58b50e]
./mybin(main+0x2f3b)[0x41cfab]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0)[0x7f3a890f6840]
./mybin[0x421969]
======= Memory map: ========
...
7f3a8cd2e000-7f3a8cd34000 rw-p 00000000 00:00 0 Aborted (core dumped)

Running it in gdb yields these last lines:

#8  0x00007ffff3aa7814 in ___vsprintf_chk (s=0x7fffffffaee0 "Some Text - \377\377\177", flags=1, slen=20, format=0x894098 "Some Text - %d", 
    args=args@entry=0x7fffffffad68) at vsprintf_chk.c:82
#9  0x00007ffff3aa776d in ___sprintf_chk (s=<optimized out>, flags=<optimized out>, slen=<optimized out>, format=<optimized out>) at sprintf_chk.c:31
#10 0x000000000058b50e in ?? ()
#11 0x000000000041cfab in main ()

The "Some Text - %d" comes from:

char aCharArr[20];
sprintf(aCharArr, "Some text - %d", anInt);

While it could do with a memset and snprintf, i've never had issues with these lines before. The int is always one digit.

I was unable to find that 0x58b50e using nm -CD. How else can i more or less pinpoint this (besides going back the commit tree as i'm doing atm and filling the program with printfs)?

vesperto
  • 804
  • 1
  • 6
  • 26

1 Answers1

1

Well, as it turns out, the original text (not "Some text") took 19 chars plus the %d, which is "always" one digit. Even so, that's 20 chars in a char aCharArr[20], producing a char array that is not \0-terminated.

Increasing the size of aCharArr (to the next multiple of 8 but that's just me) fixed it and using snprintf instead gave me peace of mind.

char aCharArr[24]; 
memset(aCharArr, '\0', sizeof(aCharArr));
sprintf(aCharArr, "Actual str orig len%d", anInt);

Compiling in debug with -O2 as is used in release was also helpful, although the available information was enough.

vesperto
  • 804
  • 1
  • 6
  • 26
  • 1
    Compiling with `-fsanitize=address -fsanitize=undefined -g` would be considerably educational if you're using either gcc or clang. – WhozCraig Feb 10 '22 at 10:30
  • 1
    [`snprintf`](https://en.cppreference.com/w/c/io/fprintf) might avoid that issue too. – Jarod42 Feb 10 '22 at 10:37
  • @WhozCraig indeed, but activating sane flags in legacy code is insane. One at a time. ;) – vesperto Feb 10 '22 at 12:16