From a1c31dff9d3f4fd2760b3e4c4c15e9f0e85f5f7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20Unneb=C3=A4ck?= Date: Sat, 16 Mar 2019 10:45:43 +0000 Subject: [PATCH] Guard JPEG width/height against maximum supported --- CHANGELOG.md | 1 + src/Image.cc | 28 ++++++++++++++++++---------- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cc24dbb5d..8e9bfcbf3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ project adheres to [Semantic Versioning](http://semver.org/). ### Changed ### Added ### Fixed +* Guard JPEG width/height against maximum supported (#1385) * Fix electron 5 and node 12 compatibility * Fix encoding options (quality) parameter in `canvas.toDataURL()` diff --git a/src/Image.cc b/src/Image.cc index ca2649803..b43a9dade 100644 --- a/src/Image.cc +++ b/src/Image.cc @@ -10,6 +10,11 @@ #include #include "Util.h" +/* Cairo limit: + * https://lists.cairographics.org/archives/cairo/2010-December/021422.html + */ +static constexpr int canvas_max_side = (1 << 15) - 1; + #ifdef HAVE_GIF typedef struct { uint8_t *buf; @@ -252,7 +257,7 @@ NAN_METHOD(Image::SetSource){ argv[0] = Nan::ErrnoException(errorInfo.cerrno, errorInfo.syscall.c_str(), errorInfo.message.c_str(), errorInfo.path.c_str()); } else if (!errorInfo.message.empty()) { argv[0] = Nan::Error(Nan::New(errorInfo.message).ToLocalChecked()); - } else { + } else { argv[0] = Nan::Error(Nan::New(cairo_status_to_string(status)).ToLocalChecked()); } onerrorFn.As()->Call(Isolate::GetCurrent()->GetCurrentContext()->Global(), 1, argv); @@ -453,7 +458,7 @@ Image::loadSurface() { return loadPNG(); } - + if (isGIF(buf)) { #ifdef HAVE_GIF return loadGIF(stream); @@ -604,17 +609,14 @@ Image::loadGIFFromBuffer(uint8_t *buf, unsigned len) { return CAIRO_STATUS_READ_ERROR; } - width = naturalWidth = gif->SWidth; - height = naturalHeight = gif->SHeight; - - /* Cairo limit: - * https://lists.cairographics.org/archives/cairo/2010-December/021422.html - */ - if (width > 32767 || height > 32767) { + if (gif->SWidth > canvas_max_side || gif->SHeight > canvas_max_side) { GIF_CLOSE_FILE(gif); return CAIRO_STATUS_INVALID_SIZE; } + width = naturalWidth = gif->SWidth; + height = naturalHeight = gif->SHeight; + uint8_t *data = new uint8_t[naturalWidth * naturalHeight * 4]; if (!data) { GIF_CLOSE_FILE(gif); @@ -799,7 +801,7 @@ void Image::jpegToARGB(jpeg_decompress_struct* args, uint8_t* data, uint8_t* src cairo_status_t Image::decodeJPEGIntoSurface(jpeg_decompress_struct *args) { cairo_status_t status = CAIRO_STATUS_SUCCESS; - + uint8_t *data = new uint8_t[naturalWidth * naturalHeight * 4]; if (!data) { jpeg_abort_decompress(args); @@ -1078,6 +1080,12 @@ Image::loadJPEG(FILE *stream) { jpeg_read_header(&args, 1); jpeg_start_decompress(&args); + + if (args.output_width > canvas_max_side || args.output_height > canvas_max_side) { + jpeg_destroy_decompress(&args); + return CAIRO_STATUS_INVALID_SIZE; + } + width = naturalWidth = args.output_width; height = naturalHeight = args.output_height;