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

SEGV on unknown address mp4file.cpp:2662 in MP4File::GetChapters #53

Open
mugichiya opened this issue Sep 19, 2024 · 1 comment
Open

Comments

@mugichiya
Copy link

mugichiya commented Sep 19, 2024

Hi, I found segfault on unknown address in mp4file.cpp:2662. It seems to occur because sample could not get a valid reference in pChapterTrack->ReadSample on line 2655.

Abstract

Segmentation fault (maybe null pointer reference) on mp4chaps(libmp4v2.so.2).

Environment

OS: Ubuntu 22.04.4 LTS
Compiler: gcc version 11.4.0

Build

cd /opt
git clone https://github.com/enzo1982/mp4v2.git -b 2.1.3 --depth 1
cd ./mp4v2
mkdir build
cmake -DCMAKE_BUILD_TYPE=Debug ../
cmake --build . -j 10

To enable Address Sanitizer, add the following options to CMakeFiles.txt.

add_compile_options(-fsanitize=address)
add_link_options(-fsanitize=address)

PoC

See testcases.

git clone https://github.com/mugichiya/pockey.git
cp -r ./pockey/projects/mp4v2_np/testcases .
./mp4chaps --list ./testcases/0000000000.mp4

ASAN output

banjo@ttc:/tmp/mp4v2/build$ ./mp4chaps --list ./testcases/0000000000.mp4
ReadAtom: "./testcases/0000000000.mp4": invalid atom size, extends outside parent atom - skipping to end of "stbl" "stco" 159384830 vs 1298
AddressSanitizer:DEADLYSIGNAL
=================================================================
==3389808==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x7f74e82f270b bp 0x7fff39dcd780 sp 0x7fff39dcd5b0 T0)
==3389808==The signal is caused by a READ memory access.
==3389808==Hint: address points to the zero page.
    #0 0x7f74e82f270b in mp4v2::impl::MP4File::GetChapters(MP4Chapter_s**, unsigned int*, MP4ChapterType) /opt/mp4v2/src/mp4file.cpp:2662
    #1 0x7f74e82c1294 in MP4GetChapters /opt/mp4v2/src/mp4.cpp:1647
    #2 0x5620329500df in mp4v2::util::ChapterUtility::actionList(mp4v2::util::Utility::JobContext&) /opt/mp4v2/util/mp4chaps.cpp:182
    #3 0x562032956476 in mp4v2::util::ChapterUtility::utility_job(mp4v2::util::Utility::JobContext&) /opt/mp4v2/util/mp4chaps.cpp:664
    #4 0x7f74e81db528 in mp4v2::util::Utility::job(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) /opt/mp4v2/libutil/Utility.cpp:298
    #5 0x7f74e81d9626 in mp4v2::util::Utility::batch(int) /opt/mp4v2/libutil/Utility.cpp:105
    #6 0x7f74e81de155 in mp4v2::util::Utility::process_impl() /opt/mp4v2/libutil/Utility.cpp:565
    #7 0x7f74e81dd24e in mp4v2::util::Utility::process() /opt/mp4v2/libutil/Utility.cpp:449
    #8 0x56203295957c in main /opt/mp4v2/util/mp4chaps.cpp:1188
    #9 0x7f74e7823a8f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
    #10 0x7f74e7823b48 in __libc_start_main_impl ../csu/libc-start.c:360
    #11 0x56203294c144 in _start (/opt/mp4v2/build2/mp4chaps+0xf144) (BuildId: 6362905fe8ce5624b29ef2869e210553dee47e65)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV /opt/mp4v2/src/mp4file.cpp:2662 in mp4v2::impl::MP4File::GetChapters(MP4Chapter_s**, unsigned int*, MP4ChapterType)
==3389808==ABORTING

Solution

It is recommended to insert a null pointer judgment, and take other instruction (if-else/exception handling) if sample is NULL. For example, if branch inserted line 2662 in src/mp4file.cpp can prevent the segfault.

                  // we know that sample+2 contains the title (sample[0] and sample[1] is the length)
                    const char * title = (const char *)&(sample[2]);
+                  if (sample == NULL) {
+                                        ...
+                     }
                    int titleLen = min((uint32_t)((sample[0] << 8) | sample[1]), (uint32_t)MP4V2_CHAPTER_TITLE_MAX);
                    strncpy(chapters[i].title, title, titleLen);
                    chapters[i].title[titleLen] = 0;

ty

@mugichiya
Copy link
Author

mugichiya commented Sep 21, 2024

I also found heap-based buffer overflow in mp4file.cpp:2662.

PoC

See testcases.

git clone https://github.com/mugichiya/pockey.git
cp -r ./pockey/projects/mp4v2_hof/testcases .
./mp4chaps --list ./testcases/0000000000.mp4

ASAN output

