From 3144e57770c1e4d26520d8abee750f8ac8b75490 Mon Sep 17 00:00:00 2001 From: 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 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 + + * 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 * 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 /* * 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 #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 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 #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= 0 && *na <= (float)0xFFFFFFFFU && + *na==(float)(uint32)(*na)) { nb[0]=(uint32)((double)(*na)*0xFFFFFFFF); nb[1]=0xFFFFFFFF;