New issue
Advanced search Search tips

Issue 889356 link

Starred by 1 user

Issue metadata

Status: Fixed
Owner:
Closed: Sep 29
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: Linux , Android , Windows , Chrome , Mac
Pri: 1
Type: Bug



Sign in to add a comment

Security: Out-Of-Bounds Write in RunLengthDecode

Reported by zhouzhen...@gmail.com, Sep 26

Issue description

VULNERABILITY DETAILS
This issue was found by fuzzing against a 64-bit asan linux build of pdfium_test.

RunLengthDecode in fpdf_parser_decode.cpp:

-----------------------------------
  size_t i = 0;
  *dest_size = 0;
  while (i < src_span.size()) {
    if (src_span[i] == 128)
      break;

    uint32_t old = *dest_size;
    if (src_span[i] < 128) {
      *dest_size += src_span[i] + 1;
      if (*dest_size < old)
        return FX_INVALID_OFFSET;
      i += src_span[i] + 2;
    } else {
      *dest_size += 257 - src_span[i];
      if (*dest_size < old)
        return FX_INVALID_OFFSET;
      i += 2;
    }
  }
-------------------------------------

run the poc, the dest_size is 2623, then do some alloc, copy buffer

-------------------------------------

  *dest_buf = FX_Alloc(uint8_t, *dest_size);
  i = 0;
  int dest_count = 0;
  while (i < src_span.size()) {
    if (src_span[i] == 128)
      break;

    if (src_span[i] < 128) {
      uint32_t copy_len = src_span[i] + 1;
      uint32_t buf_left = src_span.size() - i - 1;
      if (buf_left < copy_len) {
        uint32_t delta = copy_len - buf_left;
        copy_len = buf_left;
        memset(*dest_buf + dest_count + copy_len, '\0', delta);
      }
      memcpy(*dest_buf + dest_count, &src_span[i + 1], copy_len); // <--- out of bounds write here. copy_len is larger than 2623 - dest_count
      dest_count += src_span[i] + 1;
      i += src_span[i] + 2;
    } else {
      int fill = 0;
      if (i < src_span.size() - 1)
        fill = src_span[i + 1];
      memset(*dest_buf + dest_count, fill, 257 - src_span[i]);
      dest_count += 257 - src_span[i];
      i += 2;
    }
  }
------------------------------

VERSION
Chrome Version: asan-linux-beta-70.0.3538.16
Operating System: Fedora 28 x86_64

REPRODUCTION CASE
./pdfium_test tests_6376f0dfe1b3796a5e5d31958269ac01152cc567

