New issue
Advanced search Search tips
Starred by 1 user

Issue metadata

Status: Fixed
Closed: Jul 2018
EstimatedDays: ----
NextAction: ----
OS: Linux , Android , Windows , Chrome , Mac , Fuchsia
Pri: 1
Type: Bug-Security

Sign in to add a comment

Issue 864932: Security: Little-CMS (lcms) Heap Buffer Overflow

Reported by, Jul 18 2018

Issue description

 Little-CMS third-party library is used in PDFium to support ICC profile. I have audited source code of lcms library and I have founded a vulnerability in cmsReadTag function. The attached icc profile could crash lcms when ASAN was enabled on Linux.
==37311==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x606000000058 at pc 0x00000053bc7b bp 0x7ffcd1988bd0 sp 0x7ffcd1988bc8
READ of size 8 at 0x606000000058 thread T0
    #0 0x53bc7a in Type_S15Fixed16_Write /root/fuzzer/lcms2/Little-CMS/src/cmstypes.c:558:43
    #1 0x4f9769 in cmsReadRawTag /root/fuzzer/lcms2/Little-CMS/src/cmsio0.c:1873:10
    #2 0x4eae5b in ReadAllRAWTags /root/fuzzer/lcms2/Little-CMS/fuzz/fuzz.c:23:9
    #3 0x4eaf05 in main /root/fuzzer/lcms2/Little-CMS/fuzz/fuzz.c:31:4
    #4 0x7f5d4f0c082f in __libc_start_main (/lib/x86_64-linux-gnu/
    #5 0x41aa78 in _start (/root/fuzzer/lcms2/Little-CMS/fuzz/fuzz+0x41aa78)

0x606000000058 is located 0 bytes to the right of 56-byte region [0x606000000020,0x606000000058)
allocated by thread T0 here:
    #0 0x4bb1a3 in __interceptor_malloc /tmp/final/llvm.src/projects/compiler-rt/lib/asan/
    #1 0x57fac4 in FXMEM_DefaultAlloc /root/fuzzer/lcms2/Little-CMS/src/cmserr.c:33:9
    #2 0x57fe18 in _cmsMallocZero /root/fuzzer/lcms2/Little-CMS/src/cmserr.c:97:15
    #3 0x57feb9 in _cmsCalloc /root/fuzzer/lcms2/Little-CMS/src/cmserr.c:109:12
    #4 0x53bae0 in Type_S15Fixed16_Read /root/fuzzer/lcms2/Little-CMS/src/cmstypes.c:534:40
    #5 0x4f65d3 in cmsReadTag /root/fuzzer/lcms2/Little-CMS/src/cmsio0.c:1597:25
    #6 0x4eadc5 in ReadAllTags /root/fuzzer/lcms2/Little-CMS/fuzz/fuzz.c:11:13
    #7 0x4eaefc in main /root/fuzzer/lcms2/Little-CMS/fuzz/fuzz.c:30:4
    #8 0x7f5d4f0c082f in __libc_start_main (/lib/x86_64-linux-gnu/

SUMMARY: AddressSanitizer: heap-buffer-overflow /root/fuzzer/lcms2/Little-CMS/src/cmstypes.c:558:43 in Type_S15Fixed16_Write
Shadow bytes around the buggy address:
  0x0c0c7fff7fb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c0c7fff7fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c0c7fff7fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c0c7fff7fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c0c7fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c0c7fff8000: fa fa fa fa 00 00 00 00 00 00 00[fa]fa fa fa fa
  0x0c0c7fff8010: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c0c7fff8020: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c0c7fff8030: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c0c7fff8040: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c0c7fff8050: 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


Chrome Version: All

Operating System: All

Following code will trigger crash

#include <stdio.h>
#include <lcms2.h>