banjo@ttc:/opt/mp4v2/build$ ./mp4chaps --list ../../0000000000.mp4 
ReadAtom: "../../0000000000.mp4": invalid atom size, extends outside parent atom - skipping to end of "stbl" "stco" 150996203 vs 1279
=================================================================
==5147==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000003b11 at pc 0x7f562f5e80f7 bp 0x7ffe6f3c6680 sp 0x7ffe6f3c6670
READ of size 1 at 0x602000003b11 thread T0
    #0 0x7f562f5e80f6 in mp4v2::impl::MP4File::GetChapters(MP4Chapter_s**, unsigned int*, MP4ChapterType) /opt/mp4v2/src/mp4file.cpp:2662
    #1 0x7f562f5b7177 in MP4GetChapters /opt/mp4v2/src/mp4.cpp:1647
    #2 0x555e9921415a in mp4v2::util::ChapterUtility::actionList(mp4v2::util::Utility::JobContext&) /opt/mp4v2/util/mp4chaps.cpp:182
    #3 0x555e9921a581 in mp4v2::util::ChapterUtility::utility_job(mp4v2::util::Utility::JobContext&) /opt/mp4v2/util/mp4chaps.cpp:664
    #4 0x7f562f4e44c5 in mp4v2::util::Utility::job(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) /opt/mp4v2/libutil/Utility.cpp:298
    #5 0x7f562f4e2595 in mp4v2::util::Utility::batch(int) /opt/mp4v2/libutil/Utility.cpp:105
    #6 0x7f562f4e718d in mp4v2::util::Utility::process_impl() /opt/mp4v2/libutil/Utility.cpp:565
    #7 0x7f562f4e6252 in mp4v2::util::Utility::process() /opt/mp4v2/libutil/Utility.cpp:449
    #8 0x555e9921d794 in main /opt/mp4v2/util/mp4chaps.cpp:1188
    #9 0x7f562edf0082 in __libc_start_main ../csu/libc-start.c:308
    #10 0x555e9921012d in _start (/opt/mp4v2/build2/mp4chaps+0xf12d)

0x602000003b11 is located 0 bytes to the right of 1-byte region [0x602000003b10,0x602000003b11)
allocated by thread T0 here:
    #0 0x7f562f948808 in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cc:144
    #1 0x7f562f4d9392 in mp4v2::impl::MP4Malloc(unsigned long) /opt/mp4v2/src/mp4util.h:63
    #2 0x7f562f615dbc in mp4v2::impl::MP4Track::ReadSample(unsigned int, unsigned char**, unsigned int*, unsigned long*, unsigned long*, unsigned long*, bool*, bool*, unsigned int*) /opt/mp4v2/src/mp4track.cpp:323
    #3 0x7f562f5e8016 in mp4v2::impl::MP4File::GetChapters(MP4Chapter_s**, unsigned int*, MP4ChapterType) /opt/mp4v2/src/mp4file.cpp:2655
    #4 0x7f562f5b7177 in MP4GetChapters /opt/mp4v2/src/mp4.cpp:1647
    #5 0x555e9921415a in mp4v2::util::ChapterUtility::actionList(mp4v2::util::Utility::JobContext&) /opt/mp4v2/util/mp4chaps.cpp:182
    #6 0x555e9921a581 in mp4v2::util::ChapterUtility::utility_job(mp4v2::util::Utility::JobContext&) /opt/mp4v2/util/mp4chaps.cpp:664
    #7 0x7f562f4e44c5 in mp4v2::util::Utility::job(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) /opt/mp4v2/libutil/Utility.cpp:298
    #8 0x7f562f4e2595 in mp4v2::util::Utility::batch(int) /opt/mp4v2/libutil/Utility.cpp:105
    #9 0x7f562f4e718d in mp4v2::util::Utility::process_impl() /opt/mp4v2/libutil/Utility.cpp:565
    #10 0x7f562f4e6252 in mp4v2::util::Utility::process() /opt/mp4v2/libutil/Utility.cpp:449
    #11 0x555e9921d794 in main /opt/mp4v2/util/mp4chaps.cpp:1188
    #12 0x7f562edf0082 in __libc_start_main ../csu/libc-start.c:308

SUMMARY: AddressSanitizer: heap-buffer-overflow /opt/mp4v2/src/mp4file.cpp:2662 in mp4v2::impl::MP4File::GetChapters(MP4Chapter_s**, unsigned int*, MP4ChapterType)
Shadow bytes around the buggy address:
  0x0c047fff8710: fa fa 04 fa fa fa 04 fa fa fa fd fa fa fa fd fd
  0x0c047fff8720: fa fa fd fa fa fa fd fa fa fa fd fa fa fa 04 fa
  0x0c047fff8730: fa fa 04 fa fa fa 04 fa fa fa 04 fa fa fa 01 fa
  0x0c047fff8740: fa fa fd fd fa fa 04 fa fa fa 04 fa fa fa fd fa
  0x0c047fff8750: fa fa 00 00 fa fa 04 fa fa fa 00 fa fa fa 00 00
=>0x0c047fff8760: fa fa[01]fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8770: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8780: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8790: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff87a0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff87b0: 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
==5147==ABORTING

ty

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

1 participant