Rendering PDF file tests_6376f0dfe1b3796a5e5d31958269ac01152cc567.
AddressSanitizer:DEADLYSIGNAL
=================================================================
==22091==ERROR: AddressSanitizer: ABRT on unknown address 0x03e80000564b (pc 0x7f96c3a8ceab bp 0x7fff16942c30 sp 0x7fff16942990 T0)
SCARINESS: 10 (signal)
    #0 0x7f96c3a8ceaa in __GI_raise (/lib64/libc.so.6+0x36eaa)
    #1 0x7f96c3a775b8 in __GI_abort (/lib64/libc.so.6+0x215b8)
    #2 0x2c35479 in RunLengthDecode(pdfium::span<unsigned char const>, unsigned char**, unsigned int*) third_party/pdfium/core/fpdfapi/parser/fpdf_parser_decode.cpp
    #3 0x2ba1446 in DecodeInlineStream third_party/pdfium/core/fpdfapi/page/cpdf_streamparser.cpp:95:12
    #4 0x2ba1446 in CPDF_StreamParser::ReadInlineStream(CPDF_Document*, std::__1::unique_ptr<CPDF_Dictionary, std::__1::default_delete<CPDF_Dictionary> >, CPDF_Object const*) third_party/pdfium/core/fpdfapi/page/cpdf_streamparser.cpp:186
    #5 0x2b77dab in CPDF_StreamContentParser::Handle_BeginImage() third_party/pdfium/core/fpdfapi/page/cpdf_streamcontentparser.cpp:671:18
    #6 0x2b94bb9 in CPDF_StreamContentParser::Parse(unsigned char const*, unsigned int, unsigned int, std::__1::vector<unsigned int, std::__1::allocator<unsigned int> > const&) third_party/pdfium/core/fpdfapi/page/cpdf_streamcontentparser.cpp:1536:9
    #7 0x2b4599d in CPDF_ContentParser::Parse() third_party/pdfium/core/fpdfapi/page/cpdf_contentparser.cpp:211:33
    #8 0x2b4463a in CPDF_ContentParser::Continue(PauseIndicatorIface*) third_party/pdfium/core/fpdfapi/page/cpdf_contentparser.cpp:133:22
    #9 0x2b5b328 in CPDF_PageObjectHolder::ContinueParse(PauseIndicatorIface*) third_party/pdfium/core/fpdfapi/page/cpdf_pageobjectholder.cpp:59:18
    #10 0x2b59048 in CPDF_Page::ParseContent() third_party/pdfium/core/fpdfapi/page/cpdf_page.cpp:110:3
    #11 0x291868b in FPDF_LoadPage third_party/pdfium/fpdfsdk/fpdf_view.cpp:351:10
    #12 0xb97407 in (anonymous namespace)::GetPageForIndex(_FPDF_FORMFILLINFO*, fpdf_document_t__*, int) third_party/pdfium/samples/pdfium_test.cc:502:23
    #13 0xb91350 in RenderPage third_party/pdfium/samples/pdfium_test.cc:530:20
    #14 0xb91350 in RenderPdf third_party/pdfium/samples/pdfium_test.cc:773
    #15 0xb91350 in main third_party/pdfium/samples/pdfium_test.cc:948
    #16 0x7f96c3a7911a in __libc_start_main (/lib64/libc.so.6+0x2311a)
    #17 0xab5029 in _start (/home/henices/research/asan-linux-beta-70.0.3538.16/pdfium_test+0xab5029)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: ABRT (/lib64/libc.so.6+0x36eaa) in __GI_raise
==22091==ABORTING

testcase is in the attachment.

 
tests_6376f0dfe1b3796a5e5d31958269ac01152cc567
48.6 KB View Download
Cc: thestig@chromium.org tsepez@chromium.org
Components: Internals>Plugins>PDF
Labels: Security_Severity-High Security_Impact-Head OS-Android OS-Chrome OS-Linux OS-Mac OS-Windows Pri-1
Owner: rharrison@chromium.org
Status: Assigned (was: Unconfirmed)
+pdf folks to take a look.
it reproduced on beta (m70), but didn't reproduce on stable (m69)
try to minimize the testcase.

~/research/asan-linux-beta-70.0.3538.16/pdfium_test ./min.pdf                                                                                                                     
Rendering PDF file ./min.pdf.                                                                                                                                                                
AddressSanitizer:DEADLYSIGNAL                                                                                                                                                                
=================================================================                 
==17134==ERROR: AddressSanitizer: ABRT on unknown address 0x03e8000042ee (pc 0x7f5c35f80eab bp 0x7fff0011ea90 sp 0x7fff0011e7f0 T0)                                                          
SCARINESS: 10 (signal)                                                         
    #0 0x7f5c35f80eaa in __GI_raise (/lib64/libc.so.6+0x36eaa)             
    #1 0x7f5c35f6b5b8 in __GI_abort (/lib64/libc.so.6+0x215b8)        
    #2 0x2c35479 in RunLengthDecode(pdfium::span<unsigned char const>, unsigned char**, unsigned int*) third_party/pdfium/core/fpdfapi/parser/fpdf_parser_decode.cpp
    #3 0x2ba1446 in DecodeInlineStream third_party/pdfium/core/fpdfapi/page/cpdf_streamparser.cpp:95:12                                                                                      
    #4 0x2ba1446 in CPDF_StreamParser::ReadInlineStream(CPDF_Document*, std::__1::unique_ptr<CPDF_Dictionary, std::__1::default_delete<CPDF_Dictionary> >, CPDF_Object const*) third_party/pdf
