orangeduck/mpc

heap buffer overflow is expected

Opened this issue · 4 comments

Hello.

While i'm writing a code with mpc.c, address sanitizer reported a heap buffer overflow.
I attached a file. (both bug1.c and bug2.c can cause heap buffer overflow. please test them separately.)

commit number : 3c26618

And the build command I used is below.

clang -fsanitize=address -m32 -g -ansi -pedantic -O3 -Wall -Wextra -Wformat=2 -Wshadow -Wno-long-long -Wno-overlength-strings -Wno-format-nonliteral -Wcast-align -Wwrite-strings -Wstrict-prototypes -Wold-style-definition -Wredundant-decls -Wnested-externs -Wmissing-include-dirs -Wswitch-default -o bug1 bug1.c ./mpc.c && ./bug1

clang -fsanitize=address -m32 -g -ansi -pedantic -O3 -Wall -Wextra -Wformat=2 -Wshadow -Wno-long-long -Wno-overlength-strings -Wno-format-nonliteral -Wcast-align -Wwrite-strings -Wstrict-prototypes -Wold-style-definition -Wredundant-decls -Wnested-externs -Wmissing-include-dirs -Wswitch-default -o bug2 bug2.c ./mpc.c && ./bug2

It may my problem because I didn't fully understand this code, but anyway please check this.

bug.zip

Hi yuweol,

Thanks for the report. There could be a memory bug in mpc however I can see some bugs in your code which are probably worth fixing first:

In bug1.c you don't free the result of mpc_parse which is stored in r. Either it will be a mpc_err_t or a mpc_ast_t you need to check the return code of mpc_parse to see. You can see an example of this in the code in the quickstart: https://github.com/orangeduck/mpc#quickstart . Also you don't ever free the string bug1 you allocate.

In bug2.c you don't free any of the parsers you allocate - this needs to be done with mpc_cleanup(4, Expr, Prod, Value, Maths); like in the quickstart example again.

Finally, I also sometimes get heap memory errors when using mpc which come from inside functions such as strcmp and strcpy. The reason for this is that sometimes when these functions are compiled using optimizations they use SIMD instructions which read or write past the end of the allocation. It depends a bit on the exact nature of the report but in most cases these heap memory errors can be ignored because these optimizations are performed in a safe way (by making some basic assumptions about allocation sizes etc).

If you attach the full report/output I can take a closer look.

Hope that helps,

Dan

Hello, Thanks for your reply.
My 2 code files are just examples for reproducing bugs inside mpc.
Below is bug report of address sanitizer, and at this time I compiled the code with option -O0 (without any optimization)

<bug1.c>

==6458==ERROR: AddressSanitizer: heap-buffer-overflow on address 0xf51005ef at pc 0x0817cc32 bp 0xfffac958 sp 0xfffac94c
READ of size 1 at 0xf51005ef thread T0
#0 0x817cc31 in mpcf_strtrimr mpc.c:2135:10
#1 0x816a5f2 in mpc_parse_input mpc.c:1042:13
#2 0x81743ce in mpc_parse mpc.c:1197:7
#3 0x81654a3 in main bug1.c:12:3
#4 0xf7495285 in __libc_start_main (/lib/i386-linux-gnu/libc.so.6+0x18285)
#5 0x8064237 in _start (bug1+0x8064237)

0xf51005ef is located 1 bytes to the left of 1-byte region [0xf51005f0,0xf51005f1)
allocated by thread T0 here:
#0 0x812a824 in calloc (bug1+0x812a824)
#1 0x817978e in mpcf_strfold mpc.c:2305:13
#2 0x81737d1 in mpc_stack_merger_out mpc.c:939:18
#3 0x816c014 in mpc_parse_input mpc.c:1105:13
#4 0x81743ce in mpc_parse mpc.c:1197:7
#5 0x81654a3 in main bug1.c:12:3
#6 0xf7495285 in __libc_start_main (/lib/i386-linux-gnu/libc.so.6+0x18285)

