| From 3144e57770c1e4d26520d8abee750f8ac8b75490 Mon Sep 17 00:00:00 2001 |
| From: erouault <erouault> |
| Date: Wed, 11 Jan 2017 16:09:02 +0000 |
| Subject: [PATCH] * libtiff/tif_dir.c, tif_dirread.c, tif_dirwrite.c: implement |
| various clampings of double to other data types to avoid undefined behaviour |
| if the output range isn't big enough to hold the input value. Fixes |
| http://bugzilla.maptools.org/show_bug.cgi?id=2643 |
| http://bugzilla.maptools.org/show_bug.cgi?id=2642 |
| http://bugzilla.maptools.org/show_bug.cgi?id=2646 |
| http://bugzilla.maptools.org/show_bug.cgi?id=2647 |
| |
| Upstream-Status: Backport |
| |
| CVE: CVE-2017-7596 |
| Signed-off-by: Rajkumar Veer <rveer@mvista.com> |
| |
| Index: tiff-4.0.7/ChangeLog |
| =================================================================== |
| --- tiff-4.0.7.orig/ChangeLog 2017-04-25 15:53:40.294592812 +0530 |
| +++ tiff-4.0.7/ChangeLog 2017-04-25 16:02:03.238600641 +0530 |
| @@ -6,6 +6,16 @@ |
| Patch by Nicolás Peña. |
| Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2659 |
| |
| +2017-01-11 Even Rouault <even.rouault at spatialys.com> |
| + |
| + * libtiff/tif_dir.c, tif_dirread.c, tif_dirwrite.c: implement various clampings |
| + of double to other data types to avoid undefined behaviour if the output range |
| + isn't big enough to hold the input value. |
| + Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2643 |
| + http://bugzilla.maptools.org/show_bug.cgi?id=2642 |
| + http://bugzilla.maptools.org/show_bug.cgi?id=2646 |
| + http://bugzilla.maptools.org/show_bug.cgi?id=2647 |
| + |
| 2017-01-11 Even Rouault <even.rouault at spatialys.com> |
| |
| * libtiff/tif_jpeg.c: avoid integer division by zero in |
| Index: tiff-4.0.7/libtiff/tif_dir.c |
| =================================================================== |
| --- tiff-4.0.7.orig/libtiff/tif_dir.c 2016-10-30 04:33:18.856598072 +0530 |
| +++ tiff-4.0.7/libtiff/tif_dir.c 2017-04-25 16:02:03.238600641 +0530 |
| @@ -31,6 +31,7 @@ |
| * (and also some miscellaneous stuff) |
| */ |
| #include "tiffiop.h" |
| +#include <float.h> |
| |
| /* |
| * These are used in the backwards compatibility code... |
| @@ -154,6 +155,15 @@ |
| return (0); |
| } |
| |
| +static float TIFFClampDoubleToFloat( double val ) |
| +{ |
| + if( val > FLT_MAX ) |
| + return FLT_MAX; |
| + if( val < -FLT_MAX ) |
| + return -FLT_MAX; |
| + return (float)val; |
| +} |
| + |
| static int |
| _TIFFVSetField(TIFF* tif, uint32 tag, va_list ap) |
| { |
| @@ -312,13 +322,13 @@ |
| dblval = va_arg(ap, double); |
| if( dblval < 0 ) |
| goto badvaluedouble; |
| - td->td_xresolution = (float) dblval; |
| + td->td_xresolution = TIFFClampDoubleToFloat( dblval ); |
| break; |
| case TIFFTAG_YRESOLUTION: |
| dblval = va_arg(ap, double); |
| if( dblval < 0 ) |
| goto badvaluedouble; |
| - td->td_yresolution = (float) dblval; |
| + td->td_yresolution = TIFFClampDoubleToFloat( dblval ); |
| break; |
| case TIFFTAG_PLANARCONFIG: |
| v = (uint16) va_arg(ap, uint16_vap); |
| @@ -327,10 +337,10 @@ |
| td->td_planarconfig = (uint16) v; |
| break; |
| case TIFFTAG_XPOSITION: |
| - td->td_xposition = (float) va_arg(ap, double); |
| + td->td_xposition = TIFFClampDoubleToFloat( va_arg(ap, double) ); |
| break; |
| case TIFFTAG_YPOSITION: |
| - td->td_yposition = (float) va_arg(ap, double); |
| + td->td_yposition = TIFFClampDoubleToFloat( va_arg(ap, double) ); |
| break; |
| case TIFFTAG_RESOLUTIONUNIT: |
| v = (uint16) va_arg(ap, uint16_vap); |
| Index: tiff-4.0.7/libtiff/tif_dirread.c |
| =================================================================== |
| --- tiff-4.0.7.orig/libtiff/tif_dirread.c 2017-04-25 15:53:40.134592810 +0530 |
| +++ tiff-4.0.7/libtiff/tif_dirread.c 2017-04-25 16:02:03.242600641 +0530 |
| @@ -40,6 +40,7 @@ |
| */ |
| |
| #include "tiffiop.h" |
| +#include <float.h> |
| |
| #define IGNORE 0 /* tag placeholder used below */ |
| #define FAILED_FII ((uint32) -1) |
| @@ -2406,7 +2407,14 @@ |
| ma=(double*)origdata; |
| mb=data; |
| for (n=0; n<count; n++) |
| - *mb++=(float)(*ma++); |
| + { |
| + double val = *ma++; |
| + if( val > FLT_MAX ) |
| + val = FLT_MAX; |
| + else if( val < -FLT_MAX ) |
| + val = -FLT_MAX; |
| + *mb++=(float)val; |
| + } |
| } |
| break; |
| } |
| Index: tiff-4.0.7/libtiff/tif_dirwrite.c |
| =================================================================== |
| --- tiff-4.0.7.orig/libtiff/tif_dirwrite.c 2016-10-30 04:33:18.876854501 +0530 |
| +++ tiff-4.0.7/libtiff/tif_dirwrite.c 2017-04-25 16:07:48.670606018 +0530 |
| @@ -30,6 +30,7 @@ |
| * Directory Write Support Routines. |
| */ |
| #include "tiffiop.h" |
| +#include <float.h> |
| |
| #ifdef HAVE_IEEEFP |
| #define TIFFCvtNativeToIEEEFloat(tif, n, fp) |
| @@ -939,6 +940,69 @@ |
| return(0); |
| } |
| |
| +static float TIFFClampDoubleToFloat( double val ) |
| +{ |
| + if( val > FLT_MAX ) |
| + return FLT_MAX; |
| + if( val < -FLT_MAX ) |
| + return -FLT_MAX; |
| + return (float)val; |
| +} |
| + |
| +static int8 TIFFClampDoubleToInt8( double val ) |
| +{ |
| + if( val > 127 ) |
| + return 127; |
| + if( val < -128 || val != val ) |
| + return -128; |
| + return (int8)val; |
| +} |
| + |
| +static int16 TIFFClampDoubleToInt16( double val ) |
| +{ |
| + if( val > 32767 ) |
| + return 32767; |
| + if( val < -32768 || val != val ) |
| + return -32768; |
| + return (int16)val; |
| +} |
| + |
| +static int32 TIFFClampDoubleToInt32( double val ) |
| +{ |
| + if( val > 0x7FFFFFFF ) |
| + return 0x7FFFFFFF; |
| + if( val < -0x7FFFFFFF-1 || val != val ) |
| + return -0x7FFFFFFF-1; |
| + return (int32)val; |
| +} |
| + |
| +static uint8 TIFFClampDoubleToUInt8( double val ) |
| +{ |
| + if( val < 0 ) |
| + return 0; |
| + if( val > 255 || val != val ) |
| + return 255; |
| + return (uint8)val; |
| +} |
| + |
| +static uint16 TIFFClampDoubleToUInt16( double val ) |
| +{ |
| + if( val < 0 ) |
| + return 0; |
| + if( val > 65535 || val != val ) |
| + return 65535; |
| + return (uint16)val; |
| +} |
| + |
| +static uint32 TIFFClampDoubleToUInt32( double val ) |
| +{ |
| + if( val < 0 ) |
| + return 0; |
| + if( val > 0xFFFFFFFFU || val != val ) |
| + return 0xFFFFFFFFU; |
| + return (uint32)val; |
| +} |
| + |
| static int |
| TIFFWriteDirectoryTagSampleformatArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, double* value) |
| { |
| @@ -959,7 +1023,7 @@ |
| if (tif->tif_dir.td_bitspersample<=32) |
| { |
| for (i = 0; i < count; ++i) |
| - ((float*)conv)[i] = (float)value[i]; |
| + ((float*)conv)[i] = TIFFClampDoubleToFloat(value[i]); |
| ok = TIFFWriteDirectoryTagFloatArray(tif,ndir,dir,tag,count,(float*)conv); |
| } |
| else |
| @@ -971,19 +1035,19 @@ |
| if (tif->tif_dir.td_bitspersample<=8) |
| { |
| for (i = 0; i < count; ++i) |
| - ((int8*)conv)[i] = (int8)value[i]; |
| + ((int8*)conv)[i] = TIFFClampDoubleToInt8(value[i]); |
| ok = TIFFWriteDirectoryTagSbyteArray(tif,ndir,dir,tag,count,(int8*)conv); |
| } |
| else if (tif->tif_dir.td_bitspersample<=16) |
| { |
| for (i = 0; i < count; ++i) |
| - ((int16*)conv)[i] = (int16)value[i]; |
| + ((int16*)conv)[i] = TIFFClampDoubleToInt16(value[i]); |
| ok = TIFFWriteDirectoryTagSshortArray(tif,ndir,dir,tag,count,(int16*)conv); |
| } |
| else |
| { |
| for (i = 0; i < count; ++i) |
| - ((int32*)conv)[i] = (int32)value[i]; |
| + ((int32*)conv)[i] = TIFFClampDoubleToInt32(value[i]); |
| ok = TIFFWriteDirectoryTagSlongArray(tif,ndir,dir,tag,count,(int32*)conv); |
| } |
| break; |
| @@ -991,19 +1055,19 @@ |
| if (tif->tif_dir.td_bitspersample<=8) |
| { |
| for (i = 0; i < count; ++i) |
| - ((uint8*)conv)[i] = (uint8)value[i]; |
| + ((uint8*)conv)[i] = TIFFClampDoubleToUInt8(value[i]); |
| ok = TIFFWriteDirectoryTagByteArray(tif,ndir,dir,tag,count,(uint8*)conv); |
| } |
| else if (tif->tif_dir.td_bitspersample<=16) |
| { |
| for (i = 0; i < count; ++i) |
| - ((uint16*)conv)[i] = (uint16)value[i]; |
| + ((uint16*)conv)[i] = TIFFClampDoubleToUInt16(value[i]); |
| ok = TIFFWriteDirectoryTagShortArray(tif,ndir,dir,tag,count,(uint16*)conv); |
| } |
| else |
| { |
| for (i = 0; i < count; ++i) |
| - ((uint32*)conv)[i] = (uint32)value[i]; |
| + ((uint32*)conv)[i] = TIFFClampDoubleToUInt32(value[i]); |
| ok = TIFFWriteDirectoryTagLongArray(tif,ndir,dir,tag,count,(uint32*)conv); |
| } |
| break; |
| @@ -2094,15 +2158,25 @@ |
| static int |
| TIFFWriteDirectoryTagCheckedRational(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, double value) |
| { |
| + static const char module[] = "TIFFWriteDirectoryTagCheckedRational"; |
| uint32 m[2]; |
| - assert(value>=0.0); |
| assert(sizeof(uint32)==4); |
| - if (value<=0.0) |
| + if (value<0) |
| + { |
| + TIFFErrorExt(tif->tif_clientdata,module,"Negative value is illegal"); |
| + return 0; |
| + } |
| + else if( value != value ) |
| + { |
| + TIFFErrorExt(tif->tif_clientdata,module,"Not-a-number value is illegal"); |
| + return 0; |
| + } |
| + else if (value==0.0) |
| { |
| m[0]=0; |
| m[1]=1; |
| - } |
| - else if (value==(double)(uint32)value) |
| + } |
| + else if (value <= 0xFFFFFFFFU && value==(double)(uint32)value) |
| { |
| m[0]=(uint32)value; |
| m[1]=1; |
| @@ -2143,7 +2217,7 @@ |
| } |
| for (na=value, nb=m, nc=0; nc<count; na++, nb+=2, nc++) |
| { |
| - if (*na<=0.0) |
| + if (*na<=0.0 || *na != *na) |
| { |
| nb[0]=0; |
| nb[1]=1; |
| @@ -2153,7 +2227,8 @@ |
| nb[0]=(uint32)(*na); |
| nb[1]=1; |
| } |
| - else if (*na<1.0) |
| + else if (*na >= 0 && *na <= (float)0xFFFFFFFFU && |
| + *na==(float)(uint32)(*na)) |
| { |
| nb[0]=(uint32)((double)(*na)*0xFFFFFFFF); |
| nb[1]=0xFFFFFFFF; |