1 |
Do strip and tile size calculations in unsigned arithmetic, and then |
2 |
complain if the result overflows signed int32, because callers of these |
3 |
functions expect signed results (tsize_t is signed). CVE-2012-2088 |
4 |
|
5 |
|
6 |
diff -Naur tiff-3.9.6.orig/libtiff/tif_strip.c tiff-3.9.6/libtiff/tif_strip.c |
7 |
--- tiff-3.9.6.orig/libtiff/tif_strip.c 2011-01-03 23:31:28.000000000 -0500 |
8 |
+++ tiff-3.9.6/libtiff/tif_strip.c 2012-06-28 11:10:17.898083177 -0400 |
9 |
@@ -107,6 +107,7 @@ |
10 |
TIFFVStripSize(TIFF* tif, uint32 nrows) |
11 |
{ |
12 |
TIFFDirectory *td = &tif->tif_dir; |
13 |
+ uint32 stripsize; |
14 |
|
15 |
if (nrows == (uint32) -1) |
16 |
nrows = td->td_imagelength; |
17 |
@@ -122,7 +123,7 @@ |
18 |
* YCbCr data for the extended image. |
19 |
*/ |
20 |
uint16 ycbcrsubsampling[2]; |
21 |
- tsize_t w, scanline, samplingarea; |
22 |
+ uint32 w, scanline, samplingarea; |
23 |
|
24 |
TIFFGetFieldDefaulted(tif, TIFFTAG_YCBCRSUBSAMPLING, |
25 |
ycbcrsubsampling + 0, |
26 |
@@ -141,13 +142,27 @@ |
27 |
nrows = TIFFroundup(nrows, ycbcrsubsampling[1]); |
28 |
/* NB: don't need TIFFhowmany here 'cuz everything is rounded */ |
29 |
scanline = multiply(tif, nrows, scanline, "TIFFVStripSize"); |
30 |
- return ((tsize_t) |
31 |
- summarize(tif, scanline, |
32 |
- multiply(tif, 2, scanline / samplingarea, |
33 |
- "TIFFVStripSize"), "TIFFVStripSize")); |
34 |
+ /* a zero anywhere in here means overflow, must return zero */ |
35 |
+ if (scanline > 0) { |
36 |
+ uint32 extra = |
37 |
+ multiply(tif, 2, scanline / samplingarea, |
38 |
+ "TIFFVStripSize"); |
39 |
+ if (extra > 0) |
40 |
+ stripsize = summarize(tif, scanline, extra, |
41 |
+ "TIFFVStripSize"); |
42 |
+ else |
43 |
+ stripsize = 0; |
44 |
+ } else |
45 |
+ stripsize = 0; |
46 |
} else |
47 |
- return ((tsize_t) multiply(tif, nrows, TIFFScanlineSize(tif), |
48 |
- "TIFFVStripSize")); |
49 |
+ stripsize = multiply(tif, nrows, TIFFScanlineSize(tif), |
50 |
+ "TIFFVStripSize"); |
51 |
+ /* Because tsize_t is signed, we might have conversion overflow */ |
52 |
+ if (((tsize_t) stripsize) < 0) { |
53 |
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Integer overflow in %s", "TIFFVStripSize"); |
54 |
+ stripsize = 0; |
55 |
+ } |
56 |
+ return (tsize_t) stripsize; |
57 |
} |
58 |
|
59 |
|
60 |
diff -Naur tiff-3.9.6.orig/libtiff/tif_tile.c tiff-3.9.6/libtiff/tif_tile.c |
61 |
--- tiff-3.9.6.orig/libtiff/tif_tile.c 2010-06-08 14:50:43.000000000 -0400 |
62 |
+++ tiff-3.9.6/libtiff/tif_tile.c 2012-06-28 11:10:17.899083079 -0400 |
63 |
@@ -174,7 +174,7 @@ |
64 |
TIFFTileRowSize(TIFF* tif) |
65 |
{ |
66 |
TIFFDirectory *td = &tif->tif_dir; |
67 |
- tsize_t rowsize; |
68 |
+ uint32 rowsize; |
69 |
|
70 |
if (td->td_tilelength == 0 || td->td_tilewidth == 0) |
71 |
return ((tsize_t) 0); |
72 |
@@ -193,7 +193,7 @@ |
73 |
TIFFVTileSize(TIFF* tif, uint32 nrows) |
74 |
{ |
75 |
TIFFDirectory *td = &tif->tif_dir; |
76 |
- tsize_t tilesize; |
77 |
+ uint32 tilesize; |
78 |
|
79 |
if (td->td_tilelength == 0 || td->td_tilewidth == 0 || |
80 |
td->td_tiledepth == 0) |
81 |
@@ -209,12 +209,12 @@ |
82 |
* horizontal/vertical subsampling area include |
83 |
* YCbCr data for the extended image. |
84 |
*/ |
85 |
- tsize_t w = |
86 |
+ uint32 w = |
87 |
TIFFroundup(td->td_tilewidth, td->td_ycbcrsubsampling[0]); |
88 |
- tsize_t rowsize = |
89 |
+ uint32 rowsize = |
90 |
TIFFhowmany8(multiply(tif, w, td->td_bitspersample, |
91 |
"TIFFVTileSize")); |
92 |
- tsize_t samplingarea = |
93 |
+ uint32 samplingarea = |
94 |
td->td_ycbcrsubsampling[0]*td->td_ycbcrsubsampling[1]; |
95 |
if (samplingarea == 0) { |
96 |
TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Invalid YCbCr subsampling"); |
97 |
@@ -223,15 +223,27 @@ |
98 |
nrows = TIFFroundup(nrows, td->td_ycbcrsubsampling[1]); |
99 |
/* NB: don't need TIFFhowmany here 'cuz everything is rounded */ |
100 |
tilesize = multiply(tif, nrows, rowsize, "TIFFVTileSize"); |
101 |
- tilesize = summarize(tif, tilesize, |
102 |
- multiply(tif, 2, tilesize / samplingarea, |
103 |
- "TIFFVTileSize"), |
104 |
+ /* a zero anywhere in here means overflow, must return zero */ |
105 |
+ if (tilesize > 0) { |
106 |
+ uint32 extra = |
107 |
+ multiply(tif, 2, tilesize / samplingarea, |
108 |
"TIFFVTileSize"); |
109 |
+ if (extra > 0) |
110 |
+ tilesize = summarize(tif, tilesize, extra, |
111 |
+ "TIFFVTileSize"); |
112 |
+ else |
113 |
+ tilesize = 0; |
114 |
+ } |
115 |
} else |
116 |
tilesize = multiply(tif, nrows, TIFFTileRowSize(tif), |
117 |
"TIFFVTileSize"); |
118 |
- return ((tsize_t) |
119 |
- multiply(tif, tilesize, td->td_tiledepth, "TIFFVTileSize")); |
120 |
+ tilesize = multiply(tif, tilesize, td->td_tiledepth, "TIFFVTileSize"); |
121 |
+ /* Because tsize_t is signed, we might have conversion overflow */ |
122 |
+ if (((tsize_t) tilesize) < 0) { |
123 |
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Integer overflow in %s", "TIFFVTileSize"); |
124 |
+ tilesize = 0; |
125 |
+ } |
126 |
+ return (tsize_t) tilesize; |
127 |
} |
128 |
|
129 |
/* |