Brad Bishop | d7bf8c1 | 2018-02-25 22:55:05 -0500 | [diff] [blame] | 1 | Upstream-Status: Backport [https://github.com/opencv/opencv/pull/9448/commits/aacae20] |
| 2 | |
| 3 | Backport patch to fix CVE-2017-14136. |
| 4 | |
| 5 | Ref: https://github.com/opencv/opencv/issues/9443 |
| 6 | |
| 7 | Signed-off-by: Kai Kang <kai.kang@windriver.com> |
| 8 | --- |
| 9 | From aacae2065744adb05e858d327198c7bbe7f452b0 Mon Sep 17 00:00:00 2001 |
| 10 | From: Alexander Alekhin <alexander.alekhin@intel.com> |
| 11 | Date: Wed, 23 Aug 2017 15:15:27 +0300 |
| 12 | Subject: [PATCH] imgcodesc: fix code problems with integer overflow / address |
| 13 | arithmetic / UB |
| 14 | |
| 15 | --- |
| 16 | modules/imgcodecs/src/grfmt_bmp.cpp | 8 ++--- |
| 17 | modules/imgcodecs/src/grfmt_exr.cpp | 10 +++---- |
| 18 | modules/imgcodecs/src/grfmt_jpeg.cpp | 2 +- |
| 19 | modules/imgcodecs/src/grfmt_jpeg2000.cpp | 6 ++-- |
| 20 | modules/imgcodecs/src/grfmt_pam.cpp | 2 +- |
| 21 | modules/imgcodecs/src/grfmt_sunras.cpp | 6 ++-- |
| 22 | modules/imgcodecs/src/utils.cpp | 51 +++++++++++++++++++------------- |
| 23 | modules/imgcodecs/src/utils.hpp | 2 ++ |
| 24 | 8 files changed, 50 insertions(+), 37 deletions(-) |
| 25 | |
| 26 | diff --git a/modules/imgcodecs/src/grfmt_bmp.cpp b/modules/imgcodecs/src/grfmt_bmp.cpp |
| 27 | index 257f97c2d8b..69768e276a3 100644 |
| 28 | --- a/modules/imgcodecs/src/grfmt_bmp.cpp |
| 29 | +++ b/modules/imgcodecs/src/grfmt_bmp.cpp |
| 30 | @@ -193,7 +193,7 @@ bool BmpDecoder::readHeader() |
| 31 | bool BmpDecoder::readData( Mat& img ) |
| 32 | { |
| 33 | uchar* data = img.ptr(); |
| 34 | - int step = (int)img.step; |
| 35 | + int step = validateToInt(img.step); |
| 36 | bool color = img.channels() > 1; |
| 37 | uchar gray_palette[256] = {0}; |
| 38 | bool result = false; |
| 39 | @@ -206,7 +206,7 @@ bool BmpDecoder::readData( Mat& img ) |
| 40 | |
| 41 | if( m_origin == IPL_ORIGIN_BL ) |
| 42 | { |
| 43 | - data += (m_height - 1)*step; |
| 44 | + data += (m_height - 1)*(size_t)step; |
| 45 | step = -step; |
| 46 | } |
| 47 | |
| 48 | @@ -530,7 +530,7 @@ bool BmpEncoder::write( const Mat& img, const std::vector<int>& ) |
| 49 | int bitmapHeaderSize = 40; |
| 50 | int paletteSize = channels > 1 ? 0 : 1024; |
| 51 | int headerSize = 14 /* fileheader */ + bitmapHeaderSize + paletteSize; |
| 52 | - int fileSize = fileStep*height + headerSize; |
| 53 | + size_t fileSize = (size_t)fileStep*height + headerSize; |
| 54 | PaletteEntry palette[256]; |
| 55 | |
| 56 | if( m_buf ) |
| 57 | @@ -540,7 +540,7 @@ bool BmpEncoder::write( const Mat& img, const std::vector<int>& ) |
| 58 | strm.putBytes( fmtSignBmp, (int)strlen(fmtSignBmp) ); |
| 59 | |
| 60 | // write file header |
| 61 | - strm.putDWord( fileSize ); // file size |
| 62 | + strm.putDWord( validateToInt(fileSize) ); // file size |
| 63 | strm.putDWord( 0 ); |
| 64 | strm.putDWord( headerSize ); |
| 65 | |
| 66 | diff --git a/modules/imgcodecs/src/grfmt_exr.cpp b/modules/imgcodecs/src/grfmt_exr.cpp |
| 67 | index 0d2ae9fa7d2..78ffe6c7668 100644 |
| 68 | --- a/modules/imgcodecs/src/grfmt_exr.cpp |
| 69 | +++ b/modules/imgcodecs/src/grfmt_exr.cpp |
| 70 | @@ -195,7 +195,7 @@ bool ExrDecoder::readData( Mat& img ) |
| 71 | bool color = img.channels() > 1; |
| 72 | |
| 73 | uchar* data = img.ptr(); |
| 74 | - int step = img.step; |
| 75 | + size_t step = img.step; |
| 76 | bool justcopy = m_native_depth; |
| 77 | bool chromatorgb = false; |
| 78 | bool rgbtogray = false; |
| 79 | @@ -203,8 +203,8 @@ bool ExrDecoder::readData( Mat& img ) |
| 80 | FrameBuffer frame; |
| 81 | int xsample[3] = {1, 1, 1}; |
| 82 | char *buffer; |
| 83 | - int xstep; |
| 84 | - int ystep; |
| 85 | + size_t xstep = 0; |
| 86 | + size_t ystep = 0; |
| 87 | |
| 88 | xstep = m_native_depth ? 4 : 1; |
| 89 | |
| 90 | @@ -593,7 +593,7 @@ bool ExrEncoder::write( const Mat& img, const std::vector<int>& ) |
| 91 | bool issigned = depth == CV_8S || depth == CV_16S || depth == CV_32S; |
| 92 | bool isfloat = depth == CV_32F || depth == CV_64F; |
| 93 | depth = CV_ELEM_SIZE1(depth)*8; |
| 94 | - const int step = img.step; |
| 95 | + const size_t step = img.step; |
| 96 | |
| 97 | Header header( width, height ); |
| 98 | Imf::PixelType type; |
| 99 | @@ -623,7 +623,7 @@ bool ExrEncoder::write( const Mat& img, const std::vector<int>& ) |
| 100 | FrameBuffer frame; |
| 101 | |
| 102 | char *buffer; |
| 103 | - int bufferstep; |
| 104 | + size_t bufferstep; |
| 105 | int size; |
| 106 | if( type == FLOAT && depth == 32 ) |
| 107 | { |
| 108 | diff --git a/modules/imgcodecs/src/grfmt_jpeg.cpp b/modules/imgcodecs/src/grfmt_jpeg.cpp |
| 109 | index ce942ca1995..caf768d2569 100644 |
| 110 | --- a/modules/imgcodecs/src/grfmt_jpeg.cpp |
| 111 | +++ b/modules/imgcodecs/src/grfmt_jpeg.cpp |
| 112 | @@ -396,7 +396,7 @@ int my_jpeg_load_dht (struct jpeg_decompress_struct *info, unsigned char *dht, |
| 113 | bool JpegDecoder::readData( Mat& img ) |
| 114 | { |
| 115 | volatile bool result = false; |
| 116 | - int step = (int)img.step; |
| 117 | + size_t step = img.step; |
| 118 | bool color = img.channels() > 1; |
| 119 | |
| 120 | if( m_state && m_width && m_height ) |
| 121 | diff --git a/modules/imgcodecs/src/grfmt_jpeg2000.cpp b/modules/imgcodecs/src/grfmt_jpeg2000.cpp |
| 122 | index 950ec21375f..24dfb38bb9d 100644 |
| 123 | --- a/modules/imgcodecs/src/grfmt_jpeg2000.cpp |
| 124 | +++ b/modules/imgcodecs/src/grfmt_jpeg2000.cpp |
| 125 | @@ -156,7 +156,7 @@ bool Jpeg2KDecoder::readData( Mat& img ) |
| 126 | bool result = false; |
| 127 | int color = img.channels() > 1; |
| 128 | uchar* data = img.ptr(); |
| 129 | - int step = (int)img.step; |
| 130 | + size_t step = img.step; |
| 131 | jas_stream_t* stream = (jas_stream_t*)m_stream; |
| 132 | jas_image_t* image = (jas_image_t*)m_image; |
| 133 | |
| 134 | @@ -252,9 +252,9 @@ bool Jpeg2KDecoder::readData( Mat& img ) |
| 135 | if( !jas_image_readcmpt( image, cmptlut[i], 0, 0, xend / xstep, yend / ystep, buffer )) |
| 136 | { |
| 137 | if( img.depth() == CV_8U ) |
| 138 | - result = readComponent8u( data + i, buffer, step, cmptlut[i], maxval, offset, ncmpts ); |
| 139 | + result = readComponent8u( data + i, buffer, validateToInt(step), cmptlut[i], maxval, offset, ncmpts ); |
| 140 | else |
| 141 | - result = readComponent16u( ((unsigned short *)data) + i, buffer, step / 2, cmptlut[i], maxval, offset, ncmpts ); |
| 142 | + result = readComponent16u( ((unsigned short *)data) + i, buffer, validateToInt(step / 2), cmptlut[i], maxval, offset, ncmpts ); |
| 143 | if( !result ) |
| 144 | { |
| 145 | i = ncmpts; |
| 146 | diff --git a/modules/imgcodecs/src/grfmt_pam.cpp b/modules/imgcodecs/src/grfmt_pam.cpp |
| 147 | index 11195dc342c..8eb9e012309 100644 |
| 148 | --- a/modules/imgcodecs/src/grfmt_pam.cpp |
| 149 | +++ b/modules/imgcodecs/src/grfmt_pam.cpp |
| 150 | @@ -479,7 +479,7 @@ bool PAMDecoder::readData( Mat& img ) |
| 151 | { |
| 152 | uchar* data = img.ptr(); |
| 153 | int target_channels = img.channels(); |
| 154 | - int imp_stride = (int)img.step; |
| 155 | + size_t imp_stride = img.step; |
| 156 | int sample_depth = CV_ELEM_SIZE1(m_type); |
| 157 | int src_elems_per_row = m_width*m_channels; |
| 158 | int src_stride = src_elems_per_row*sample_depth; |
| 159 | diff --git a/modules/imgcodecs/src/grfmt_sunras.cpp b/modules/imgcodecs/src/grfmt_sunras.cpp |
| 160 | index aca9b369318..6d448f94ed3 100644 |
| 161 | --- a/modules/imgcodecs/src/grfmt_sunras.cpp |
| 162 | +++ b/modules/imgcodecs/src/grfmt_sunras.cpp |
| 163 | @@ -160,7 +160,7 @@ bool SunRasterDecoder::readData( Mat& img ) |
| 164 | { |
| 165 | int color = img.channels() > 1; |
| 166 | uchar* data = img.ptr(); |
| 167 | - int step = (int)img.step; |
| 168 | + size_t step = img.step; |
| 169 | uchar gray_palette[256] = {0}; |
| 170 | bool result = false; |
| 171 | int src_pitch = ((m_width*m_bpp + 7)/8 + 1) & -2; |
| 172 | @@ -308,11 +308,11 @@ bool SunRasterDecoder::readData( Mat& img ) |
| 173 | code = m_strm.getByte(); |
| 174 | |
| 175 | if( color ) |
| 176 | - data = FillUniColor( data, line_end, step, width3, |
| 177 | + data = FillUniColor( data, line_end, validateToInt(step), width3, |
| 178 | y, m_height, len, |
| 179 | m_palette[code] ); |
| 180 | else |
| 181 | - data = FillUniGray( data, line_end, step, width3, |
| 182 | + data = FillUniGray( data, line_end, validateToInt(step), width3, |
| 183 | y, m_height, len, |
| 184 | gray_palette[code] ); |
| 185 | if( y >= m_height ) |
| 186 | diff --git a/modules/imgcodecs/src/utils.cpp b/modules/imgcodecs/src/utils.cpp |
| 187 | index 2ee5bafc712..474dae008ca 100644 |
| 188 | --- a/modules/imgcodecs/src/utils.cpp |
| 189 | +++ b/modules/imgcodecs/src/utils.cpp |
| 190 | @@ -42,6 +42,13 @@ |
| 191 | #include "precomp.hpp" |
| 192 | #include "utils.hpp" |
| 193 | |
| 194 | +int validateToInt(size_t sz) |
| 195 | +{ |
| 196 | + int valueInt = (int)sz; |
| 197 | + CV_Assert((size_t)valueInt == sz); |
| 198 | + return valueInt; |
| 199 | +} |
| 200 | + |
| 201 | #define SCALE 14 |
| 202 | #define cR (int)(0.299*(1 << SCALE) + 0.5) |
| 203 | #define cG (int)(0.587*(1 << SCALE) + 0.5) |
| 204 | @@ -537,23 +544,25 @@ uchar* FillColorRow1( uchar* data, uchar* indices, int len, PaletteEntry* palett |
| 205 | { |
| 206 | uchar* end = data + len*3; |
| 207 | |
| 208 | + const PaletteEntry p0 = palette[0], p1 = palette[1]; |
| 209 | + |
| 210 | while( (data += 24) < end ) |
| 211 | { |
| 212 | int idx = *indices++; |
| 213 | - *((PaletteEntry*)(data - 24)) = palette[(idx & 128) != 0]; |
| 214 | - *((PaletteEntry*)(data - 21)) = palette[(idx & 64) != 0]; |
| 215 | - *((PaletteEntry*)(data - 18)) = palette[(idx & 32) != 0]; |
| 216 | - *((PaletteEntry*)(data - 15)) = palette[(idx & 16) != 0]; |
| 217 | - *((PaletteEntry*)(data - 12)) = palette[(idx & 8) != 0]; |
| 218 | - *((PaletteEntry*)(data - 9)) = palette[(idx & 4) != 0]; |
| 219 | - *((PaletteEntry*)(data - 6)) = palette[(idx & 2) != 0]; |
| 220 | - *((PaletteEntry*)(data - 3)) = palette[(idx & 1) != 0]; |
| 221 | + *((PaletteEntry*)(data - 24)) = (idx & 128) ? p1 : p0; |
| 222 | + *((PaletteEntry*)(data - 21)) = (idx & 64) ? p1 : p0; |
| 223 | + *((PaletteEntry*)(data - 18)) = (idx & 32) ? p1 : p0; |
| 224 | + *((PaletteEntry*)(data - 15)) = (idx & 16) ? p1 : p0; |
| 225 | + *((PaletteEntry*)(data - 12)) = (idx & 8) ? p1 : p0; |
| 226 | + *((PaletteEntry*)(data - 9)) = (idx & 4) ? p1 : p0; |
| 227 | + *((PaletteEntry*)(data - 6)) = (idx & 2) ? p1 : p0; |
| 228 | + *((PaletteEntry*)(data - 3)) = (idx & 1) ? p1 : p0; |
| 229 | } |
| 230 | |
| 231 | - int idx = indices[0] << 24; |
| 232 | + int idx = indices[0]; |
| 233 | for( data -= 24; data < end; data += 3, idx += idx ) |
| 234 | { |
| 235 | - PaletteEntry clr = palette[idx < 0]; |
| 236 | + const PaletteEntry clr = (idx & 128) ? p1 : p0; |
| 237 | WRITE_PIX( data, clr ); |
| 238 | } |
| 239 | |
| 240 | @@ -565,23 +574,25 @@ uchar* FillGrayRow1( uchar* data, uchar* indices, int len, uchar* palette ) |
| 241 | { |
| 242 | uchar* end = data + len; |
| 243 | |
| 244 | + const uchar p0 = palette[0], p1 = palette[1]; |
| 245 | + |
| 246 | while( (data += 8) < end ) |
| 247 | { |
| 248 | int idx = *indices++; |
| 249 | - *((uchar*)(data - 8)) = palette[(idx & 128) != 0]; |
| 250 | - *((uchar*)(data - 7)) = palette[(idx & 64) != 0]; |
| 251 | - *((uchar*)(data - 6)) = palette[(idx & 32) != 0]; |
| 252 | - *((uchar*)(data - 5)) = palette[(idx & 16) != 0]; |
| 253 | - *((uchar*)(data - 4)) = palette[(idx & 8) != 0]; |
| 254 | - *((uchar*)(data - 3)) = palette[(idx & 4) != 0]; |
| 255 | - *((uchar*)(data - 2)) = palette[(idx & 2) != 0]; |
| 256 | - *((uchar*)(data - 1)) = palette[(idx & 1) != 0]; |
| 257 | + *((uchar*)(data - 8)) = (idx & 128) ? p1 : p0; |
| 258 | + *((uchar*)(data - 7)) = (idx & 64) ? p1 : p0; |
| 259 | + *((uchar*)(data - 6)) = (idx & 32) ? p1 : p0; |
| 260 | + *((uchar*)(data - 5)) = (idx & 16) ? p1 : p0; |
| 261 | + *((uchar*)(data - 4)) = (idx & 8) ? p1 : p0; |
| 262 | + *((uchar*)(data - 3)) = (idx & 4) ? p1 : p0; |
| 263 | + *((uchar*)(data - 2)) = (idx & 2) ? p1 : p0; |
| 264 | + *((uchar*)(data - 1)) = (idx & 1) ? p1 : p0; |
| 265 | } |
| 266 | |
| 267 | - int idx = indices[0] << 24; |
| 268 | + int idx = indices[0]; |
| 269 | for( data -= 8; data < end; data++, idx += idx ) |
| 270 | { |
| 271 | - data[0] = palette[idx < 0]; |
| 272 | + data[0] = (idx & 128) ? p1 : p0; |
| 273 | } |
| 274 | |
| 275 | return data; |
| 276 | diff --git a/modules/imgcodecs/src/utils.hpp b/modules/imgcodecs/src/utils.hpp |
| 277 | index cab10609db2..7af4c6174ee 100644 |
| 278 | --- a/modules/imgcodecs/src/utils.hpp |
| 279 | +++ b/modules/imgcodecs/src/utils.hpp |
| 280 | @@ -42,6 +42,8 @@ |
| 281 | #ifndef _UTILS_H_ |
| 282 | #define _UTILS_H_ |
| 283 | |
| 284 | +int validateToInt(size_t step); |
| 285 | + |
| 286 | struct PaletteEntry |
| 287 | { |
| 288 | unsigned char b, g, r, a; |