|
|
- From e1cd2d7ab032e7fe80b4c13e07895194c8bac85e Mon Sep 17 00:00:00 2001
- From: Brian May <brian@linuxpenguins.xyz>
- Date: Thu, 7 Dec 2017 07:46:47 +1100
- Subject: [PATCH 1/4] [PATCH] tiff2pdf: Fix CVE-2017-9935
-
- Fix for http://bugzilla.maptools.org/show_bug.cgi?id=2704
-
- This vulnerability - at least for the supplied test case - is because we
- assume that a tiff will only have one transfer function that is the same
- for all pages. This is not required by the TIFF standards.
-
- We than read the transfer function for every page. Depending on the
- transfer function, we allocate either 2 or 4 bytes to the XREF buffer.
- We allocate this memory after we read in the transfer function for the
- page.
-
- For the first exploit - POC1, this file has 3 pages. For the first page
- we allocate 2 extra extra XREF entries. Then for the next page 2 more
- entries. Then for the last page the transfer function changes and we
- allocate 4 more entries.
-
- When we read the file into memory, we assume we have 4 bytes extra for
- each and every page (as per the last transfer function we read). Which
- is not correct, we only have 2 bytes extra for the first 2 pages. As a
- result, we end up writing past the end of the buffer.
-
- There are also some related issues that this also fixes. For example,
- TIFFGetField can return uninitalized pointer values, and the logic to
- detect a N=3 vs N=1 transfer function seemed rather strange.
-
- It is also strange that we declare the transfer functions to be of type
- float, when the standard says they are unsigned 16 bit values. This is
- fixed in another patch.
-
- This patch will check to ensure that the N value for every transfer
- function is the same for every page. If this changes, we abort with an
- error. In theory, we should perhaps check that the transfer function
- itself is identical for every page, however we don't do that due to the
- confusion of the type of the data in the transfer function.
- ---
- libtiff/tif_dir.c | 3 +++
- tools/tiff2pdf.c | 69 +++++++++++++++++++++++++++++++----------------
- 2 files changed, 49 insertions(+), 23 deletions(-)
-
- diff --git a/libtiff/tif_dir.c b/libtiff/tif_dir.c
- index f00f808..c36a5f3 100644
- --- a/libtiff/tif_dir.c
- +++ b/libtiff/tif_dir.c
- @@ -1067,6 +1067,9 @@ _TIFFVGetField(TIFF* tif, uint32 tag, va_list ap)
- if (td->td_samplesperpixel - td->td_extrasamples > 1) {
- *va_arg(ap, uint16**) = td->td_transferfunction[1];
- *va_arg(ap, uint16**) = td->td_transferfunction[2];
- + } else {
- + *va_arg(ap, uint16**) = NULL;
- + *va_arg(ap, uint16**) = NULL;
- }
- break;
- case TIFFTAG_REFERENCEBLACKWHITE:
- diff --git a/tools/tiff2pdf.c b/tools/tiff2pdf.c
- index bdb9126..bd23c9e 100644
- --- a/tools/tiff2pdf.c
- +++ b/tools/tiff2pdf.c
- @@ -239,7 +239,7 @@ typedef struct {
- float tiff_whitechromaticities[2];
- float tiff_primarychromaticities[6];
- float tiff_referenceblackwhite[2];
- - float* tiff_transferfunction[3];
- + uint16* tiff_transferfunction[3];
- int pdf_image_interpolate; /* 0 (default) : do not interpolate,
- 1 : interpolate */
- uint16 tiff_transferfunctioncount;
- @@ -1049,6 +1049,8 @@ void t2p_read_tiff_init(T2P* t2p, TIFF* input){
- uint16 pagen=0;
- uint16 paged=0;
- uint16 xuint16=0;
- + uint16 tiff_transferfunctioncount=0;
- + uint16* tiff_transferfunction[3];
-
- directorycount=TIFFNumberOfDirectories(input);
- if(directorycount > TIFF_DIR_MAX) {
- @@ -1157,26 +1159,48 @@ void t2p_read_tiff_init(T2P* t2p, TIFF* input){
- }
- #endif
- if (TIFFGetField(input, TIFFTAG_TRANSFERFUNCTION,
- - &(t2p->tiff_transferfunction[0]),
- - &(t2p->tiff_transferfunction[1]),
- - &(t2p->tiff_transferfunction[2]))) {
- - if((t2p->tiff_transferfunction[1] != (float*) NULL) &&
- - (t2p->tiff_transferfunction[2] != (float*) NULL) &&
- - (t2p->tiff_transferfunction[1] !=
- - t2p->tiff_transferfunction[0])) {
- - t2p->tiff_transferfunctioncount = 3;
- - t2p->tiff_pages[i].page_extra += 4;
- - t2p->pdf_xrefcount += 4;
- - } else {
- - t2p->tiff_transferfunctioncount = 1;
- - t2p->tiff_pages[i].page_extra += 2;
- - t2p->pdf_xrefcount += 2;
- - }
- - if(t2p->pdf_minorversion < 2)
- - t2p->pdf_minorversion = 2;
- + &(tiff_transferfunction[0]),
- + &(tiff_transferfunction[1]),
- + &(tiff_transferfunction[2]))) {
- +
- + if((tiff_transferfunction[1] != (uint16*) NULL) &&
- + (tiff_transferfunction[2] != (uint16*) NULL)
- + ) {
- + tiff_transferfunctioncount=3;
- + } else {
- + tiff_transferfunctioncount=1;
- + }
- } else {
- - t2p->tiff_transferfunctioncount=0;
- + tiff_transferfunctioncount=0;
- }
- +
- + if (i > 0){
- + if (tiff_transferfunctioncount != t2p->tiff_transferfunctioncount){
- + TIFFError(
- + TIFF2PDF_MODULE,
- + "Different transfer function on page %d",
- + i);
- + t2p->t2p_error = T2P_ERR_ERROR;
- + return;
- + }
- + }
- +
- + t2p->tiff_transferfunctioncount = tiff_transferfunctioncount;
- + t2p->tiff_transferfunction[0] = tiff_transferfunction[0];
- + t2p->tiff_transferfunction[1] = tiff_transferfunction[1];
- + t2p->tiff_transferfunction[2] = tiff_transferfunction[2];
- + if(tiff_transferfunctioncount == 3){
- + t2p->tiff_pages[i].page_extra += 4;
- + t2p->pdf_xrefcount += 4;
- + if(t2p->pdf_minorversion < 2)
- + t2p->pdf_minorversion = 2;
- + } else if (tiff_transferfunctioncount == 1){
- + t2p->tiff_pages[i].page_extra += 2;
- + t2p->pdf_xrefcount += 2;
- + if(t2p->pdf_minorversion < 2)
- + t2p->pdf_minorversion = 2;
- + }
- +
- if( TIFFGetField(
- input,
- TIFFTAG_ICCPROFILE,
- @@ -1837,10 +1861,9 @@ void t2p_read_tiff_data(T2P* t2p, TIFF* input){
- &(t2p->tiff_transferfunction[0]),
- &(t2p->tiff_transferfunction[1]),
- &(t2p->tiff_transferfunction[2]))) {
- - if((t2p->tiff_transferfunction[1] != (float*) NULL) &&
- - (t2p->tiff_transferfunction[2] != (float*) NULL) &&
- - (t2p->tiff_transferfunction[1] !=
- - t2p->tiff_transferfunction[0])) {
- + if((t2p->tiff_transferfunction[1] != (uint16*) NULL) &&
- + (t2p->tiff_transferfunction[2] != (uint16*) NULL)
- + ) {
- t2p->tiff_transferfunctioncount=3;
- } else {
- t2p->tiff_transferfunctioncount=1;
- --
- 2.17.0
-
|