SUMMARY: AddressSanitizer: heap-buffer-overflow mpc.c:2135:10 in mpcf_strtrimr
Shadow bytes around the buggy address:
0x3ea20060: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x3ea20070: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x3ea20080: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x3ea20090: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x3ea200a0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x3ea200b0: fa fa fa fa fa fa fa fa fa fa fa fa fa[fa]01 fa
0x3ea200c0: fa fa 00 06 fa fa 04 fa fa fa 07 fa fa fa fd fd
0x3ea200d0: fa fa fd fa fa fa fd fa fa fa fd fd fa fa fd fa
0x3ea200e0: fa fa fd fd fa fa fd fa fa fa 01 fa fa fa 07 fa
0x3ea200f0: fa fa 00 06 fa fa 00 07 fa fa fa fa fa fa fa fa
0x3ea20100: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
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
==6458==ABORTING

<bug2.c>

==7438==ERROR: AddressSanitizer: heap-buffer-overflow on address 0xf5020314 at pc 0x08129b01 bp 0xff9e9968 sp 0xff9e9540
READ of size 8 at 0xf5020314 thread T0
#0 0x8129b00 in __asan_memmove (bug2+0x8129b00)
#1 0x818b409 in mpc_optimise_unretained mpc.c:3426:7
#2 0x8188d23 in mpc_optimise_unretained mpc.c:3358:7
#3 0x817c916 in mpc_optimise mpc.c:3505:3
#4 0x8194d04 in mpca_stmt_list_apply_to mpc.c:3109:5
#5 0x816a9c4 in mpc_parse_input mpc.c:1052:13
#6 0x8186894 in mpca_lang_st mpc.c:3180:8
#7 0x8186f68 in mpca_lang mpc.c:3250:9
#8 0x81653e6 in main bug2.c:12:3
#9 0xf7575285 in __libc_start_main (/lib/i386-linux-gnu/libc.so.6+0x18285)
#10 0x8064237 in _start (bug2+0x8064237)

0xf5020314 is located 0 bytes to the right of 4-byte region [0xf5020310,0xf5020314)
allocated by thread T0 here:
#0 0x812a624 in malloc (bug2+0x812a624)
#1 0x8184013 in mpca_and mpc.c:2780:21
#2 0x8184f74 in mpcaf_grammar_and mpc.c:2857:30
#3 0x81736b1 in mpc_stack_merger_out mpc.c:939:18
#4 0x816c674 in mpc_parse_input mpc.c:1121:15
#5 0x8186894 in mpca_lang_st mpc.c:3180:8
#6 0x8186f68 in mpca_lang mpc.c:3250:9
#7 0x81653e6 in main bug2.c:12:3
#8 0xf7575285 in __libc_start_main (/lib/i386-linux-gnu/libc.so.6+0x18285)

SUMMARY: AddressSanitizer: heap-buffer-overflow (bug2+0x8129b00) in __asan_memmove
Shadow bytes around the buggy address:
0x3ea04010: fa fa fd fa fa fa fd fa fa fa fd fa fa fa fd fa
0x3ea04020: fa fa fd fa fa fa fd fd fa fa fd fa fa fa fd fd
0x3ea04030: fa fa fd fa fa fa fd fa fa fa fd fd fa fa fd fa
0x3ea04040: fa fa fd fd fa fa fd fa fa fa fd fa fa fa fd fd
0x3ea04050: fa fa fd fd fa fa fd fd fa fa fd fa fa fa fd fa
=>0x3ea04060: fa fa[04]fa fa fa 00 fa fa fa fd fa fa fa fd fa
0x3ea04070: fa fa fd fa fa fa fd fa fa fa fd fa fa fa fd fa
0x3ea04080: fa fa fd fa fa fa fd fa fa fa fd fa fa fa fd fa
0x3ea04090: fa fa fd fd fa fa fd fa fa fa fd fd fa fa fd fa
0x3ea040a0: fa fa fd fa fa fa fd fd fa fa fd fa fa fa fd fd
0x3ea040b0: fa fa fd fa fa fa fd fa fa fa fd fd fa fa fd fa
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
==7438==ABORTING

As you can see, address sanitizer found a bug and forcefully terminated a program while each mpc_parse, mpca_lang function was working.
So I don't think this bugs are because of my misuse of mpc.

Thanks.

Thanks for the full report I will look into it a bit more.

I wasn't able to reproduce these crashes. I think I need to use valgrind to get more information on this which means installing Ubuntu however I am still surprised you are getting errors in this case. These sort of examples have been tried and tested many times...