Skip to content
GitLab
  • Menu
Projects Groups Snippets
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
    • Contribute to GitLab
  • Sign in / Register
  • G GLib
  • Project information
    • Project information
    • Activity
    • Labels
    • Members
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
  • Issues 882
    • Issues 882
    • List
    • Boards
    • Service Desk
    • Milestones
  • Merge requests 41
    • Merge requests 41
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Schedules
  • Deployments
    • Deployments
    • Releases
  • Packages & Registries
    • Packages & Registries
    • Container Registry
  • Analytics
    • Analytics
    • Value stream
    • CI/CD
    • Repository
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar
  • GNOME
  • GLib
  • Issues
  • #1361
Closed
Open
Created Apr 08, 2018 by Bugzilla@bugzilla-migration💬Reporter

Out of Bound Read in g_markup_parse_context_parse()

Submitted by Jin @JsHuang

Link to original bug (#795060)

Description

Created attachment 370643 libfuzer fuzz target function and crash input

Function g_markup_parse_context_parse() can cause an out of bound read and may cause access violation error. While parsing a invalid string , g_markup_parse_context_parse() will call set_error() (gmarkup.c: line1254) fuction to print some error message, in set_error(), it calls utf8_str() to get the current parsing character. utf8_str() calls char_str() and g_utf8_get_char(), the error comes in g_utf8_get_char().

g_utf8_get_char (const gchar *p) { int i, mask = 0, len; gunichar result; unsigned char c = (unsigned char) *p;

// compute len and mask UTF8_COMPUTE (c, mask, len);

/* for an invalid input string, eg: 4 byte input 0x3c002fc9(bin), when handling the last character "c9" ,len will be 2, other invalid character, may be bigger then 2. */

if (len == -1) return (gunichar)-1; UTF8_GET (result, p, i, mask, len);

/* len is 2, and will read out of bound */

return result; }

This bug is found by ASAN. The error message is as below :

==18252==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000050294 at pc 0x7f335b6638b2 bp 0x7ffffc114660 sp 0x7ffffc114658 READ of size 1 at 0x602000050294 thread T0 #0 0x7f335b6638b1 in g_utf8_get_char /home/afl/fuzzing/glib-master/glib/gutf8.c:323:3 #1 (closed) 0x7f335b55119e in utf8_str /home/afl/fuzzing/glib-master/glib/gmarkup.c:564:13 #2 (closed) 0x7f335b55119e in g_markup_parse_context_parse /home/afl/fuzzing/glib-master/glib/gmarkup.c:1256 #3 (closed) 0x545729 in LLVMFuzzerTestOneInput /home/afl/fuzzing/glib-master/fuzzing/g_markup_parse_context_parse.cc:18:2 #4 (closed) 0x52da66 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /home/afl/Fuzzer/./FuzzerLoop.cpp:517:13 #5 (closed) 0x52d29b in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool*) /home/afl/Fuzzer/./FuzzerLoop.cpp:442:3 #6 (closed) 0x52e9d6 in fuzzer::Fuzzer::MutateAndTestOne() /home/afl/Fuzzer/./FuzzerLoop.cpp:650:19 #7 0x52f355 in fuzzer::Fuzzer::Loop(std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, fuzzer::fuzzer_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&) /home/afl/Fuzzer/./FuzzerLoop.cpp:773:5 #8 (closed) 0x525180 in fuzzer::FuzzerDriver(int*, char***, int ()(unsigned char const, unsigned long)) /home/afl/Fuzzer/./FuzzerDriver.cpp:754:6 #9 (closed) 0x520930 in main /home/afl/Fuzzer/./FuzzerMain.cpp:20:10 #10 (closed) 0x7f3359fea82f in __libc_start_main /build/glibc-Cl5G7W/glibc-2.23/csu/../csu/libc-start.c:291 #11 (closed) 0x41d248 in _start (/home/afl/fuzzing/glib-master/fuzzing/g_markup_parse_context_parse+0x41d248)

0x602000050294 is located 0 bytes to the right of 4-byte region [0x602000050290,0x602000050294) allocated by thread T0 here: #0 0x4e8fb8 in __interceptor_malloc (/home/afl/fuzzing/glib-master/fuzzing/g_markup_parse_context_parse+0x4e8fb8) #1 (closed) 0x7f335af69e77 in operator new(unsigned long) (/usr/lib/x86_64-linux-gnu/libstdc++.so.6+0x8de77) #2 (closed) 0x52d29b in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool*) /home/afl/Fuzzer/./FuzzerLoop.cpp:442:3 #3 (closed) 0x52e9d6 in fuzzer::Fuzzer::MutateAndTestOne() /home/afl/Fuzzer/./FuzzerLoop.cpp:650:19 #4 (closed) 0x52f355 in fuzzer::Fuzzer::Loop(std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, fuzzer::fuzzer_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&) /home/afl/Fuzzer/./FuzzerLoop.cpp:773:5 #5 (closed) 0x525180 in fuzzer::FuzzerDriver(int*, char***, int ()(unsigned char const, unsigned long)) /home/afl/Fuzzer/./FuzzerDriver.cpp:754:6 #6 (closed) 0x520930 in main /home/afl/Fuzzer/./FuzzerMain.cpp:20:10 #7 0x7f3359fea82f in __libc_start_main /build/glibc-Cl5G7W/glibc-2.23/csu/../csu/libc-start.c:291

SUMMARY: AddressSanitizer: heap-buffer-overflow /home/afl/fuzzing/glib-master/glib/gutf8.c:323:3 in g_utf8_get_char Shadow bytes around the buggy address: 0x0c0480002000: fa fa fd fa fa fa fd fa fa fa fd fa fa fa fd fa 0x0c0480002010: fa fa fd fa fa fa fd fa fa fa fd fa fa fa fd fa 0x0c0480002020: fa fa fd fa fa fa fd fa fa fa fd fa fa fa fd fa 0x0c0480002030: fa fa fd fa fa fa fd fa fa fa fd fa fa fa fd fa 0x0c0480002040: fa fa fd fa fa fa fd fa fa fa fd fa fa fa fd fa =>0x0c0480002050: fa fa[04]fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c0480002060: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c0480002070: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c0480002080: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c0480002090: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c04800020a0: 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

Function g_markup_parse_context_parse() can cause an out of bound read and may cause access violation error. While parsing a invalid string , g_markup_parse_context_parse() will call set_error() (gmarkup.c: line1254) fuction to print some error message, in set_error(), it calls utf8_str() to get the current parsing character. utf8_str() calls char_str() and g_utf8_get_char(), the error comes in g_utf8_get_char().

g_utf8_get_char (const gchar *p) { int i, mask = 0, len; gunichar result; unsigned char c = (unsigned char) *p;

// compute len and mask UTF8_COMPUTE (c, mask, len);

/* for an invalid input string, eg: 4 byte input 0x3c002fc9(bin), when handling the last character "c9" ,len will be 2, other invalid character, may be bigger then 2. */

if (len == -1) return (gunichar)-1; UTF8_GET (result, p, i, mask, len);

/* len is 2, and will read out of bound */

return result; }

This bug is found by ASAN. The error message is as below :

==18252==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000050294 at pc 0x7f335b6638b2 bp 0x7ffffc114660 sp 0x7ffffc114658 READ of size 1 at 0x602000050294 thread T0 #0 0x7f335b6638b1 in g_utf8_get_char /home/afl/fuzzing/glib-master/glib/gutf8.c:323:3 #1 (closed) 0x7f335b55119e in utf8_str /home/afl/fuzzing/glib-master/glib/gmarkup.c:564:13 #2 (closed) 0x7f335b55119e in g_markup_parse_context_parse /home/afl/fuzzing/glib-master/glib/gmarkup.c:1256 #3 (closed) 0x545729 in LLVMFuzzerTestOneInput /home/afl/fuzzing/glib-master/fuzzing/g_markup_parse_context_parse.cc:18:2 #4 (closed) 0x52da66 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /home/afl/Fuzzer/./FuzzerLoop.cpp:517:13 #5 (closed) 0x52d29b in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool*) /home/afl/Fuzzer/./FuzzerLoop.cpp:442:3 #6 (closed) 0x52e9d6 in fuzzer::Fuzzer::MutateAndTestOne() /home/afl/Fuzzer/./FuzzerLoop.cpp:650:19 #7 0x52f355 in fuzzer::Fuzzer::Loop(std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, fuzzer::fuzzer_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&) /home/afl/Fuzzer/./FuzzerLoop.cpp:773:5 #8 (closed) 0x525180 in fuzzer::FuzzerDriver(int*, char***, int ()(unsigned char const, unsigned long)) /home/afl/Fuzzer/./FuzzerDriver.cpp:754:6 #9 (closed) 0x520930 in main /home/afl/Fuzzer/./FuzzerMain.cpp:20:10 #10 (closed) 0x7f3359fea82f in __libc_start_main /build/glibc-Cl5G7W/glibc-2.23/csu/../csu/libc-start.c:291 #11 (closed) 0x41d248 in _start (/home/afl/fuzzing/glib-master/fuzzing/g_markup_parse_context_parse+0x41d248)

0x602000050294 is located 0 bytes to the right of 4-byte region [0x602000050290,0x602000050294) allocated by thread T0 here: #0 0x4e8fb8 in __interceptor_malloc (/home/afl/fuzzing/glib-master/fuzzing/g_markup_parse_context_parse+0x4e8fb8) #1 (closed) 0x7f335af69e77 in operator new(unsigned long) (/usr/lib/x86_64-linux-gnu/libstdc++.so.6+0x8de77) #2 (closed) 0x52d29b in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool*) /home/afl/Fuzzer/./FuzzerLoop.cpp:442:3 #3 (closed) 0x52e9d6 in fuzzer::Fuzzer::MutateAndTestOne() /home/afl/Fuzzer/./FuzzerLoop.cpp:650:19 #4 (closed) 0x52f355 in fuzzer::Fuzzer::Loop(std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, fuzzer::fuzzer_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&) /home/afl/Fuzzer/./FuzzerLoop.cpp:773:5 #5 (closed) 0x525180 in fuzzer::FuzzerDriver(int*, char***, int ()(unsigned char const, unsigned long)) /home/afl/Fuzzer/./FuzzerDriver.cpp:754:6 #6 (closed) 0x520930 in main /home/afl/Fuzzer/./FuzzerMain.cpp:20:10 #7 0x7f3359fea82f in __libc_start_main /build/glibc-Cl5G7W/glibc-2.23/csu/../csu/libc-start.c:291

SUMMARY: AddressSanitizer: heap-buffer-overflow /home/afl/fuzzing/glib-master/glib/gutf8.c:323:3 in g_utf8_get_char Shadow bytes around the buggy address: 0x0c0480002000: fa fa fd fa fa fa fd fa fa fa fd fa fa fa fd fa 0x0c0480002010: fa fa fd fa fa fa fd fa fa fa fd fa fa fa fd fa 0x0c0480002020: fa fa fd fa fa fa fd fa fa fa fd fa fa fa fd fa 0x0c0480002030: fa fa fd fa fa fa fd fa fa fa fd fa fa fa fd fa 0x0c0480002040: fa fa fd fa fa fa fd fa fa fa fd fa fa fa fd fa =>0x0c0480002050: fa fa[04]fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c0480002060: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c0480002070: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c0480002080: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c0480002090: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c04800020a0: 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

credit:ADLab of Venustech

Attachment 370643, "libfuzer fuzz target function and crash input":
g_markup_parse_context_parse-crash

Version: 2.56.x

Assignee
Assign to
Time tracking