Bug 91686 - [patch] Fix pdftoppm core dump with free(): invalid next size (normal): 0x00000000009e2f80
Summary: [patch] Fix pdftoppm core dump with free(): invalid next size (normal): 0x000...
Status: RESOLVED FIXED
Alias: None
Product: poppler
Classification: Unclassified
Component: splash backend (show other bugs)
Version: unspecified
Hardware: Other All
: medium normal
Assignee: poppler-bugs
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2015-08-19 08:29 UTC by William Bader
Modified: 2015-08-19 21:02 UTC (History)
1 user (show)

See Also:
i915 platform:
i915 features:


Attachments
patch to fix the core dump (416 bytes, text/plain)
2015-08-19 08:29 UTC, William Bader
Details

Description William Bader 2015-08-19 08:29:58 UTC
Created attachment 117779 [details]
patch to fix the core dump

Pieter van der Eems produced a PDF where
 pdftoppm -cropbox -f 0 -l 0 -r 150 /tmp/memory_issue_pdf.pdf x
core dumps with a memory corruption error like
  *** Error in `/usr/bin/pdftoppm': double free or corruption (out): 0x00000000011145b0 ***
or
  *** Error in `./pdftoppm': free(): invalid next size (normal): 0x000000000107cf80 ***

valgrind reports
Invalid read of size 1
   at 0x47AF9C: Splash::pipeRun(SplashPipe*) (Splash.cc:504)
   by 0x488D97: Splash::drawPixel(SplashPipe*, int, int, bool) (Splash.cc:1414)
   by 0x47F96A: Splash::arbitraryTransformMask(bool (*)(void*, unsigned char*), void*, int, int, double*, bool) (Splash.cc:3242)
   by 0x48331B: Splash::fillImageMask(bool (*)(void*, unsigned char*), void*, int, int, double*, bool) (Splash.cc:2980)
   by 0x40EE72: SplashOutputDev::setSoftMaskFromImageMask(GfxState*, Object*, Stream*, int, int, bool, bool, double*) (SplashOutputDev.cc:2845)
   by 0x42529A: Gfx::doPatternImageMask(Object*, Stream*, int, int, bool, bool) (Gfx.cc:2091)
   by 0x42611A: Gfx::doImage(Object*, Stream*, bool) (Gfx.cc:4380)
   by 0x4268C9: Gfx::opBeginImage(Object*, int) (Gfx.cc:4987)
   by 0x421BC9: Gfx::go(bool) (Gfx.cc:763)
   by 0x422054: Gfx::display(Object*, bool) (Gfx.cc:729)
   by 0x4BF027: Page::displaySlice(OutputDev*, double, double, int, bool, bool, int, int, int, int, bool, bool (*)(void*), void*, bool (*)(Annot*, void*), void*, ...
   by 0x40AAF3: savePageSlice(PDFDoc*, SplashOutputDev*, int, int, int, int, int, double, double, char*) (pdftoppm.cc:225)
 Address 0x58d82af is 1 bytes before a block of size 2,112 alloc'd
   at 0x4A06BBD: malloc (vg_replace_malloc.c:296)
   by 0x469F6C: gmalloc(unsigned long, bool) (gmem.cc:110)
   by 0x489A8F: SplashBitmap::SplashBitmap(int, int, int, SplashColorMode, bool, bool, GooList*) (SplashBitmap.cc:113)
   by 0x40EDC9: SplashOutputDev::setSoftMaskFromImageMask(GfxState*, Object*, Stream*, int, int, bool, bool, double*) (SplashOutputDev.cc:2839)
   by 0x42529A: Gfx::doPatternImageMask(Object*, Stream*, int, int, bool, bool) (Gfx.cc:2091)
   by 0x42611A: Gfx::doImage(Object*, Stream*, bool) (Gfx.cc:4380)
   by 0x4268C9: Gfx::opBeginImage(Object*, int) (Gfx.cc:4987)
   by 0x421BC9: Gfx::go(bool) (Gfx.cc:763)
   by 0x422054: Gfx::display(Object*, bool) (Gfx.cc:729)
   by 0x4BF027: Page::displaySlice(OutputDev*, double, double, int, bool, bool, int, int, int, int, bool, bool (*)(void*), void*, bool (*)(Annot*, void*), void*, ...
   by 0x40AAF3: savePageSlice(PDFDoc*, SplashOutputDev*, int, int, int, int, int, double, double, char*) (pdftoppm.cc:225)
   by 0x40A348: main (pdftoppm.cc:532)

Debug code shows that Splash::arbitraryTransformMask() was setting xa to -1 and then running
  for (x = xa; x < xb; x++) {
    drawPixel(&pipe, x, y, clipRes2 == splashClipAllInside);
  }
With xa of -1, it was corrupting internal malloc data in front of the buffer.
valgrind warns "Address 0x58d82af is 1 bytes before a block of size 2,112 alloc'd"

A later write to the byte corrupts memory, and then pdftoppm will eventually crash.

Invalid write of size 1
  at 0x47AAD1: Splash::pipeRun(SplashPipe*) (Splash.cc:827)
  by 0x488D97: Splash::drawPixel(SplashPipe*, int, int, bool) (Splash.cc:1414)
  by 0x47F96A: Splash::arbitraryTransformMask(bool (*)(void*, unsigned char*), void*, int, int, double*, bool) (Splash.cc:3242)
  by 0x48331B: Splash::fillImageMask(bool (*)(void*, unsigned char*), void*, int, int, double*, bool) (Splash.cc:2980)

The patch ensures that xa is >= 0.

There might be a deeper problem that splashFloor() can return a negative value.
splashFloor() is implemented in SplashMath.h.
Comment 1 Albert Astals Cid 2015-08-19 21:02:36 UTC
Pushed (with an added unlikely)


Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.