akimd / bison

GNU Bison
GNU General Public License v3.0
332 stars 89 forks source link

[BUG] abitset_set is reachable by crafted input, which cause the program abort #92

Closed kdsjZh closed 2 years ago

kdsjZh commented 2 years ago

short summary

Hello, I was testing my fuzzer and found function abitset_set in lib/bitset/array.c:92 can be reached when bison parse a crafted input. As commented in the code indicate, it should not be reached. I'm not sure if it's a bug or just error handling, pls ignore if it's just an expected behavior.

Step to reproduce

CC="gcc -fsanitize=address -g " CXX="g++ -fsanitize=address -g" ./autogen.sh && ./configure --disable-shared && make -j$(nproc)
./src/bison $POC

Environment

Ubuntu 22.04 (docker image) gcc 11.2.0 bison latest commit https://github.com/akimd/bison/commit/637636412037d1fc2079f81260b19de5d0dab199

Output / gdb log

poc1:40.30: warning: stray '$' [-Wother]
   40 | %printer { fprintf (y_o, "%g"$ E$); } <double>;
      |                              ^
...
      |                                       ^
poc1:98.24: warning: empty rule without %empty [-Wempty-rule]
   98 |   {            } YYEOF:
      |                        ^
      |                        %empty

Program received signal SIGABRT, Aborted.
[----------------------------------registers-----------------------------------]
RAX: 0x0
RBX: 0x7ffff72aac00 (0x00007ffff72aac00)
RCX: 0x7ffff7440828 (<__GI___pthread_kill+248>: mov    r13d,eax)
RDX: 0xffffffe6 --> 0x0
RSI: 0x6
RDI: 0x257de6
RBP: 0x6
RSP: 0x7fffffffda60 --> 0xffffffffb4e --> 0x0
RIP: 0x7ffff7440828 (<__GI___pthread_kill+248>: mov    r13d,eax)
R8 : 0x7fffffffdb30 --> 0x20 (' ')
R9 : 0x0
R10: 0x8
R11: 0x246
R12: 0x5555556cbc60 --> 0xb ('\x0b')
R13: 0x16
R14: 0x1e
R15: 0x5555556e8ca0 --> 0x29 (')')
EFLAGS: 0x246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x7ffff744081f <__GI___pthread_kill+239>:    mov    edi,eax
   0x7ffff7440821 <__GI___pthread_kill+241>:    mov    eax,0x3e
   0x7ffff7440826 <__GI___pthread_kill+246>:    syscall
=> 0x7ffff7440828 <__GI___pthread_kill+248>:    mov    r13d,eax
   0x7ffff744082b <__GI___pthread_kill+251>:    neg    r13d
   0x7ffff744082e <__GI___pthread_kill+254>:    cmp    eax,0xfffff000
   0x7ffff7440833 <__GI___pthread_kill+259>:    mov    eax,0x0
   0x7ffff7440838 <__GI___pthread_kill+264>:    cmovbe r13d,eax
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffda60 --> 0xffffffffb4e --> 0x0
0008| 0x7fffffffda68 --> 0x5555555c799d (<location_caret_suggestion+557>:       jmp    0x5555555c793c <location_caret_suggestion+460>)
0016| 0x7fffffffda70 --> 0x41b58ab3
0024| 0x7fffffffda78 --> 0x5555556a8a00 ("4 32 24 7 now:175 96 24 7 now:126 160 144 8 self:105 368 144 8 chld:107")
0032| 0x7fffffffda80 --> 0x555555667330 (<timevar_push>:        endbr64)
0040| 0x7fffffffda88 --> 0x5555556a8a48 ("4 32 24 7 now:214 96 24 7 now:126 160 144 8 self:105 368 144 8 chld:107")
0048| 0x7fffffffda90 --> 0x555555667970 (<timevar_pop>: endbr64)
0056| 0x7fffffffda98 --> 0x606000004128 --> 0x602000001090 --> 0x606000004160 --> 0x602000000250 --> 0x31636f70 ('poc1')
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGABRT
__pthread_kill_implementation (no_tid=0x0, signo=0x6, threadid=0x7ffff72aac00) at pthread_kill.c:44
44      pthread_kill.c: No such file or directory.
gdb-peda$ bt
#0  __pthread_kill_implementation (no_tid=0x0, signo=0x6, threadid=0x7ffff72aac00) at pthread_kill.c:44
#1  __pthread_kill_internal (signo=0x6, threadid=0x7ffff72aac00) at pthread_kill.c:80
#2  __GI___pthread_kill (threadid=0x7ffff72aac00, signo=signo@entry=0x6) at pthread_kill.c:91
#3  0x00007ffff73ec476 in __GI_raise (sig=sig@entry=0x6) at ../sysdeps/posix/raise.c:26
#4  0x00007ffff73d27b7 in __GI_abort () at abort.c:79
#5  0x000055555558a638 in abitset_set (dst=<optimized out>, bitno=<optimized out>) at lib/bitset/array.c:92
#6  0x00005555556013ca in bitset_set (bitno=<optimized out>, bset=0x6040000009d0) at ./lib/bitset.h:146
#7  bitset_set (bitno=<optimized out>, bset=0x6040000009d0) at ./lib/bitset.h:138
#8  useless_nonterminals () at src/reduce.c:121
#9  reduce_grammar () at src/reduce.c:377
#10 0x000055555558b9ad in main (argc=argc@entry=0x2, argv=argv@entry=0x7fffffffde58) at src/main.c:126
#11 0x00007ffff73d3fd0 in __libc_start_call_main (main=main@entry=0x55555558b780 <main>, argc=argc@entry=0x2, argv=argv@entry=0x7fffffffde58)
    at ../sysdeps/nptl/libc_start_call_main.h:58
#12 0x00007ffff73d407d in __libc_start_main_impl (main=0x55555558b780 <main>, argc=0x2, argv=0x7fffffffde58, init=<optimized out>, fini=<optimized out>,
    rtld_fini=<optimized out>, stack_end=0x7fffffffde48) at ../csu/libc-start.c:409
#13 0x000055555558d0c5 in _start ()

Seems that function abitset_set should never be reached. I'm not sure if it's a bug or just error handling.

/* Set bit BITNO in bitset DST.  */
static void
abitset_set (MAYBE_UNUSED bitset dst, MAYBE_UNUSED bitset_bindex bitno)
{
  /* This should never occur for abitsets since we should always hit
     the cache.  It is likely someone is trying to access outside the
     bounds of the bitset.  */
  abort ();
}

POC

poc1.zip

Credit

Han Zheng (NCNIPC of China, Hexhive)

akimd commented 2 years ago

Hi, Thanks for the report. It boils down to this:

%%
input:;
YYEOF:

In other words, your file redefined YYEOF from being a token to being a nonterminal symbol. This should not happen. I'll see how to address this.

Thanks!