Bug 1696638 (CVE-2019-10872)

Summary: CVE-2019-10872 poppler: heap-based buffer over-read in function Splash::blitTransparent in splash/Splash.cc
Product: [Other] Security Response Reporter: Dhananjay Arunesh <darunesh>
Component: vulnerabilityAssignee: Red Hat Product Security <security-response-team>
Status: CLOSED NOTABUG QA Contact:
Severity: medium Docs Contact:
Priority: medium    
Version: unspecifiedCC: caillon+fedoraproject, feborges, gnome-sig, john.j5live, mclasen, mkasik, rdieter, rhughes, rstrode, sandmann
Target Milestone: ---Keywords: Security
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: If docs needed, set a value
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2019-06-10 10:53:40 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Bug Depends On: 1696640    
Bug Blocks: 1696639    

Description Dhananjay Arunesh 2019-04-05 10:38:15 UTC
An issue was discovered in Poppler 0.74.0. There is a heap-based buffer over-read in the function Splash::blitTransparent at splash/Splash.cc.

Reference:
https://gitlab.freedesktop.org/poppler/poppler/issues/750

Comment 1 Dhananjay Arunesh 2019-04-05 10:43:03 UTC
Created poppler tracking bugs for this issue:

Affects: fedora-all [bug 1696640]

Comment 2 Scott Gayou 2019-04-08 19:29:18 UTC
Couldn't reproduce this on any versions we ship, but it did spit out a mildly interesting out of memory error.

```
Error (7289): Illegal character <6f> in hex string
Error (7298): Illegal character <52> in hex string
Error (7301): Illegal character '>'
Error: font resource is not a dictionary
Out of memory
```

Rebuilt with address sanitizer and we get:

```
Syntax Error (7301): Illegal character '>'
Syntax Error: font resource is not a dictionary
==8038== ERROR: AddressSanitizer failed to allocate 0x80002000 (2147491840) bytes of LargeMmapAllocator: Cannot allocate memory
==8038== Process memory map follows:
	0x000000400000-0x000000408000	/usr/bin/pdftoppm
	0x000000608000-0x000000609000	/usr/bin/pdftoppm
	0x000000609000-0x00000060b000	/usr/bin/pdftoppm
```

Asan BT:

```
    #0 0x7ffff4e5db9a (/usr/lib64/libasan.so.0.0.0+0x12b9a)
    #1 0x7ffff4e64e03 (/usr/lib64/libasan.so.0.0.0+0x19e03)
    #2 0x7ffff4e674f3 (/usr/lib64/libasan.so.0.0.0+0x1c4f3)
    #3 0x7ffff4e53ee8 (/usr/lib64/libasan.so.0.0.0+0x8ee8)
    #4 0x7ffff4e60f21 (/usr/lib64/libasan.so.0.0.0+0x15f21)
    #5 0x7ffff499164b (/usr/lib64/libpoppler.so.46.0.0+0x3fd64b) // gmalloc
    #6 0x7ffff499187a (/usr/lib64/libpoppler.so.46.0.0+0x3fd87a) // inline static void *gmallocn(int nObjs, int objSize, bool checkoverflow) {
    #7 0x7ffff499189e (/usr/lib64/libpoppler.so.46.0.0+0x3fd89e) // void *gmallocn(int nObjs, int objSize) {
    #8 0x7ffff4a0fd75 (/usr/lib64/libpoppler.so.46.0.0+0x47bd75) //  alpha = (Guchar *)gmallocn(width, height);
    #9 0x7ffff4725779 (/usr/lib64/libpoppler.so.46.0.0+0x191779)
    #10 0x7ffff47f402e (/usr/lib64/libpoppler.so.46.0.0+0x26002e)
    #11 0x7ffff47f2eb0 (/usr/lib64/libpoppler.so.46.0.0+0x25eeb0)
```

Seems like a correctly handled out of memory condition. Size of 2147491840 is a bit suspect.

gmalloc throws the error in goo/gmem.cc.

```c
  if (!(p = malloc(size))) {
    fprintf(stderr, "Out of memory\n");
    if (checkoverflow) return NULL;
    else exit(1);
  }
```

which is called by: `inline static void *gmallocn(int nObjs, int objSize, bool checkoverflow) {`

which is eventually called by splash/SplashBitmap.cc in SplashBitmap::SplashBitmap:

```c
    if (alphaA) {
      alpha = (Guchar *)gmallocn(width, height);
    } else {
      alpha = NULL;
    }
```

Looks like SplashBitmap is getting constructed with a widthA of a large value (widthA=2147482383). See this backtrace before the malloc fails:

