[FFmpeg-trac] #9004(avcodec:new): TSAN reports heap-user-after-free in ff_h2645_extract_rbsp

FFmpeg trac at avcodec.org
Mon Nov 23 17:54:40 EET 2020


#9004: TSAN reports heap-user-after-free in ff_h2645_extract_rbsp
-------------------------------------+-------------------------------------
             Reporter:  jsierant-    |                     Type:  defect
  at-vewd                            |
               Status:  new          |                 Priority:  normal
            Component:  avcodec      |                  Version:
                                     |  unspecified
             Keywords:               |               Blocked By:
             Blocking:               |  Reproduced by developer:  0
Analyzed by developer:  0            |
-------------------------------------+-------------------------------------
 The problem has been detected in FFmpeg for the chromium project and is
 reproducable with following code:

 {{{
 std::vector<std::uint8_t> bitstream = {
     0x00, 0x00, 0x00, 0x01, 0x02, 0x01, 0xE0, 0x64, 0x9D, 0x78, 0x24,
 0x72,
     0x72, 0x19, 0x9E, 0x40, 0xF5, 0x24, 0x0F, 0x81, 0xE4, 0x1B, 0xA8,
 0x87,
     0xB3, 0xCF, 0x84, 0x10, 0x60, 0xFE, 0x1C, 0x5F, 0x80, 0x00, 0x08,
 0xE8,
     0x5A, 0x00, 0x02, 0x7E, 0x61, 0x80, 0x20, 0x60, 0x67, 0x00, 0xCD,
 0x80,
     0x5D, 0xC5, 0x59, 0x83, 0x44, 0x75, 0x51, 0xC1, 0xEB, 0x24, 0xFF,
 0x64,
     0x2F, 0x0D, 0xF2, 0xC5, 0x60, 0x15, 0x21, 0x19};

 static const int kIsNalff = 0;
 static const int kNalLengthSize = 2;
 static const int kSmallPadding = 1;
 static const int kUseRef = 0;

 ::H2645Packet packet{};
 ::AVCodecContext context{};
 ::ff_h2645_packet_split(&packet, bitstream.data(), bitstream.size(),
 &context,
                         kIsNalff, kNalLengthSize, AV_CODEC_ID_HEVC,
                         kSmallPadding, kUseRef);
 }}}

 TSAN report:
 {{{
 WARNING: ThreadSanitizer: heap-use-after-free (pid=422689)
   Read of size 1 at 0x7b140000a958 by main thread:
     #0 ff_h2645_extract_rbsp
 third_party/ffmpeg/libavcodec/h2645_parse.c:57:17 (libffmpeg.so+0x2d12f7)
     #1 ff_h2645_packet_split
 third_party/ffmpeg/libavcodec/h2645_parse.c:485:20 (libffmpeg.so+0x2d21af)
     #2 media::FFmpegHevcTest_NalSplit_Test::TestBody()
 media/ffmpeg/ffmpeg_common_unittest.cc:396:3 (media_unittests+0x14a0039)
     #3 void
 testing::internal::HandleExceptionsInMethodIfSupported<testing::Test,
 void>(testing::Test*, void (testing::Test::*)(), char const*)
 third_party/googletest/src/googletest/src/gtest.cc
 (media_unittests+0x15225ed)
     #4 testing::Test::Run()
 third_party/googletest/src/googletest/src/gtest.cc:2689:5
 (media_unittests+0x1522548)
     #5 testing::TestInfo::Run()
 third_party/googletest/src/googletest/src/gtest.cc:2866:11
 (media_unittests+0x1522f9c)
     #6 testing::TestSuite::Run()
 third_party/googletest/src/googletest/src/gtest.cc:3020:28
 (media_unittests+0x1523ac6)
     #7 testing::internal::UnitTestImpl::RunAllTests()
 third_party/googletest/src/googletest/src/gtest.cc:5730:44
 (media_unittests+0x152bf1f)
     #8 bool
 testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl,
 bool>(testing::internal::UnitTestImpl*, bool
 (testing::internal::UnitTestImpl::*)(), char const*)
 third_party/googletest/src/googletest/src/gtest.cc
 (media_unittests+0x152bb79)
     #9 testing::UnitTest::Run()
 third_party/googletest/src/googletest/src/gtest.cc:5313:10
 (media_unittests+0x152ba64)
     #10 RUN_ALL_TESTS()
 third_party/googletest/src/googletest/include/gtest/gtest.h:2485:46
 (media_unittests+0x1fdcb1f)
     #11 base::TestSuite::Run() base/test/test_suite.cc:480:16
 (media_unittests+0x1fdc48b)
     #12 Invoke<int (base::TestSuite::*)(), TestSuiteNoAtExit *>
 base/bind_internal.h:498:12 (media_unittests+0x1483c14)
     #13 int base::internal::InvokeHelper<false, int>::MakeItSo<int
 (base::TestSuite::*)(), TestSuiteNoAtExit*>(int (base::TestSuite::*&&)(),
 TestSuiteNoAtExit*&&) base/bind_internal.h:637:12
 (media_unittests+0x1483c14)
     #14 int base::internal::Invoker<base::internal::BindState<int
 (base::TestSuite::*)(),
 base::internal::UnretainedWrapper<TestSuiteNoAtExit> >, int
 ()>::RunImpl<int (base::TestSuite::*)(),
 std::tuple<base::internal::UnretainedWrapper<TestSuiteNoAtExit> >,
 0ul>(int (base::TestSuite::*&&)(),
 std::tuple<base::internal::UnretainedWrapper<TestSuiteNoAtExit> >&&,
 std::integer_sequence<unsigned long, 0ul>) base/bind_internal.h:710:12
 (media_unittests+0x1483b9d)
     #15 base::internal::Invoker<base::internal::BindState<int
 (base::TestSuite::*)(),
 base::internal::UnretainedWrapper<TestSuiteNoAtExit> >, int
 ()>::RunOnce(base::internal::BindStateBase*) base/bind_internal.h:679:12
 (media_unittests+0x1483b58)
     #16 base::OnceCallback<int ()>::Run() && base/callback.h:100:12
 (media_unittests+0x1b96a63)
     #17 base::(anonymous
 namespace)::LaunchUnitTestsInternal(base::OnceCallback<int ()>, unsigned
 long, int, unsigned long, bool, base::OnceCallback<void ()>)
 base/test/launcher/unit_test_launcher.cc:179:38
 (media_unittests+0x200183d)
     #18 base::LaunchUnitTests(int, char**, base::OnceCallback<int ()>,
 unsigned long) base/test/launcher/unit_test_launcher.cc:249:10
 (media_unittests+0x20016d3)
     #19 main media/test/run_all_unittests.cc:55:10
 (media_unittests+0x14839a6)

   Previous write of size 8 at 0x7b140000a958 by main thread:
     #0 operator delete(void*)
 /home/jenkins/shared_ws/opera_work_0/chromium/src/third_party/llvm
 /compiler-rt/lib/tsan/rtl/tsan_new_delete.cpp:126:3
 (media_unittests+0xe4edde)
     #1 ~basic_string
 tc_cache_workdir/x86_64-gcc5-4.22-2020-10-28-c3cf13530b5fd448252afe7097a212ec/lib/gcc/x86_64
 -linux-gnu/5.5.0/../../../../include/c++/5.5.0/bits/basic_string.h:559:9
 (media_unittests+0x151e917)
     #2
 testing::internal::UnitTestOptions::FilterMatchesTest(std::__cxx11::basic_string<char,
 std::char_traits<char>, std::allocator<char> > const&,
 std::__cxx11::basic_string<char, std::char_traits<char>,
 std::allocator<char> > const&)
 third_party/googletest/src/googletest/src/gtest.cc:727:1
 (media_unittests+0x151e917)
     #3
 testing::internal::UnitTestImpl::FilterTests(testing::internal::UnitTestImpl::ReactionToSharding)
 third_party/googletest/src/googletest/src/gtest.cc:5918:35
 (media_unittests+0x152d9d6)
     #4 testing::internal::UnitTestImpl::RunAllTests()
 third_party/googletest/src/googletest/src/gtest.cc:5658:33
 (media_unittests+0x152bc23)
     #5 bool
 testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl,
 bool>(testing::internal::UnitTestImpl*, bool
 (testing::internal::UnitTestImpl::*)(), char const*)
 third_party/googletest/src/googletest/src/gtest.cc
 (media_unittests+0x152bb79)
     #6 testing::UnitTest::Run()
 third_party/googletest/src/googletest/src/gtest.cc:5313:10
 (media_unittests+0x152ba64)
     #7 RUN_ALL_TESTS()
 third_party/googletest/src/googletest/include/gtest/gtest.h:2485:46
 (media_unittests+0x1fdcb1f)
     #8 base::TestSuite::Run() base/test/test_suite.cc:480:16
 (media_unittests+0x1fdc48b)
     #9 Invoke<int (base::TestSuite::*)(), TestSuiteNoAtExit *>
 base/bind_internal.h:498:12 (media_unittests+0x1483c14)
     #10 int base::internal::InvokeHelper<false, int>::MakeItSo<int
 (base::TestSuite::*)(), TestSuiteNoAtExit*>(int (base::TestSuite::*&&)(),
 TestSuiteNoAtExit*&&) base/bind_internal.h:637:12
 (media_unittests+0x1483c14)
     #11 int base::internal::Invoker<base::internal::BindState<int
 (base::TestSuite::*)(),
 base::internal::UnretainedWrapper<TestSuiteNoAtExit> >, int
 ()>::RunImpl<int (base::TestSuite::*)(),
 std::tuple<base::internal::UnretainedWrapper<TestSuiteNoAtExit> >,
 0ul>(int (base::TestSuite::*&&)(),
 std::tuple<base::internal::UnretainedWrapper<TestSuiteNoAtExit> >&&,
 std::integer_sequence<unsigned long, 0ul>) base/bind_internal.h:710:12
 (media_unittests+0x1483b9d)
     #12 base::internal::Invoker<base::internal::BindState<int
 (base::TestSuite::*)(),
 base::internal::UnretainedWrapper<TestSuiteNoAtExit> >, int
 ()>::RunOnce(base::internal::BindStateBase*) base/bind_internal.h:679:12
 (media_unittests+0x1483b58)
     #13 base::OnceCallback<int ()>::Run() && base/callback.h:100:12
 (media_unittests+0x1b96a63)
     #14 base::(anonymous
 namespace)::LaunchUnitTestsInternal(base::OnceCallback<int ()>, unsigned
 long, int, unsigned long, bool, base::OnceCallback<void ()>)
 base/test/launcher/unit_test_launcher.cc:179:38
 (media_unittests+0x200183d)
     #15 base::LaunchUnitTests(int, char**, base::OnceCallback<int ()>,
 unsigned long) base/test/launcher/unit_test_launcher.cc:249:10
 (media_unittests+0x20016d3)
     #16 main media/test/run_all_unittests.cc:55:10
 (media_unittests+0x14839a6)

   Location is heap block of size 68 at 0x7b140000a910 allocated by main
 thread:
     #0 operator new(unsigned long)
 /home/jenkins/shared_ws/opera_work_0/chromium/src/third_party/llvm
 /compiler-rt/lib/tsan/rtl/tsan_new_delete.cpp:64:3
 (media_unittests+0xe4e726)
     #1 allocate
 tc_cache_workdir/x86_64-gcc5-4.22-2020-10-28-c3cf13530b5fd448252afe7097a212ec/lib/gcc/x86_64
 -linux-gnu/5.5.0/../../../../include/c++/5.5.0/ext/new_allocator.h:104:27
 (media_unittests+0x10234a2)
     #2 allocate
 tc_cache_workdir/x86_64-gcc5-4.22-2020-10-28-c3cf13530b5fd448252afe7097a212ec/lib/gcc/x86_64
 -linux-gnu/5.5.0/../../../../include/c++/5.5.0/bits/alloc_traits.h:491:20
 (media_unittests+0x10234a2)
     #3 std::_Vector_base<unsigned char, std::allocator<unsigned char>
 >::_M_allocate(unsigned long)
 tc_cache_workdir/x86_64-gcc5-4.22-2020-10-28-c3cf13530b5fd448252afe7097a212ec/lib/gcc/x86_64
 -linux-gnu/5.5.0/../../../../include/c++/5.5.0/bits/stl_vector.h:170:20
 (media_unittests+0x10234a2)
     #4 void std::vector<unsigned char, std::allocator<unsigned char>
 >::_M_range_initialize<unsigned char const*>(unsigned char const*,
 unsigned char const*, std::forward_iterator_tag)
 tc_cache_workdir/x86_64-gcc5-4.22-2020-10-28-c3cf13530b5fd448252afe7097a212ec/lib/gcc/x86_64
 -linux-gnu/5.5.0/../../../../include/c++/5.5.0/bits/stl_vector.h:1287:35
 (media_unittests+0x10c2e8b)
     #5 vector
 tc_cache_workdir/x86_64-gcc5-4.22-2020-10-28-c3cf13530b5fd448252afe7097a212ec/lib/gcc/x86_64
 -linux-gnu/5.5.0/../../../../include/c++/5.5.0/bits/stl_vector.h:377:2
 (media_unittests+0x149ffeb)
     #6 media::FFmpegHevcTest_NalSplit_Test::TestBody()
 media/ffmpeg/ffmpeg_common_unittest.cc:381:41 (media_unittests+0x149ffeb)
     #7 void
 testing::internal::HandleExceptionsInMethodIfSupported<testing::Test,
 void>(testing::Test*, void (testing::Test::*)(), char const*)
 third_party/googletest/src/googletest/src/gtest.cc
 (media_unittests+0x15225ed)
     #8 testing::Test::Run()
 third_party/googletest/src/googletest/src/gtest.cc:2689:5
 (media_unittests+0x1522548)
     #9 testing::TestInfo::Run()
 third_party/googletest/src/googletest/src/gtest.cc:2866:11
 (media_unittests+0x1522f9c)
     #10 testing::TestSuite::Run()
 third_party/googletest/src/googletest/src/gtest.cc:3020:28
 (media_unittests+0x1523ac6)
     #11 testing::internal::UnitTestImpl::RunAllTests()
 third_party/googletest/src/googletest/src/gtest.cc:5730:44
 (media_unittests+0x152bf1f)
     #12 bool
 testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl,
 bool>(testing::internal::UnitTestImpl*, bool
 (testing::internal::UnitTestImpl::*)(), char const*)
 third_party/googletest/src/googletest/src/gtest.cc
 (media_unittests+0x152bb79)
     #13 testing::UnitTest::Run()
 third_party/googletest/src/googletest/src/gtest.cc:5313:10
 (media_unittests+0x152ba64)
     #14 RUN_ALL_TESTS()
 third_party/googletest/src/googletest/include/gtest/gtest.h:2485:46
 (media_unittests+0x1fdcb1f)
     #15 base::TestSuite::Run() base/test/test_suite.cc:480:16
 (media_unittests+0x1fdc48b)
     #16 Invoke<int (base::TestSuite::*)(), TestSuiteNoAtExit *>
 base/bind_internal.h:498:12 (media_unittests+0x1483c14)
     #17 int base::internal::InvokeHelper<false, int>::MakeItSo<int
 (base::TestSuite::*)(), TestSuiteNoAtExit*>(int (base::TestSuite::*&&)(),
 TestSuiteNoAtExit*&&) base/bind_internal.h:637:12
 (media_unittests+0x1483c14)
     #18 int base::internal::Invoker<base::internal::BindState<int
 (base::TestSuite::*)(),
 base::internal::UnretainedWrapper<TestSuiteNoAtExit> >, int
 ()>::RunImpl<int (base::TestSuite::*)(),
 std::tuple<base::internal::UnretainedWrapper<TestSuiteNoAtExit> >,
 0ul>(int (base::TestSuite::*&&)(),
 std::tuple<base::internal::UnretainedWrapper<TestSuiteNoAtExit> >&&,
 std::integer_sequence<unsigned long, 0ul>) base/bind_internal.h:710:12
 (media_unittests+0x1483b9d)
     #19 base::internal::Invoker<base::internal::BindState<int
 (base::TestSuite::*)(),
 base::internal::UnretainedWrapper<TestSuiteNoAtExit> >, int
 ()>::RunOnce(base::internal::BindStateBase*) base/bind_internal.h:679:12
 (media_unittests+0x1483b58)
     #20 base::OnceCallback<int ()>::Run() && base/callback.h:100:12
 (media_unittests+0x1b96a63)
     #21 base::(anonymous
 namespace)::LaunchUnitTestsInternal(base::OnceCallback<int ()>, unsigned
 long, int, unsigned long, bool, base::OnceCallback<void ()>)
 base/test/launcher/unit_test_launcher.cc:179:38
 (media_unittests+0x200183d)
     #22 base::LaunchUnitTests(int, char**, base::OnceCallback<int ()>,
 unsigned long) base/test/launcher/unit_test_launcher.cc:249:10
 (media_unittests+0x20016d3)
     #23 main media/test/run_all_unittests.cc:55:10
 (media_unittests+0x14839a6)

 SUMMARY: ThreadSanitizer: heap-use-after-free
 third_party/ffmpeg/libavcodec/h2645_parse.c:57:17 in ff_h2645_extract_rbsp
 }}}

 The problem originates in ff_h2645_extract_rbsp (line 57 has been marked):

 {{{
 #if HAVE_FAST_64BIT
     for (i = 0; i + 1 < length; i += 9) {
         if (!((~AV_RN64(src + i) & // line 57
                (AV_RN64(src + i) - 0x0100010001000101ULL)) &
               0x8000800080008080ULL))
             continue;
         FIND_FIRST_ZERO;
         STARTCODE_TEST;
         i -= 7;
     }
 #else
 }}}

 It seems that when the optimizations are enabled
 ({{{HAVE_FAST_UNALIGNED}}} and {{{HAVE_FAST_64BIT}}} are set) the size of
 the provided data {{{src}}} is exceeded (despite that {{{length}}} = 68,
 byte 72 is read (calculated as 0x7b140000a958 - 0x7b140000a910)).
 The same problem will probably be visible when HAVE_FAST_64BIT is not set
 as the algorithm is the same for 32 bits machines.

 Accessing memory outside of allocated space may lead to segmentation fault
 and an abnormal termination of the process.

 The FFmpeg version that has been used is:
 Upstream Git: git://source.ffmpeg.org/ffmpeg.git
 Last Upstream Merge: 71ec3e4583def61fbb32a4815376773ef7c80dee, Aug 27 2020

 The code seems to be same as in latest FFmpeg release (4.3.1) so the
 problem should also be visible there.

--
Ticket URL: <https://trac.ffmpeg.org/ticket/9004>
FFmpeg <https://ffmpeg.org>
FFmpeg issue tracker


More information about the FFmpeg-trac mailing list