mirror of
https://github.com/opencv/opencv.git
synced 2026-07-29 23:33:05 +04:00
Merge pull request #27811 from Kumataro:fix27789
imgcodecs: bmp: relax decoding size limit to over 1GiB #27811 Close https://github.com/opencv/opencv/issues/27789 Close https://github.com/opencv/opencv/issues/23233 ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [ ] The feature is well documented and sample code can be built with the project CMake
This commit is contained in:
@@ -59,7 +59,17 @@ void RBaseStream::readBlock()
|
||||
throw RBS_THROW_EOS;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
// See https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/fseek-fseeki64?view=msvc-170
|
||||
// See https://en.wikipedia.org/wiki/64-bit_computing#64-bit_data_models
|
||||
// - Windows uses LLP64 data model, sizeof long int = 32.
|
||||
// - Linux uses LP64 data model, sizeof long int = 64.
|
||||
// So for Windows, we have to use _fseeki64() instead of fseek().
|
||||
_fseeki64( m_file, m_block_pos, SEEK_SET );
|
||||
#else
|
||||
fseek( m_file, m_block_pos, SEEK_SET );
|
||||
#endif
|
||||
|
||||
size_t readed = fread( m_start, 1, m_block_size, m_file );
|
||||
m_end = m_start + readed;
|
||||
|
||||
@@ -120,7 +130,7 @@ void RBaseStream::release()
|
||||
}
|
||||
|
||||
|
||||
void RBaseStream::setPos( int pos )
|
||||
void RBaseStream::setPos( int64_t pos )
|
||||
{
|
||||
CV_Assert(isOpened() && pos >= 0);
|
||||
|
||||
@@ -132,7 +142,7 @@ void RBaseStream::setPos( int pos )
|
||||
}
|
||||
|
||||
int offset = pos % m_block_size;
|
||||
int old_block_pos = m_block_pos;
|
||||
int64_t old_block_pos = m_block_pos;
|
||||
m_block_pos = pos - offset;
|
||||
m_current = m_start + offset;
|
||||
if (old_block_pos != m_block_pos)
|
||||
@@ -140,16 +150,16 @@ void RBaseStream::setPos( int pos )
|
||||
}
|
||||
|
||||
|
||||
int RBaseStream::getPos()
|
||||
int64_t RBaseStream::getPos()
|
||||
{
|
||||
CV_Assert(isOpened());
|
||||
int pos = validateToInt((m_current - m_start) + m_block_pos);
|
||||
int64_t pos = validateToInt64((m_current - m_start) + m_block_pos);
|
||||
CV_Assert(pos >= m_block_pos); // overflow check
|
||||
CV_Assert(pos >= 0); // overflow check
|
||||
return pos;
|
||||
}
|
||||
|
||||
void RBaseStream::skip( int bytes )
|
||||
void RBaseStream::skip( int64_t bytes )
|
||||
{
|
||||
CV_Assert(bytes >= 0);
|
||||
uchar* old = m_current;
|
||||
|
||||
@@ -45,9 +45,9 @@ public:
|
||||
virtual bool open( const Mat& buf );
|
||||
virtual void close();
|
||||
bool isOpened();
|
||||
void setPos( int pos );
|
||||
int getPos();
|
||||
void skip( int bytes );
|
||||
void setPos( int64_t pos );
|
||||
int64_t getPos();
|
||||
void skip( int64_t bytes );
|
||||
|
||||
protected:
|
||||
|
||||
@@ -57,7 +57,7 @@ protected:
|
||||
uchar* m_current;
|
||||
FILE* m_file;
|
||||
int m_block_size;
|
||||
int m_block_pos;
|
||||
int64_t m_block_pos;
|
||||
bool m_is_opened;
|
||||
|
||||
virtual void readBlock();
|
||||
|
||||
@@ -237,9 +237,6 @@ bool BmpDecoder::readData( Mat& img )
|
||||
int nch = color ? 3 : 1;
|
||||
int y, width3 = m_width*nch;
|
||||
|
||||
// FIXIT: use safe pointer arithmetic (avoid 'int'), use size_t, intptr_t, etc
|
||||
CV_Assert(((uint64)m_height * m_width * nch < (CV_BIG_UINT(1) << 30)) && "BMP reader implementation doesn't support large images >= 1Gb");
|
||||
|
||||
if( m_offset < 0 || !m_strm.isOpened())
|
||||
return false;
|
||||
|
||||
|
||||
@@ -87,7 +87,7 @@ protected:
|
||||
PaletteEntry m_palette[256];
|
||||
Origin m_origin;
|
||||
int m_bpp;
|
||||
int m_offset;
|
||||
int64_t m_offset;
|
||||
BmpCompression m_rle_code;
|
||||
uint m_rgba_mask[4];
|
||||
int m_rgba_bit_offset[4];
|
||||
|
||||
@@ -78,8 +78,8 @@ public:
|
||||
protected:
|
||||
|
||||
RLByteStream m_strm;
|
||||
int m_maxval, m_channels, m_sampledepth, m_offset,
|
||||
selected_fmt;
|
||||
int64_t m_offset;
|
||||
int m_maxval, m_channels, m_sampledepth, selected_fmt;
|
||||
bool bit_mode;
|
||||
};
|
||||
|
||||
|
||||
@@ -79,7 +79,7 @@ protected:
|
||||
RLByteStream m_strm;
|
||||
PaletteEntry m_palette[256];
|
||||
int m_bpp;
|
||||
int m_offset;
|
||||
int64_t m_offset;
|
||||
bool m_binary;
|
||||
int m_maxval;
|
||||
};
|
||||
|
||||
@@ -94,7 +94,7 @@ bool SunRasterDecoder::readHeader()
|
||||
m_type = IsColorPalette( m_palette, m_bpp ) ? CV_8UC3 : CV_8UC1;
|
||||
m_offset = m_strm.getPos();
|
||||
|
||||
CV_Assert(m_offset == 32 + m_maplength);
|
||||
CV_Assert(m_offset == static_cast<int64_t>(32 + m_maplength));
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
@@ -107,7 +107,7 @@ bool SunRasterDecoder::readHeader()
|
||||
|
||||
m_offset = m_strm.getPos();
|
||||
|
||||
CV_Assert(m_offset == 32 + m_maplength);
|
||||
CV_Assert(m_offset == static_cast<int64_t>(32 + m_maplength));
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ protected:
|
||||
RMByteStream m_strm;
|
||||
PaletteEntry m_palette[256];
|
||||
int m_bpp;
|
||||
int m_offset;
|
||||
int64_t m_offset;
|
||||
SunRasType m_encoding;
|
||||
SunRasMapType m_maptype;
|
||||
int m_maplength;
|
||||
|
||||
@@ -51,6 +51,13 @@ int validateToInt(size_t sz)
|
||||
return valueInt;
|
||||
}
|
||||
|
||||
int64_t validateToInt64(size_t sz)
|
||||
{
|
||||
int64_t valueInt = static_cast<int64_t>(sz);
|
||||
CV_Assert((size_t)valueInt == sz);
|
||||
return valueInt;
|
||||
}
|
||||
|
||||
#define SCALE 14
|
||||
#define cR (int)(0.299*(1 << SCALE) + 0.5)
|
||||
#define cG (int)(0.587*(1 << SCALE) + 0.5)
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
namespace cv {
|
||||
|
||||
int validateToInt(size_t step);
|
||||
int64_t validateToInt64(size_t step);
|
||||
|
||||
template <typename _Tp> static inline
|
||||
size_t safeCastToSizeT(const _Tp v_origin, const char* msg)
|
||||
|
||||
Reference in New Issue
Block a user