```
(gdb) bt
#0  SplashBitmap::SplashBitmap (this=0x600800120a90, widthA=2147482383, heightA=1, rowPadA=4, modeA=splashModeMono1, alphaA=true, 
    topDown=true, separationListA=0x60060003b3b0) at SplashBitmap.cc:57
#1  0x00007ffff472577a in SplashOutputDev::beginTransparencyGroup (this=0x602c0000fe00, state=0x603e0000da00, bbox=0x7fffffffcbd0, 
    blendingColorSpace=0x0, isolated=false, knockout=false, forSoftMask=false) at SplashOutputDev.cc:3851
#2  0x00007ffff47f402f in Gfx::drawForm (this=0x60240001e180, str=0x7fffffffcda0, resDict=0x600e000277e0, matrix=0x7fffffffcc10, 
    bbox=0x7fffffffcbd0, transpGroup=true, softMask=false, blendingColorSpace=0x0, isolated=false, knockout=false, alpha=false, 
    transferFunc=0x0, backdropColor=0x0) at Gfx.cc:4910
#3  0x00007ffff47f2eb1 in Gfx::doForm (this=0x60240001e180, str=0x7fffffffcda0) at Gfx.cc:4845
#4  0x00007ffff47eedd3 in Gfx::opXObject (this=0x60240001e180, args=0x7fffffffd0a0, numArgs=1) at Gfx.cc:4199
#5  0x00007ffff47c8aaf in Gfx::execOp (this=0x60240001e180, cmd=0x7fffffffd000, args=0x7fffffffd0a0, numArgs=1) at Gfx.cc:904
#6  0x00007ffff47c7c42 in Gfx::go (this=0x60240001e180, topLevel=false) at Gfx.cc:763
#7  0x00007ffff47c7854 in Gfx::display (this=0x60240001e180, obj=0x7fffffffd8e0, topLevel=false) at Gfx.cc:729
#8  0x00007ffff47f41fe in Gfx::drawForm (this=0x60240001e180, str=0x7fffffffd8e0, resDict=0x600e00005650, matrix=0x7fffffffd750, 
    bbox=0x7fffffffd710, transpGroup=true, softMask=false, blendingColorSpace=0x0, isolated=false, knockout=false, alpha=false, 
    transferFunc=0x0, backdropColor=0x0) at Gfx.cc:4922
#9  0x00007ffff47f2eb1 in Gfx::doForm (this=0x60240001e180, str=0x7fffffffd8e0) at Gfx.cc:4845
#10 0x00007ffff47eedd3 in Gfx::opXObject (this=0x60240001e180, args=0x7fffffffdbe0, numArgs=1) at Gfx.cc:4199
#11 0x00007ffff47c8aaf in Gfx::execOp (this=0x60240001e180, cmd=0x7fffffffdb40, args=0x7fffffffdbe0, numArgs=1) at Gfx.cc:904
#12 0x00007ffff47c7c42 in Gfx::go (this=0x60240001e180, topLevel=true) at Gfx.cc:763
#13 0x00007ffff47c7854 in Gfx::display (this=0x60240001e180, obj=0x7fffffffe040, topLevel=true) at Gfx.cc:729
#14 0x00007ffff48ab19f in Page::displaySlice (this=0x60220001fa80, out=0x602c0000fe00, hDPI=150, vDPI=150, rotate=0, 
    useMediaBox=false, crop=false, sliceX=0, sliceY=0, sliceW=1275, sliceH=1651, printing=false, abortCheckCbk=0x0, 
    abortCheckCbkData=0x0, annotDisplayDecideCbk=0x0, annotDisplayDecideCbkData=0x0, copyXRef=false) at Page.cc:585
#15 0x00007ffff48b2bbc in PDFDoc::displayPageSlice (this=0x601c0000df60, out=0x602c0000fe00, page=2, hDPI=150, vDPI=150, rotate=0, 
    useMediaBox=false, crop=false, printing=false, sliceX=0, sliceY=0, sliceW=1275, sliceH=1651, abortCheckCbk=0x0, 
    abortCheckCbkData=0x0, annotDisplayDecideCbk=0x0, annotDisplayDecideCbkData=0x0, copyXRef=false) at PDFDoc.cc:503
#16 0x0000000000401cfe in savePageSlice (doc=0x601c0000df60, splashOut=0x602c0000fe00, pg=2, x=0, y=0, w=1275, h=1651, pg_w=1275, 
    pg_h=1650.0000000000002, ppmFile=0x0) at pdftoppm.cc:222
#17 0x0000000000403098 in main (argc=2, argv=0x7fffffffe428) at pdftoppm.cc:521
```

Behavior seems fine then. Large value is passed to a memory allocation, it fails, it is checked, execution terminates after the failure.

Comment 3 Scott Gayou 2019-04-08 19:30:38 UTC
To summarize this: Unable to reproduce the heap-overread in any version shipped. Explored the out-of-memory error, looks benign.