On Wed, Sep 13, 2023 at 06:52:08PM -0300, Antonio Terceiro wrote:
> ohcount segfaults (and sometimes aborts with a Bus error) on arm64,
> almost 90% of the time. I tried this on an up to date arm64 Debian
Running ohcount under gdb traps on the segfault but can't get a
backtrace due to a corrupted stack. So I recompiled ohcount with
the address sanitiser which traps on the segfault with the following:
=================================================================
==14540==ERROR: AddressSanitizer: dynamic-stack-buffer-overflow on address
0xffffeab309b4 at pc 0xaaaaacf8bd38 bp 0xffffeab30960 sp 0xffffeab30978
WRITE of size 1 at 0xffffeab309b4 thread T0
#0 0xaaaaacf8bd34 in disambiguate_aspx src/detector.c:241
#1 0xaaaaacf8ba80 in ohcount_detect_language src/detector.c:221
#2 0xaaaaacf87304 in ohcount_sourcefile_get_language src/sourcefile.c:128
#3 0xaaaaad1fb5d0 in ohcount_parse src/parser.c:16
#4 0xaaaaacf879cc in ohcount_sourcefile_parse src/sourcefile.c:195
#5 0xaaaaacf87be0 in ohcount_sourcefile_get_loc_list src/sourcefile.c:239
#6 0xaaaaacf88f48 in ohcount_sourcefile_list_analyze_languages
src/sourcefile.c:404
#7 0xaaaaacf8582c in summary src/ohcount.c:210
#8 0xaaaaacf86394 in main src/ohcount.c:302
#9 0xffffa95f777c in __libc_start_call_main
../sysdeps/nptl/libc_start_call_main.h:58
#10 0xffffa95f7854 in __libc_start_main_impl ../csu/libc-start.c:360
#11 0xaaaaacf840ac in _start
(/home/mjc/debian/ohcount/ohcount-4.0.0/bin/ohcount+0x240ac)
Address 0xffffeab309b4 is located in stack of thread T0
SUMMARY: AddressSanitizer: dynamic-stack-buffer-overflow src/detector.c:241 in
disambiguate_aspx
Shadow bytes around the buggy address:
0x200ffd5660e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x200ffd5660f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x200ffd566100: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x200ffd566110: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x200ffd566120: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x200ffd566130: ca ca ca ca 00 00[04]cb cb cb cb cb 00 00 00 00
0x200ffd566140: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x200ffd566150: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x200ffd566160: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x200ffd566170: 00 00 00 00 f1 f1 f1 f1 00 00 00 00 00 00 00 00
0x200ffd566180: 00 00 01 f2 f2 f2 f2 f2 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
==14540==ABORTING
The code for disambiguate_aspx() where the segfaults occurs is:
const char *disambiguate_aspx(SourceFile *sourcefile) {
char *p = ohcount_sourcefile_get_contents(sourcefile);
char *eof = p + ohcount_sourcefile_get_contents_size(sourcefile);
for (; p < eof; p++) {
// /<%@\s*Page[^>]+Language="VB"[^>]+%>/
p = strstr(p, "<%@");
if (!p)
break;
char *pe = strstr(p, "%>");
if (p && pe) {
p += 3;
const int length = pe - p;
char buf[length];
strncpy(buf, p, length);
buf[length] = '\0';
char *eol = buf + strlen(buf);
for (p = buf; p < eol; p++) *p = tolower(*p);
p = buf;
while (*p == ' ' || *p == '\t') p++;
if (strncmp(p, "page", 4) == 0) {
p += 4;
if (strstr(p, "language=\"vb\""))
return LANG_VB_ASPX;
}
}
}
return LANG_CS_ASPX;
}
Line 241 is the line with: buf[length] = '\0';
We see that buf is declared two lines above as a variable length
array. Being a local variable I assume that it is allocated on the
stack, which is dangerous if its length turns out to be too large
for the stack. Presumably that is the problem.
Cheers,
Michael.