diff --git a/src/pngchunk_int.cpp b/src/pngchunk_int.cpp index bf389ee1..64a370e5 100644 --- a/src/pngchunk_int.cpp +++ b/src/pngchunk_int.cpp @@ -625,8 +625,12 @@ namespace Exiv2 { const char *sp = (char*) text.pData_+1; // current byte (space pointer) const char *eot = (char*) text.pData_+text.size_; // end of text + if (sp >= eot) { + return DataBuf(); + } + // Look for newline - while (*sp != '\n' && sp < eot ) + while (*sp != '\n') { sp++; if ( sp == eot ) @@ -635,9 +639,12 @@ namespace Exiv2 { } } sp++ ; // step over '\n' + if (sp == eot) { + return DataBuf(); + } // Look for length - while ( (*sp == '\0' || *sp == ' ' || *sp == '\n') && sp < eot ) + while (*sp == '\0' || *sp == ' ' || *sp == '\n') { sp++; if (sp == eot ) @@ -647,7 +654,7 @@ namespace Exiv2 { } const char* startOfLength = sp; - while ( ('0' <= *sp && *sp <= '9') && sp < eot) + while ('0' <= *sp && *sp <= '9') { sp++; if (sp == eot ) @@ -656,8 +663,13 @@ namespace Exiv2 { } } sp++ ; // step over '\n' + if (sp == eot) { + return DataBuf(); + } long length = (long) atol(startOfLength); + enforce(length >= 0, Exiv2::kerCorruptedMetadata); + enforce(length <= (eot - sp)/2, Exiv2::kerCorruptedMetadata); // Allocate space if (length == 0) @@ -682,6 +694,7 @@ namespace Exiv2 { for (long i = 0; i < (long) nibbles; i++) { + enforce(sp < eot, Exiv2::kerCorruptedMetadata); while (*sp < '0' || (*sp > '9' && *sp < 'a') || *sp > 'f') { if (*sp == '\0') @@ -693,6 +706,7 @@ namespace Exiv2 { } sp++; + enforce(sp < eot, Exiv2::kerCorruptedMetadata); } if (i%2 == 0) diff --git a/test/data/issue_845_poc.png b/test/data/issue_845_poc.png new file mode 100644 index 00000000..9f8fe1e9 Binary files /dev/null and b/test/data/issue_845_poc.png differ diff --git a/tests/bugfixes/github/test_issue_845.py b/tests/bugfixes/github/test_issue_845.py new file mode 100644 index 00000000..87814e9d --- /dev/null +++ b/tests/bugfixes/github/test_issue_845.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- + +from system_tests import CaseMeta, path + + +class LargeAllocationInPngChunk(metaclass=CaseMeta): + """ + Regression test for the bug described in: + https://github.com/Exiv2/exiv2/issues/845 + + An unchecked allocation size causes a std::bad_alloc to + be thrown. + """ + url = "https://github.com/Exiv2/exiv2/issues/845" + + filename = path("$data_path/issue_845_poc.png") + commands = ["$exiv2 $filename"] + stdout = [""] + stderr = [ + """$exiv2_exception_message $filename: +$kerCorruptedMetadata +"""] + retval = [1]