utils.h: add SizeOverflow()

this normalizes the 'size != (size_t)size' checks in the libraries.

Change-Id: I1e8ccd0d3697266f23911ecf0f7a546f011befde
This commit is contained in:
James Zern 2021-06-14 12:20:35 -07:00
parent 695bdaa2f6
commit 28d488e6f1
6 changed files with 13 additions and 9 deletions

View File

@ -705,7 +705,7 @@ static int AllocateMemory(VP8Decoder* const dec) {
+ cache_size + alpha_size + WEBP_ALIGN_CST; + cache_size + alpha_size + WEBP_ALIGN_CST;
uint8_t* mem; uint8_t* mem;
if (needed != (size_t)needed) return 0; // check for overflow if (!CheckSizeOverflow(needed)) return 0; // check for overflow
if (needed > dec->mem_size_) { if (needed > dec->mem_size_) {
WebPSafeFree(dec->mem_); WebPSafeFree(dec->mem_);
dec->mem_size_ = 0; dec->mem_size_ = 0;

View File

@ -312,7 +312,7 @@ static int InitYUVRescaler(const VP8Io* const io, WebPDecParams* const p) {
} }
rescaler_size = num_rescalers * sizeof(*p->scaler_y) + WEBP_ALIGN_CST; rescaler_size = num_rescalers * sizeof(*p->scaler_y) + WEBP_ALIGN_CST;
total_size += rescaler_size; total_size += rescaler_size;
if (total_size != (size_t)total_size) { if (!CheckSizeOverflow(total_size)) {
return 0; return 0;
} }
@ -499,7 +499,7 @@ static int InitRGBRescaler(const VP8Io* const io, WebPDecParams* const p) {
total_size = tmp_size1 * sizeof(*work) + tmp_size2 * sizeof(*tmp); total_size = tmp_size1 * sizeof(*work) + tmp_size2 * sizeof(*tmp);
rescaler_size = num_rescalers * sizeof(*p->scaler_y) + WEBP_ALIGN_CST; rescaler_size = num_rescalers * sizeof(*p->scaler_y) + WEBP_ALIGN_CST;
total_size += rescaler_size; total_size += rescaler_size;
if (total_size != (size_t)total_size) { if (!CheckSizeOverflow(total_size)) {
return 0; return 0;
} }

View File

@ -153,7 +153,7 @@ static int ZeroFillCanvas(uint8_t* buf, uint32_t canvas_width,
uint32_t canvas_height) { uint32_t canvas_height) {
const uint64_t size = const uint64_t size =
(uint64_t)canvas_width * canvas_height * NUM_CHANNELS * sizeof(*buf); (uint64_t)canvas_width * canvas_height * NUM_CHANNELS * sizeof(*buf);
if (size != (size_t)size) return 0; if (!CheckSizeOverflow(size)) return 0;
memset(buf, 0, (size_t)size); memset(buf, 0, (size_t)size);
return 1; return 1;
} }
@ -174,7 +174,7 @@ static void ZeroFillFrameRect(uint8_t* buf, int buf_stride, int x_offset,
static int CopyCanvas(const uint8_t* src, uint8_t* dst, static int CopyCanvas(const uint8_t* src, uint8_t* dst,
uint32_t width, uint32_t height) { uint32_t width, uint32_t height) {
const uint64_t size = (uint64_t)width * height * NUM_CHANNELS; const uint64_t size = (uint64_t)width * height * NUM_CHANNELS;
if (size != (size_t)size) return 0; if (!CheckSizeOverflow(size)) return 0;
assert(src != NULL && dst != NULL); assert(src != NULL && dst != NULL);
memcpy(dst, src, (size_t)size); memcpy(dst, src, (size_t)size);
return 1; return 1;

View File

@ -278,7 +278,7 @@ void VP8LPutBitsFlushBits(VP8LBitWriter* const bw) {
// If needed, make some room by flushing some bits out. // If needed, make some room by flushing some bits out.
if (bw->cur_ + VP8L_WRITER_BYTES > bw->end_) { if (bw->cur_ + VP8L_WRITER_BYTES > bw->end_) {
const uint64_t extra_size = (bw->end_ - bw->buf_) + MIN_EXTRA_SIZE; const uint64_t extra_size = (bw->end_ - bw->buf_) + MIN_EXTRA_SIZE;
if (extra_size != (size_t)extra_size || if (!CheckSizeOverflow(extra_size) ||
!VP8LBitWriterResize(bw, (size_t)extra_size)) { !VP8LBitWriterResize(bw, (size_t)extra_size)) {
bw->cur_ = bw->buf_; bw->cur_ = bw->buf_;
bw->error_ = 1; bw->error_ = 1;
@ -314,7 +314,7 @@ void VP8LPutBitsInternal(VP8LBitWriter* const bw, uint32_t bits, int n_bits) {
while (used >= VP8L_WRITER_BITS) { while (used >= VP8L_WRITER_BITS) {
if (bw->cur_ + VP8L_WRITER_BYTES > bw->end_) { if (bw->cur_ + VP8L_WRITER_BYTES > bw->end_) {
const uint64_t extra_size = (bw->end_ - bw->buf_) + MIN_EXTRA_SIZE; const uint64_t extra_size = (bw->end_ - bw->buf_) + MIN_EXTRA_SIZE;
if (extra_size != (size_t)extra_size || if (!CheckSizeOverflow(extra_size) ||
!VP8LBitWriterResize(bw, (size_t)extra_size)) { !VP8LBitWriterResize(bw, (size_t)extra_size)) {
bw->cur_ = bw->buf_; bw->cur_ = bw->buf_;
bw->error_ = 1; bw->error_ = 1;

View File

@ -172,7 +172,7 @@ static int CheckSizeArgumentsOverflow(uint64_t nmemb, size_t size) {
const uint64_t total_size = nmemb * size; const uint64_t total_size = nmemb * size;
if (nmemb == 0) return 1; if (nmemb == 0) return 1;
if ((uint64_t)size > WEBP_MAX_ALLOCABLE_MEMORY / nmemb) return 0; if ((uint64_t)size > WEBP_MAX_ALLOCABLE_MEMORY / nmemb) return 0;
if (total_size != (size_t)total_size) return 0; if (!CheckSizeOverflow(total_size)) return 0;
#if defined(PRINT_MEM_INFO) && defined(MALLOC_FAIL_AT) #if defined(PRINT_MEM_INFO) && defined(MALLOC_FAIL_AT)
if (countdown_to_fail > 0 && --countdown_to_fail == 0) { if (countdown_to_fail > 0 && --countdown_to_fail == 0) {
return 0; // fake fail! return 0; // fake fail!
@ -181,7 +181,7 @@ static int CheckSizeArgumentsOverflow(uint64_t nmemb, size_t size) {
#if defined(PRINT_MEM_INFO) && defined(MALLOC_LIMIT) #if defined(PRINT_MEM_INFO) && defined(MALLOC_LIMIT)
if (mem_limit > 0) { if (mem_limit > 0) {
const uint64_t new_total_mem = (uint64_t)total_mem + total_size; const uint64_t new_total_mem = (uint64_t)total_mem + total_size;
if (new_total_mem != (size_t)new_total_mem || if (!CheckSizeOverflow(new_total_mem) ||
new_total_mem > mem_limit) { new_total_mem > mem_limit) {
return 0; // fake fail! return 0; // fake fail!
} }

View File

@ -42,6 +42,10 @@ extern "C" {
#endif #endif
#endif // WEBP_MAX_ALLOCABLE_MEMORY #endif // WEBP_MAX_ALLOCABLE_MEMORY
static WEBP_INLINE int CheckSizeOverflow(uint64_t size) {
return size == (size_t)size;
}
// size-checking safe malloc/calloc: verify that the requested size is not too // size-checking safe malloc/calloc: verify that the requested size is not too
// large, or return NULL. You don't need to call these for constructs like // large, or return NULL. You don't need to call these for constructs like
// malloc(sizeof(foo)), but only if there's picture-dependent size involved // malloc(sizeof(foo)), but only if there's picture-dependent size involved