ium/core/fpdfapi/page/cpdf_streamparser.cpp:186  
    #5 0x2b77dab in CPDF_StreamContentParser::Handle_BeginImage() third_party/pdfium/core/fpdfapi/page/cpdf_streamcontentparser.cpp:671:18
    #6 0x2b94bb9 in CPDF_StreamContentParser::Parse(unsigned char const*, unsigned int, unsigned int, std::__1::vector<unsigned int, std::__1::allocator<unsigned int> > const&) third_party/p
dfium/core/fpdfapi/page/cpdf_streamcontentparser.cpp:1536:9
    #7 0x2b4599d in CPDF_ContentParser::Parse() third_party/pdfium/core/fpdfapi/page/cpdf_contentparser.cpp:211:33
    #8 0x2b4463a in CPDF_ContentParser::Continue(PauseIndicatorIface*) third_party/pdfium/core/fpdfapi/page/cpdf_contentparser.cpp:133:22
    #9 0x2b5b328 in CPDF_PageObjectHolder::ContinueParse(PauseIndicatorIface*) third_party/pdfium/core/fpdfapi/page/cpdf_pageobjectholder.cpp:59:18
    #10 0x2b59048 in CPDF_Page::ParseContent() third_party/pdfium/core/fpdfapi/page/cpdf_page.cpp:110:3
    #11 0x291868b in FPDF_LoadPage third_party/pdfium/fpdfsdk/fpdf_view.cpp:351:10
    #12 0xb97407 in (anonymous namespace)::GetPageForIndex(_FPDF_FORMFILLINFO*, fpdf_document_t__*, int) third_party/pdfium/samples/pdfium_test.cc:502:23
    #13 0xb91350 in RenderPage third_party/pdfium/samples/pdfium_test.cc:530:20
    #14 0xb91350 in RenderPdf third_party/pdfium/samples/pdfium_test.cc:773
    #15 0xb91350 in main third_party/pdfium/samples/pdfium_test.cc:948
    #16 0x7f5c35f6d11a in __libc_start_main (/lib64/libc.so.6+0x2311a)
    #17 0xab5029 in _start (/home/henices/research/asan-linux-beta-70.0.3538.16/pdfium_test+0xab5029)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: ABRT (/lib64/libc.so.6+0x36eaa) in __GI_raise
==17134==ABORTING

min.pdf
376 bytes Download
Labels: -Security_Impact-Head Security_Impact-Beta
Labels: M-70
Project Member

Comment 6 by sheriffbot@chromium.org, Sep 26

Labels: ReleaseBlock-Stable
This is a serious security regression. If you are not able to fix this quickly, please revert the change that introduced it.

If this doesn't affect a release branch, or has not been properly classified for severity, please update the Security_Impact or Security_Severity labels, and remove the ReleaseBlock label. To disable this altogether, apply ReleaseBlock-NA.

For more details visit https://www.chromium.org/issue-tracking/autotriage - Your friendly Sheriffbot
This issue is present on the M70 branch, but PDFium's current HEAD works fine.
https://pdfium-review.googlesource.com/41930 fixed it, so this is likely a duplicate of  bug 879910 . We probably should merge the fix to the M70 branch.

Also, I'm not sure there is an OOB write here. ASAN hit a SIGABRT, and did not print out the usual memory map to show where the bad write is. It's actually an out of bound read on |src_span|, but because it is a pdfium::base::span and not a raw array, span's operator[] ensures the OOB access does not happen.
Owner: tsepez@chromium.org
compared to  bug 879910 , back trace is slightly different.

