Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/lvandeve/lodepng.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLode <lvandeve@gmail.com>2020-01-12 12:24:07 +0300
committerLode <lvandeve@gmail.com>2020-01-12 12:28:30 +0300
commit2febfe0d105822575328759dd950c8a24b0ad6b3 (patch)
tree20fbbe9bad26bd9506d484dc44c8b0cb64fd8685 /lodepng.cpp
parent9652b36175737fbec20c3cfbfcaaa4b4807ea26f (diff)
handle integer overflow in lodepng_chunk_next and lodepng_chunk_find
Fixes issue https://github.com/lvandeve/lodepng/issues/123
Diffstat (limited to 'lodepng.cpp')
-rw-r--r--lodepng.cpp69
1 files changed, 41 insertions, 28 deletions
diff --git a/lodepng.cpp b/lodepng.cpp
index e5723b5..788c95e 100644
--- a/lodepng.cpp
+++ b/lodepng.cpp
@@ -1,7 +1,7 @@
/*
-LodePNG version 20191219
+LodePNG version 20200112
-Copyright (c) 2005-2019 Lode Vandevenne
+Copyright (c) 2005-2020 Lode Vandevenne
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@@ -44,7 +44,7 @@ Rename this file to lodepng.cpp to use it for C++, or to lodepng.c to use it for
#pragma warning( disable : 4996 ) /*VS does not like fopen, but fopen_s is not standard C so unusable here*/
#endif /*_MSC_VER */
-const char* LODEPNG_VERSION_STRING = "20191219";
+const char* LODEPNG_VERSION_STRING = "20200112";
/*
This source file is built up in the following large parts. The code sections
@@ -135,6 +135,14 @@ static size_t lodepng_strlen(const char* a) {
#define LODEPNG_MIN(a, b) (((a) < (b)) ? (a) : (b))
#define LODEPNG_ABS(x) ((x) < 0 ? -(x) : (x))
+#if defined(LODEPNG_COMPILE_PNG) || defined(LODEPNG_COMPILE_DECODER)
+/* Safely check if adding two integers will overflow (no undefined
+behavior, compiler removing the code, etc...) and output result. */
+static int lodepng_addofl(size_t a, size_t b, size_t* result) {
+ *result = a + b; /* Unsigned addition is well defined and safe in C90 */
+ return *result < a;
+}
+#endif /*defined(LODEPNG_COMPILE_PNG) || defined(LODEPNG_COMPILE_DECODER)*/
#ifdef LODEPNG_COMPILE_DECODER
/* Safely check if multiplying two integers will overflow (no undefined
@@ -144,13 +152,6 @@ static int lodepng_mulofl(size_t a, size_t b, size_t* result) {
return (a != 0 && *result / a != b);
}
-/* Safely check if adding two integers will overflow (no undefined
-behavior, compiler removing the code, etc...) and output result. */
-static int lodepng_addofl(size_t a, size_t b, size_t* result) {
- *result = a + b; /* Unsigned addition is well defined and safe in C90 */
- return *result < a;
-}
-
#ifdef LODEPNG_COMPILE_ZLIB
/* Safely check if a + b > c, even if overflow could happen. */
static int lodepng_gtofl(size_t a, size_t b, size_t c) {
@@ -2515,50 +2516,61 @@ void lodepng_chunk_generate_crc(unsigned char* chunk) {
lodepng_set32bitInt(chunk + 8 + length, CRC);
}
-unsigned char* lodepng_chunk_next(unsigned char* chunk) {
+unsigned char* lodepng_chunk_next(unsigned char* chunk, unsigned char* end) {
+ if(chunk >= end || end - chunk < 12) return end; /*too small to contain a chunk*/
if(chunk[0] == 0x89 && chunk[1] == 0x50 && chunk[2] == 0x4e && chunk[3] == 0x47
&& chunk[4] == 0x0d && chunk[5] == 0x0a && chunk[6] == 0x1a && chunk[7] == 0x0a) {
/* Is PNG magic header at start of PNG file. Jump to first actual chunk. */
return chunk + 8;
} else {
- unsigned total_chunk_length = lodepng_chunk_length(chunk) + 12;
- return chunk + total_chunk_length;
+ size_t total_chunk_length;
+ unsigned char* result;
+ if(lodepng_addofl(lodepng_chunk_length(chunk), 12, &total_chunk_length)) return end;
+ result = chunk + total_chunk_length;
+ if(result < chunk) return end; /*pointer overflow*/
+ return result;
}
}
-const unsigned char* lodepng_chunk_next_const(const unsigned char* chunk) {
+const unsigned char* lodepng_chunk_next_const(const unsigned char* chunk, const unsigned char* end) {
+ if(chunk >= end || end - chunk < 12) return end; /*too small to contain a chunk*/
if(chunk[0] == 0x89 && chunk[1] == 0x50 && chunk[2] == 0x4e && chunk[3] == 0x47
&& chunk[4] == 0x0d && chunk[5] == 0x0a && chunk[6] == 0x1a && chunk[7] == 0x0a) {
/* Is PNG magic header at start of PNG file. Jump to first actual chunk. */
return chunk + 8;
} else {
- unsigned total_chunk_length = lodepng_chunk_length(chunk) + 12;
- return chunk + total_chunk_length;
+ size_t total_chunk_length;
+ const unsigned char* result;
+ if(lodepng_addofl(lodepng_chunk_length(chunk), 12, &total_chunk_length)) return end;
+ result = chunk + total_chunk_length;
+ if(result < chunk) return end; /*pointer overflow*/
+ return result;
}
}
-unsigned char* lodepng_chunk_find(unsigned char* chunk, const unsigned char* end, const char type[5]) {
+unsigned char* lodepng_chunk_find(unsigned char* chunk, unsigned char* end, const char type[5]) {
for(;;) {
- if(chunk + 12 >= end) return 0;
+ if(chunk >= end || end - chunk < 12) return 0; /* past file end: chunk + 12 > end */
if(lodepng_chunk_type_equals(chunk, type)) return chunk;
- chunk = lodepng_chunk_next(chunk);
+ chunk = lodepng_chunk_next(chunk, end);
}
}
const unsigned char* lodepng_chunk_find_const(const unsigned char* chunk, const unsigned char* end, const char type[5]) {
for(;;) {
- if(chunk + 12 >= end) return 0;
+ if(chunk >= end || end - chunk < 12) return 0; /* past file end: chunk + 12 > end */
if(lodepng_chunk_type_equals(chunk, type)) return chunk;
- chunk = lodepng_chunk_next_const(chunk);
+ chunk = lodepng_chunk_next_const(chunk, end);
}
}
unsigned lodepng_chunk_append(unsigned char** out, size_t* outlength, const unsigned char* chunk) {
unsigned i;
- unsigned total_chunk_length = lodepng_chunk_length(chunk) + 12;
+ size_t total_chunk_length, new_length;
unsigned char *chunk_start, *new_buffer;
- size_t new_length = (*outlength) + total_chunk_length;
- if(new_length < total_chunk_length || new_length < (*outlength)) return 77; /*integer overflow happened*/
+
+ if(lodepng_addofl(lodepng_chunk_length(chunk), 12, &total_chunk_length)) return 77;
+ if(lodepng_addofl(*outlength, total_chunk_length, &new_length)) return 77;
new_buffer = (unsigned char*)lodepng_realloc(*out, new_length);
if(!new_buffer) return 83; /*alloc fail*/
@@ -2575,8 +2587,9 @@ unsigned lodepng_chunk_create(unsigned char** out, size_t* outlength, unsigned l
const char* type, const unsigned char* data) {
unsigned i;
unsigned char *chunk, *new_buffer;
- size_t new_length = (*outlength) + length + 12;
- if(new_length < length + 12 || new_length < (*outlength)) return 77; /*integer overflow happened*/
+ size_t new_length = *outlength;
+ if(lodepng_addofl(new_length, length, &new_length)) return 77;
+ if(lodepng_addofl(new_length, 12, &new_length)) return 77;
new_buffer = (unsigned char*)lodepng_realloc(*out, new_length);
if(!new_buffer) return 83; /*alloc fail*/
(*out) = new_buffer;
@@ -4868,7 +4881,7 @@ static void decodeGeneric(unsigned char** out, unsigned* w, unsigned* h,
if(lodepng_chunk_check_crc(chunk)) CERROR_BREAK(state->error, 57); /*invalid CRC*/
}
- if(!IEND) chunk = lodepng_chunk_next_const(chunk);
+ if(!IEND) chunk = lodepng_chunk_next_const(chunk, in + insize);
}
if (state->info_png.color.colortype == LCT_PALETTE
@@ -5750,7 +5763,7 @@ static unsigned addUnknownChunks(ucvector* out, unsigned char* data, size_t data
while((size_t)(inchunk - data) < datasize) {
CERROR_TRY_RETURN(lodepng_chunk_append(&out->data, &out->size, inchunk));
out->allocsize = out->size; /*fix the allocsize again*/
- inchunk = lodepng_chunk_next(inchunk);
+ inchunk = lodepng_chunk_next(inchunk, data + datasize);
}
return 0;
}