Created attachment 128300 [details] testcase testcase attached. detail reproduce steps please see https://github.com/google/oss-fuzz/blob/master/docs/reproducing.md and https://github.com/google/oss-fuzz/tree/master/projects/libtsm What happened 1. cursor_x=79 and tsm_screen_write() an unicode character (width=2). 1098 move_cursor(con, con->cursor_x + len, con->cursor_y); cursor_x became 81. 2. tsm_screen_tab_left() 1318 x = con->cursor_x; 1319 for (i = 0; i < num; ++i) { 1320 for (j = x - 1; j > 0; --j) { 1321 if (con->tab_ruler[j]) x=81 at line 1318. j=x-1. Buffer overflow read when access tab_ruler[80] because the size of tab_ruler is only 80. Here is my patch, simply limit max of x to size_x. I think this is correct fix because this pattern exists in libtsm many times. diff --git a/src/tsm/tsm-screen.c b/src/tsm/tsm-screen.c index 2004d9f..aacdf8e 100644 --- a/src/tsm/tsm-screen.c +++ b/src/tsm/tsm-screen.c @@ -1316,6 +1316,8 @@ void tsm_screen_tab_left(struct tsm_screen *con, unsigned int num) screen_inc_age(con); x = con->cursor_x; + if (x > con->size_x) + x = con->size_x; for (i = 0; i < num; ++i) { for (j = x - 1; j > 0; --j) { if (con->tab_ruler[j]) Finally, following is ASAN report. ==294918==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60700000df90 at pc 0x0000005038d8 bp 0x7ffc4f901ab0 sp 0x7ffc4f901aa8 READ of size 1 at 0x60700000df90 thread T0 #0 0x5038d7 in tsm_screen_tab_left /oss-fuzz/projects/libtsm/libtsm/src/tsm/tsm-screen.c:1321:8 #1 0x517110 in do_csi /oss-fuzz/projects/libtsm/libtsm/src/tsm/tsm-vte.c:1722:3 #2 0x513368 in do_action /oss-fuzz/projects/libtsm/libtsm/src/tsm/tsm-vte.c:1812:4 #3 0x5131b2 in do_trans /oss-fuzz/projects/libtsm/libtsm/src/tsm/tsm-vte.c:1858:3 #4 0x50e250 in parse_data /oss-fuzz/projects/libtsm/libtsm/src/tsm/tsm-vte.c:2002:4 #5 0x50db71 in tsm_vte_input /oss-fuzz/projects/libtsm/libtsm/src/tsm/tsm-vte.c:2237:5 #6 0x4f6bb7 in LLVMFuzzerTestOneInput /oss-fuzz/projects/libtsm/libtsm/../libtsm_fuzzer.c:44:3 #7 0x529b57 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /fuzz/Fuzzer/./FuzzerLoop.cpp:515:13 #8 0x529d45 in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long) /fuzz/Fuzzer/./FuzzerLoop.cpp:469:3 #9 0x520875 in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) /fuzz/Fuzzer/./FuzzerDriver.cpp:272:3 #10 0x5225a9 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /fuzz/Fuzzer/./FuzzerDriver.cpp:482:9 #11 0x5207d0 in main /fuzz/Fuzzer/./FuzzerMain.cpp:20:10 #12 0x7f847e40cf44 in __libc_start_main /build/eglibc-oGUzwX/eglibc-2.19/csu/libc-start.c:287 #13 0x41b797 in _start (/oss-fuzz/projects/libtsm/libtsm_fuzzer+0x41b797) 0x60700000df90 is located 0 bytes to the right of 80-byte region [0x60700000df40,0x60700000df90) allocated by thread T0 here: #0 0x4c5e9d in realloc (/oss-fuzz/projects/libtsm/libtsm_fuzzer+0x4c5e9d) #1 0x4fa28c in tsm_screen_resize /oss-fuzz/projects/libtsm/libtsm/src/tsm/tsm-screen.c:652:15 #2 0x4f951f in tsm_screen_new /oss-fuzz/projects/libtsm/libtsm/src/tsm/tsm-screen.c:490:8 #3 0x4f6acb in LLVMFuzzerTestOneInput /oss-fuzz/projects/libtsm/libtsm/../libtsm_fuzzer.c:39:3 #4 0x529b57 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /fuzz/Fuzzer/./FuzzerLoop.cpp:515:13 #5 0x529d45 in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long) /fuzz/Fuzzer/./FuzzerLoop.cpp:469:3 #6 0x520875 in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) /fuzz/Fuzzer/./FuzzerDriver.cpp:272:3 #7 0x5225a9 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /fuzz/Fuzzer/./FuzzerDriver.cpp:482:9 #8 0x5207d0 in main /fuzz/Fuzzer/./FuzzerMain.cpp:20:10 #9 0x7f847e40cf44 in __libc_start_main /build/eglibc-oGUzwX/eglibc-2.19/csu/libc-start.c:287 SUMMARY: AddressSanitizer: heap-buffer-overflow /oss-fuzz/projects/libtsm/libtsm/src/tsm/tsm-screen.c:1321:8 in tsm_screen_tab_left Shadow bytes around the buggy address: 0x0c0e7fff9ba0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c0e7fff9bb0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c0e7fff9bc0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c0e7fff9bd0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c0e7fff9be0: fa fa fa fa fa fa fa fa 00 00 00 00 00 00 00 00 =>0x0c0e7fff9bf0: 00 00[fa]fa fa fa 00 00 00 00 00 00 00 00 00 fa 0x0c0e7fff9c00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c0e7fff9c10: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c0e7fff9c20: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c0e7fff9c30: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c0e7fff9c40: 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 Heap right redzone: fb Freed heap region: fd Stack left redzone: f1 Stack mid redzone: f2 Stack right redzone: f3 Stack partial redzone: f4 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 ==294918==ABORTING
Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.