Fix out of bounds read in PNG decoder, don't crash on invalid scanline filter byte (Thanks khang06, addresses #590)

This commit is contained in:
UnknownShadow200 2019-06-01 12:07:47 +10:00
parent 8999a1accb
commit 831330df5c
4 changed files with 14 additions and 14 deletions

View File

@ -113,10 +113,6 @@ static void Png_Reconstruct(uint8_t type, uint8_t bytesPerPixel, uint8_t* line,
else { line[i] += c; }
}
return;
default:
Logger_Abort("PNG scanline has invalid filter type");
return;
}
}
@ -475,11 +471,13 @@ ReturnCode Png_Decode(Bitmap* bmp, struct Stream* stream) {
/* reached end of buffer, cycle back to start */
if (bufferIdx == bufferLen) bufferIdx = 0;
for (rowY = begY; rowY < endY; rowY++, curY++) {
/* NOTE: Need to check curY too, in case IDAT is corrupted and has extra data */
for (rowY = begY; rowY < endY && curY < bmp->Height; rowY++, curY++) {
uint32_t priorY = rowY == 0 ? bufferRows : rowY;
uint8_t* prior = &buffer[(priorY - 1) * scanlineBytes];
uint8_t* scanline = &buffer[rowY * scanlineBytes];
if (scanline[0] > PNG_FILTER_PAETH) return PNG_ERR_INVALID_SCANLINE;
Png_Reconstruct(scanline[0], bytesPerPixel, &scanline[1], &prior[1], scanlineSize);
rowExpander(bmp->Width, palette, &scanline[1], Bitmap_GetRow(bmp, curY));
}

View File

@ -27,6 +27,7 @@ enum ERRORS_ALL {
PNG_ERR_INVALID_SIG, PNG_ERR_INVALID_HDR_SIZE, PNG_ERR_TOO_WIDE, PNG_ERR_TOO_TALL,
PNG_ERR_INVALID_COL_BPP, PNG_ERR_COMP_METHOD, PNG_ERR_FILTER, PNG_ERR_INTERLACED,
PNG_ERR_PAL_SIZE, PNG_ERR_TRANS_COUNT, PNG_ERR_TRANS_INVALID, PNG_ERR_INVALID_END_SIZE, PNG_ERR_NO_DATA,
PNG_ERR_INVALID_SCANLINE,
/* ZIP archive decoding errors */
ZIP_ERR_TOO_MANY_ENTRIES, ZIP_ERR_SEEK_END_OF_CENTRAL_DIR, ZIP_ERR_NO_END_OF_CENTRAL_DIR,
ZIP_ERR_SEEK_CENTRAL_DIR, ZIP_ERR_INVALID_CENTRAL_DIR,

View File

@ -117,6 +117,7 @@ static const char* Logger_GetCCErrorDesc(ReturnCode res) {
case PNG_ERR_TRANS_INVALID: return "Transparency invalid for color type";
case PNG_ERR_INVALID_END_SIZE: return "Non-empty IEND chunk";
case PNG_ERR_NO_DATA: return "No image in PNG";
case PNG_ERR_INVALID_SCANLINE: return "Invalid PNG scanline type";
/* ZIP archive decoding errors */ /*
ZIP_ERR_TOO_MANY_ENTRIES,

View File

@ -2803,7 +2803,7 @@ static EM_BOOL Window_KeyPress(int type, const EmscriptenKeyboardEvent* ev, void
}
static void Window_HookEvents(void) {
emscripten_set_wheel_callback("#canvas", NULL, 0, Window_MouseWheel);
emscripten_set_wheel_callback("#window", NULL, 0, Window_MouseWheel);
emscripten_set_mousedown_callback("#canvas", NULL, 0, Window_MouseButton);
emscripten_set_mouseup_callback("#canvas", NULL, 0, Window_MouseButton);
emscripten_set_mousemove_callback("#canvas", NULL, 0, Window_MouseMove);
@ -2819,10 +2819,10 @@ static void Window_HookEvents(void) {
emscripten_set_keyup_callback("#window", NULL, 0, Window_Key);
emscripten_set_keypress_callback("#window", NULL, 0, Window_KeyPress);
emscripten_set_touchstart_callback(0, NULL, 0, Window_TouchStart);
emscripten_set_touchmove_callback(0, NULL, 0, Window_TouchMove);
emscripten_set_touchend_callback(0, NULL, 0, Window_TouchEnd);
emscripten_set_touchcancel_callback(0, NULL, 0, Window_TouchEnd);
emscripten_set_touchstart_callback("#window", NULL, 0, Window_TouchStart);
emscripten_set_touchmove_callback("#window", NULL, 0, Window_TouchMove);
emscripten_set_touchend_callback("#window", NULL, 0, Window_TouchEnd);
emscripten_set_touchcancel_callback("#window", NULL, 0, Window_TouchEnd);
}
static void Window_UnhookEvents(void) {
@ -2842,10 +2842,10 @@ static void Window_UnhookEvents(void) {
emscripten_set_keyup_callback("#window", NULL, 0, NULL);
emscripten_set_keypress_callback("#window", NULL, 0, NULL);
emscripten_set_touchstart_callback(0, NULL, 0, NULL);
emscripten_set_touchmove_callback(0, NULL, 0, NULL);
emscripten_set_touchend_callback(0, NULL, 0, NULL);
emscripten_set_touchcancel_callback(0, NULL, 0, NULL);
emscripten_set_touchstart_callback("#window", NULL, 0, NULL);
emscripten_set_touchmove_callback("#window", NULL, 0, NULL);
emscripten_set_touchend_callback("#window", NULL, 0, NULL);
emscripten_set_touchcancel_callback("#window", NULL, 0, NULL);
}
void Window_Init(void) {