Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Heap buffer overflow with in situ parsing #1723

Open
Oipo opened this issue May 21, 2020 · 4 comments
Open

Heap buffer overflow with in situ parsing #1723

Oipo opened this issue May 21, 2020 · 4 comments

Comments

@Oipo
Copy link

Oipo commented May 21, 2020

The following program causes a heap buffer overflow, sometimes a segfault:

#define RAPIDJSON_SSE42 1
#include <rapidjson/document.h>

int main()
{
    const char *literal = "{\"type\":962337350526730037,\"slot\":1}\0";
    char *dst = strdup(literal);
    rapidjson::Document d;
    d.ParseInsitu(dst);
}

Compile with g++ -fsanitize=address -g3 -mavx -I rapidjson/include test.cpp

Address sanitizer output:

=================================================================
==45424==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x604000000030 at pc 0x5d4cafcd2999 bp 0x7ffca551eb20 sp 0x7ffca551eb10
READ of size 16 at 0x604000000030 thread T0
    #0 0x5d4cafcd2998 in _mm_load_si128(long long __vector(2) const*) /usr/lib/gcc/x86_64-linux-gnu/9/include/emmintrin.h:697
    #1 0x5d4cafcd2998 in rapidjson::GenericReader<rapidjson::UTF8<char>, rapidjson::UTF8<char>, rapidjson::CrtAllocator>::SkipUnescapedString(rapidjson::GenericInsituStringStream<rapidjson::UTF8<char> >&) include/rapidjson/reader.h:1202
    #2 0x5d4cafcd093e in rapidjson::GenericReader<rapidjson::UTF8<char>, rapidjson::UTF8<char>, rapidjson::CrtAllocator>::ScanCopyUnescapedString(rapidjson::GenericInsituStringStream<rapidjson::UTF8<char> >&, rapidjson::GenericInsituStringStream<rapidjson::UTF8<char> >&) include/rapidjson/reader.h:1127
    #3 0x5d4cafccf63c in void rapidjson::GenericReader<rapidjson::UTF8<char>, rapidjson::UTF8<char>, rapidjson::CrtAllocator>::ParseStringToStream<1u, rapidjson::UTF8<char>, rapidjson::UTF8<char>, rapidjson::GenericInsituStringStream<rapidjson::UTF8<char> >, rapidjson::GenericInsituStringStream<rapidjson::UTF8<char> > >(rapidjson::GenericInsituStringStream<rapidjson::UTF8<char> >&, rapidjson::GenericInsituStringStream<rapidjson::UTF8<char> >&) include/rapidjson/reader.h:1007
    #4 0x5d4cafccd0a4 in void rapidjson::GenericReader<rapidjson::UTF8<char>, rapidjson::UTF8<char>, rapidjson::CrtAllocator>::ParseString<1u, rapidjson::GenericInsituStringStream<rapidjson::UTF8<char> >, rapidjson::GenericDocument<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>, rapidjson::CrtAllocator> >(rapidjson::GenericInsituStringStream<rapidjson::UTF8<char> >&, rapidjson::GenericDocument<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>, rapidjson::CrtAllocator>&, bool) include/rapidjson/reader.h:969
    #5 0x5d4cafccd556 in void rapidjson::GenericReader<rapidjson::UTF8<char>, rapidjson::UTF8<char>, rapidjson::CrtAllocator>::ParseObject<1u, rapidjson::GenericInsituStringStream<rapidjson::UTF8<char> >, rapidjson::GenericDocument<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>, rapidjson::CrtAllocator> >(rapidjson::GenericInsituStringStream<rapidjson::UTF8<char> >&, rapidjson::GenericDocument<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>, rapidjson::CrtAllocator>&) include/rapidjson/reader.h:760
    #6 0x5d4cafccc64d in void rapidjson::GenericReader<rapidjson::UTF8<char>, rapidjson::UTF8<char>, rapidjson::CrtAllocator>::ParseValue<1u, rapidjson::GenericInsituStringStream<rapidjson::UTF8<char> >, rapidjson::GenericDocument<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>, rapidjson::CrtAllocator> >(rapidjson::GenericInsituStringStream<rapidjson::UTF8<char> >&, rapidjson::GenericDocument<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>, rapidjson::CrtAllocator>&) include/rapidjson/reader.h:1748
    #7 0x5d4cafccbf72 in rapidjson::ParseResult rapidjson::GenericReader<rapidjson::UTF8<char>, rapidjson::UTF8<char>, rapidjson::CrtAllocator>::Parse<1u, rapidjson::GenericInsituStringStream<rapidjson::UTF8<char> >, rapidjson::GenericDocument<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>, rapidjson::CrtAllocator> >(rapidjson::GenericInsituStringStream<rapidjson::UTF8<char> >&, rapidjson::GenericDocument<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>, rapidjson::CrtAllocator>&) include/rapidjson/reader.h:575
    #8 0x5d4cafccb9e5 in rapidjson::GenericDocument<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>, rapidjson::CrtAllocator>& rapidjson::GenericDocument<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>, rapidjson::CrtAllocator>::ParseStream<1u, rapidjson::UTF8<char>, rapidjson::GenericInsituStringStream<rapidjson::UTF8<char> > >(rapidjson::GenericInsituStringStream<rapidjson::UTF8<char> >&) include/rapidjson/document.h:2342
    #9 0x5d4cafccb6c2 in rapidjson::GenericDocument<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>, rapidjson::CrtAllocator>& rapidjson::GenericDocument<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>, rapidjson::CrtAllocator>::ParseStream<1u, rapidjson::GenericInsituStringStream<rapidjson::UTF8<char> > >(rapidjson::GenericInsituStringStream<rapidjson::UTF8<char> >&) include/rapidjson/document.h:2358
    #10 0x5d4cafccb4a7 in rapidjson::GenericDocument<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>, rapidjson::CrtAllocator>& rapidjson::GenericDocument<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>, rapidjson::CrtAllocator>::ParseInsitu<0u>(char*) include/rapidjson/document.h:2383
    #11 0x5d4cafccaf3a in rapidjson::GenericDocument<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>, rapidjson::CrtAllocator>::ParseInsitu(char*) include/rapidjson/document.h:2391
    #12 0x5d4cafcca5d3 in main /home/oipo-unencrypted/Programming/IdleBossHunter/external/rapidjson/test.cpp:9
    #13 0x7740f15690b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)
    #14 0x5d4cafcca42d in _start (/home/oipo-unencrypted/Programming/IdleBossHunter/external/rapidjson/a.out+0x242d)