I'm also confused why ASAN is hit a SIGABRT, so i used gdb to debug.
When debugging i found OOB write in memcpy ( comment #1 ), but it didn't crash immediately.
Because I didn't minimize the testcase at that time, too many next was
needed, so I submitted it first.

This issue can cause OOB write many times, ASAN report code might not
work correctly. If I have time i will look into it.


As I explained, you are hitting the CHECK() here. [1] ASAN stack traces are not always the most accurate. If you do a normal debug pdfium_test build, gdb can give a better stack trace.

[1] https://pdfium.googlesource.com/pdfium.git/+/072d829e2cd1586645022498a01a61db83a2db4d/third_party/base/span.h#247
I found a strange problem in my gdb, asan is right, no OOB write here.

This testcase is just hitting CHECK() in

https://pdfium.googlesource.com/pdfium.git/+/072d829e2cd1586645022498a01a61db83a2db4d/third_party/base/span.h#247

Sorry for my mistake. 
Labels: -Security_Severity-High Security_Severity-Medium
Dropping severity since it's not an OOB write. It would be good to merge the fix to M70.
Do we need a merge request here?
Project Member

Comment 16 by sheriffbot@chromium.org, Sep 28

Labels: -Merge-Request-70 Merge-Review-70 Hotlist-Merge-Review
This bug requires manual review: M70 has already been promoted to the beta branch, so this requires manual review
Please contact the milestone owner if you have questions.
Owners: benmason@(Android), kariahda@(iOS), geohsu@(ChromeOS), abdulsyed@(Desktop)

For more details visit https://www.chromium.org/issue-tracking/autotriage - Your friendly Sheriffbot
Project Member

Comment 17 by sheriffbot@chromium.org, Sep 29

Status: Fixed (was: Assigned)
Please mark security bugs as fixed as soon as the fix lands, and before requesting merges. This update is based on the merge- labels applied to this issue. Please reopen if this update was incorrect.

For more details visit https://www.chromium.org/issue-tracking/autotriage - Your friendly Sheriffbot
Project Member

Comment 18 by sheriffbot@chromium.org, Sep 30

Labels: -Restrict-View-SecurityTeam Restrict-View-SecurityNotify
Labels: -Merge-Review-70 Merge-Approved-70
branch:3538
Project Member

Comment 20 by bugdroid1@chromium.org, Oct 1

Labels: -merge-approved-70 merge-merged-3538
The following revision refers to this bug:
  https://pdfium.googlesource.com/pdfium/+/13b08aa11de74120909b871b987d010f33cd0bc6

commit 13b08aa11de74120909b871b987d010f33cd0bc6
Author: Lei Zhang <thestig@chromium.org>
Date: Mon Oct 01 17:47:52 2018

M70: Avoid CHECK in fpdf_parser_decode.cpp (memcpy empty span)

Given a span of size N, memcpy(dest, &span[N], 0) ought to be a no-op,
but since we compute span[N] before checking for zero length, we hit
an assert. The correct idiom should be to create a sub-span, which
allows specifying N, but only when the size is 0.

Bug:  chromium:879910 , chromium:889356 
Change-Id: Ic6f368109a5c2f1e13a5f638c6a233769e2ad41b
Reviewed-on: https://pdfium-review.googlesource.com/41930
Commit-Queue: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
(cherry picked from commit 73e97f4fac2f4f591ff62e70377a80fd40b5f6f3)
Reviewed-on: https://pdfium-review.googlesource.com/43271

[modify] https://crrev.com/13b08aa11de74120909b871b987d010f33cd0bc6/core/fpdfapi/parser/fpdf_parser_decode.cpp

Labels: reward-topanel
Labels: -ReleaseBlock-Stable
Labels: -Type-Bug-Security -Security_Severity-Medium -Security_Impact-Beta Type-Bug
VRP panel look a look and agreed this isn't a security bug.
Labels: -reward-topanel reward-0
Project Member

Comment 25 by sheriffbot@chromium.org, Jan 5

Labels: -Restrict-View-SecurityNotify allpublic
This bug has been closed for more than 14 weeks. Removing security view restrictions.

For more details visit https://www.chromium.org/issue-tracking/autotriage - Your friendly Sheriffbot

Sign in to add a comment