void ReadAllTags(cmsHPROFILE h) {
    cmsInt32Number i, n;
    cmsTagSignature sig;

    n = cmsGetTagCount(h);
    for (i=0; i < n; i++) {
        sig = cmsGetTagSignature(h, i);
        if (cmsReadTag(h, sig) == NULL) return;

// Read all tags on a profile given by its handle
void ReadAllRAWTags(cmsHPROFILE h) {
    cmsInt32Number i, n;
    cmsTagSignature sig;

    n = cmsGetTagCount(h);
    for (i=0; i < n; i++) {
        sig = cmsGetTagSignature(h, i);
        cmsReadRawTag(h, sig, NULL, 0);

int main(int argc, char* argv[]) {
   cmsHPROFILE h = cmsOpenProfileFromFile(argv[1], "rb");
   if (h == NULL) return 1;
   return 0;

There are many tag types which are supported in lcms:

// This is the list of built-in tags
static _cmsTagLinkedList SupportedTags[] = {
   //  .....
    { cmsSigChromaticAdaptationTag, { 9, 1, { cmsSigS15Fixed16ArrayType }, NULL}, &SupportedTags[15]},
   //  .....

Each type has `ElemCount`:

// This is the tag plugin, which identifies tags. For writing, a pointer to function is provided.
// This function should return the desired type for this tag, given the version of profile
// and the data being serialized.
typedef struct {

    cmsUInt32Number     ElemCount;          // If this tag needs an array, how many elements should keep

    // For reading.
    cmsUInt32Number     nSupportedTypes;    // In how many types this tag can come (MAX_TYPES_IN_LCMS_PLUGIN maximum)
    cmsTagTypeSignature SupportedTypes[MAX_TYPES_IN_LCMS_PLUGIN];

    // For writting
    cmsTagTypeSignature (* DecideType)(cmsFloat64Number ICCVersion, const void *Data);

} cmsTagDescriptor;

Let's see cmsReadTag:

The number of elements, which is calculated from data, may be less than `ElemCount`:
// This is a weird error that may be a symptom of something more serious, the number of
    // stored item is actually less than the number of required elements.
    if (ElemCount < TagDescriptor ->ElemCount) {

        char String[5];

        _cmsTagSignature2String(String, sig);
        cmsSignalError(Icc ->ContextID, cmsERROR_CORRUPTION_DETECTED, "'%s' Inconsistent number of items: expected %d, got %d",
            String, TagDescriptor ->ElemCount, ElemCount);
if ElemCount is less than TagDescriptor ->ElemCount, it is a malformed tag and it MUST be ignored.
180 bytes View Download

Comment 1 by, Jul 18 2018

Patch for this issue: 
diff --git a/third_party/lcms/src/cmsio0.c b/third_party/lcms/src/cmsio0.c
index cc5f89064..63e4105d1 100644
--- a/third_party/lcms/src/cmsio0.c
+++ b/third_party/lcms/src/cmsio0.c
@@ -1616,6 +1616,7 @@ void* CMSEXPORT cmsReadTag(cmsHPROFILE hProfile, cmsTagSignature sig)
         _cmsTagSignature2String(String, sig);
         cmsSignalError(Icc ->ContextID, cmsERROR_CORRUPTION_DETECTED, "'%s' Inconsistent number of items: expected %d, got %d",
             String, TagDescriptor ->ElemCount, ElemCount);
+               goto Error;


Comment 2 by, Jul 18 2018

Components: Internals>Plugins>PDF
Labels: M-69 Security_Severity-Medium FoundIn-67 Security_Impact-Stable OS-Android OS-Chrome OS-Fuchsia OS-Linux OS-Mac OS-Windows Pri-1
Thank you for the detailed writeup and for including a patch :-)

Setting some labels. If I understand correctly, this is a limited out-of-bounds write, so applying Sev-Medium.

thestig@ Could you take a look? You had the most recent patch to lcms/.

Comment 3 by, Jul 18 2018


Comment 4 by, Jul 18 2018

Yes, it looks like cmsReadTag() is missing the goto statement to handle the error. We'll patch it up. Have you reported the issue upstream to lcms?

Comment 5 by, Jul 18 2018

Status: Started (was: Unconfirmed)

Comment 7 by, Jul 18 2018

Labels: M-68 Merge-Request-68
Status: Fixed (was: Started)

Comment 8 by, Jul 18 2018

Project Member
Labels: -Merge-Request-68 Hotlist-Merge-Review Merge-Review-68
This bug requires manual review: We are only 5 days from stable.
Please contact the milestone owner if you have questions.
Owners: cmasso@(Android), kariahda@(iOS), bhthompson@(ChromeOS), abdulsyed@(Desktop)

For more details visit - Your friendly Sheriffbot

Comment 9 by, Jul 19 2018

Project Member
The following revision refers to this bug:

commit 30ce134f3d94e8addd51f007a468af9ac626af9f
Author: pdfium-chromium-autoroll <>
Date: Thu Jul 19 02:04:36 2018

Roll src/third_party/pdfium f22b4e2f6682..c15c0b3a1e9a (3 commits)

git log f22b4e2f6682..c15c0b3a1e9a --date=short --no-merges --format='%ad %ae %s'
2018-07-18 Roll third_party/skia/ af7700265..588f87967 (1391 commits; 41 trivial rolls)
2018-07-18 Handle wrong tag element count in littlecms.
2018-07-18 Add pdfium::span::as_bytes() and as_writable_bytes().

Created with:
  gclient setdep -r src/third_party/pdfium@c15c0b3a1e9a

The AutoRoll server is located here:

Documentation for the AutoRoller is here:

If the roll is causing failures, please contact the current sheriff, who should
be CC'd on the roll, and stop the roller if necessary.

BUG= chromium:864932

Change-Id: If7555664cbb89a71e68d034eacbb6b6be0e87415
Reviewed-by: pdfium-chromium-autoroll <>
Commit-Queue: pdfium-chromium-autoroll <>
Cr-Commit-Position: refs/heads/master@{#576322}

Comment 10 by, Jul 19 2018

Thank you for reviewing the issue. Do you reward for this report?

Comment 11 by, Jul 19 2018


Comment 12 by, Jul 19 2018

Project Member
Labels: -Restrict-View-SecurityTeam Restrict-View-SecurityNotify

Comment 13 by, Jul 19 2018

Labels: reward-topanel
quangnh89@, this will go to a future meetings of the VRP panel, we'll see what they say.

Comment 14 by, Jul 19 2018

Labels: -Merge-Review-68 Merge-Rejected-68
My recommendation is to target this for M69, since M68 stable is next week. Rejecting merge for M68. Awhalley@/thestig@ - please confirm if this is absolutely critical.

Comment 15 by, Jul 23 2018

Labels: -M-68

Comment 17 by, Aug 1

Comment 18 by, Aug 2

I have checked lcms v2.9. The vulnerability still exists.
If you update lcms, please patch it :)

Comment 19 by, Aug 2

Thanks for mention that. When we upgrade a third party library, we usually re-evaluate all the patches to see which ones are still relevant.

Comment 20 by, Aug 6

Labels: -reward-topanel reward-unpaid reward-2500
*** Boilerplate reminders! ***
Please do NOT publicly disclose details until a fix has been released to all our users. Early public disclosure may cancel the provisional reward. Also, please be considerate about disclosure when the bug affects a core library that may be used by other products. Please do NOT share this information with third parties who are not directly involved in fixing the bug. Doing so may cancel the provisional reward. Please be honest if you have already disclosed anything publicly or to third parties. Lastly, we understand that some of you are not interested in money. We offer the option to donate your reward to an eligible charity. If you prefer this option, let us know and we will also match your donation - subject to our discretion. Any rewards that are unclaimed after 12 months will be donated to a charity of our choosing.

Comment 21 by, Aug 6

Thanks for the report, quangnh89@! The VRP panel decided to award $2,000 for the report, and $500 for supplying the patch we used. They also noted that they'd be open to considering a higher amount if you could show how this might lead to memory corruption rather than just being an information leak.  Cheers!  A member of our finance team will be in touch to arrange for payment.

Comment 22 by, Aug 6

Labels: -reward-unpaid reward-inprocess

Comment 23 by, Aug 7

Thank you so much for the reward! That means so much to me! Your thoughtfulness encourage me to do my best. :) Have a nice day!

Comment 24 by, Aug 16

Labels: Release-0-M69

Comment 25 by, Oct 25

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

For more details visit - Your friendly Sheriffbot

Comment 26 by, Oct 26

Hello, can you tell me how to reproduce this issue under pdfium? Thanks.

Sign in to add a comment