0x604000000035 is located 0 bytes to the right of 37-byte region [0x604000000010,0x604000000035)
allocated by thread T0 here:
    #0 0x7740f19c63dd in strdup (/lib/x86_64-linux-gnu/libasan.so.5+0x963dd)
    #1 0x5d4cafcca595 in main /home/oipo-unencrypted/Programming/IdleBossHunter/external/rapidjson/test.cpp:7
    #2 0x7740f15690b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)

SUMMARY: AddressSanitizer: heap-buffer-overflow /usr/lib/gcc/x86_64-linux-gnu/9/include/emmintrin.h:697 in _mm_load_si128(long long __vector(2) const*)
Shadow bytes around the buggy address:
  0x0c087fff7fb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c087fff7fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c087fff7fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c087fff7fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c087fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c087fff8000: fa fa 00 00 00 00[05]fa fa fa 00 00 00 00 00 fa
  0x0c087fff8010: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c087fff8020: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c087fff8030: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c087fff8040: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c087fff8050: 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
  Shadow gap:              cc
==45424==ABORTING
@miloyip
Copy link
Collaborator

miloyip commented May 22, 2020

For SIMD version, I think it is needed to add padding to the source string.

@Oipo
Copy link
Author

Oipo commented May 22, 2020

Is there a way to know how much? Just adding 4 or 8 bytes doesn't seem to always work, there'll just be another example that goes wrong.

@miloyip
Copy link
Collaborator

miloyip commented May 22, 2020

Currently RapidJSON supports up to SSE 4.1, 16 bytes alignment should be sufficient.

@Oipo
Copy link
Author

Oipo commented May 22, 2020

Though it doesn't show in this minimal example, having to add padding to the buffers I get from my network library would add an extra memory allocation, negating the gain from using SSE 4 instructions. I'll just disable them for now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants