diff --git a/package.json b/package.json index 34d75082..4c198cdd 100755 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ ], "description": "High performance Node.js module to resize JPEG, PNG, WebP and TIFF images using the libvips library", "scripts": { - "test": "node ./node_modules/istanbul/lib/cli.js cover ./node_modules/mocha/bin/_mocha -- --slow=5000 --timeout=10000 ./test/unit/*.js" + "test": "VIPS_WARNING=0 node ./node_modules/istanbul/lib/cli.js cover ./node_modules/mocha/bin/_mocha -- --slow=5000 --timeout=10000 ./test/unit/*.js" }, "main": "index.js", "repository": { diff --git a/src/metadata.cc b/src/metadata.cc index 06c6ff0c..c6e00a00 100755 --- a/src/metadata.cc +++ b/src/metadata.cc @@ -62,6 +62,10 @@ class MetadataWorker : public NanAsyncWorker { imageType = DetermineImageType(baton->bufferIn, baton->bufferInLength); if (imageType != ImageType::UNKNOWN) { image = InitImage(imageType, baton->bufferIn, baton->bufferInLength, VIPS_ACCESS_RANDOM); + if (image == NULL) { + (baton->err).append("Input buffer has corrupt header"); + imageType = ImageType::UNKNOWN; + } } else { (baton->err).append("Input buffer contains unsupported image format"); } @@ -70,8 +74,12 @@ class MetadataWorker : public NanAsyncWorker { imageType = DetermineImageType(baton->fileIn.c_str()); if (imageType != ImageType::UNKNOWN) { image = InitImage(imageType, baton->fileIn.c_str(), VIPS_ACCESS_RANDOM); + if (image == NULL) { + (baton->err).append("Input file has corrupt header"); + imageType = ImageType::UNKNOWN; + } } else { - (baton->err).append("File is of an unsupported image format"); + (baton->err).append("Input file is of an unsupported image format"); } } if (image != NULL && imageType != ImageType::UNKNOWN) { diff --git a/src/resize.cc b/src/resize.cc index 0053f0e9..a0ccdd0c 100755 --- a/src/resize.cc +++ b/src/resize.cc @@ -153,6 +153,10 @@ class ResizeWorker : public NanAsyncWorker { inputImageType = DetermineImageType(baton->bufferIn, baton->bufferInLength); if (inputImageType != ImageType::UNKNOWN) { image = InitImage(inputImageType, baton->bufferIn, baton->bufferInLength, baton->accessMethod); + if (image == NULL) { + (baton->err).append("Input buffer has corrupt header"); + inputImageType = ImageType::UNKNOWN; + } } else { (baton->err).append("Input buffer contains unsupported image format"); } @@ -161,8 +165,12 @@ class ResizeWorker : public NanAsyncWorker { inputImageType = DetermineImageType(baton->fileIn.c_str()); if (inputImageType != ImageType::UNKNOWN) { image = InitImage(inputImageType, baton->fileIn.c_str(), baton->accessMethod); + if (image == NULL) { + (baton->err).append("Input file has corrupt header"); + inputImageType = ImageType::UNKNOWN; + } } else { - (baton->err).append("File is of an unsupported image format"); + (baton->err).append("Input file is of an unsupported image format"); } } if (inputImageType == ImageType::UNKNOWN) { diff --git a/test/fixtures/corrupt-header.jpg b/test/fixtures/corrupt-header.jpg new file mode 100644 index 00000000..6e241eb0 Binary files /dev/null and b/test/fixtures/corrupt-header.jpg differ diff --git a/test/fixtures/index.js b/test/fixtures/index.js index 9d0e657e..d497430c 100755 --- a/test/fixtures/index.js +++ b/test/fixtures/index.js @@ -14,6 +14,7 @@ module.exports = { inputJpgWithGammaHoliness: getPath('gamma_dalai_lama_gray.jpg'), // http://www.4p8.com/eric.brasseur/gamma.html inputJpgWithCmykProfile: getPath('Channel_digital_image_CMYK_color.jpg'), // http://en.wikipedia.org/wiki/File:Channel_digital_image_CMYK_color.jpg inputJpgWithCmykNoProfile: getPath('Channel_digital_image_CMYK_color_no_profile.jpg'), + inputJpgWithCorruptHeader: getPath('corrupt-header.jpg'), inputPng: getPath('50020484-00001.png'), // http://c.searspartsdirect.com/lis_png/PLDM/50020484-00001.png inputPngWithTransparency: getPath('blackbug.png'), // public domain diff --git a/test/unit/io.js b/test/unit/io.js index c531557e..994bb184 100755 --- a/test/unit/io.js +++ b/test/unit/io.js @@ -292,6 +292,22 @@ describe('Input/output', function() { }); }); + it('File input with corrupt header fails gracefully', function(done) { + sharp(fixtures.inputJpgWithCorruptHeader) + .toBuffer(function(err) { + assert.strictEqual(true, !!err); + done(); + }); + }); + + it('Buffer input with corrupt header fails gracefully', function(done) { + sharp(fs.readFileSync(fixtures.inputJpgWithCorruptHeader)) + .toBuffer(function(err) { + assert.strictEqual(true, !!err); + done(); + }); + }); + describe('Output filename without extension uses input format', function() { it('JPEG', function(done) { diff --git a/test/unit/metadata.js b/test/unit/metadata.js index db741d38..272e9162 100755 --- a/test/unit/metadata.js +++ b/test/unit/metadata.js @@ -216,4 +216,20 @@ describe('Image metadata', function() { }); }); + it('File input with corrupt header fails gracefully', function(done) { + sharp(fixtures.inputJpgWithCorruptHeader) + .metadata(function(err) { + assert.strictEqual(true, !!err); + done(); + }); + }); + + it('Buffer input with corrupt header fails gracefully', function(done) { + sharp(fs.readFileSync(fixtures.inputJpgWithCorruptHeader)) + .metadata(function(err) { + assert.strictEqual(true, !!err); + done(); + }); + }); + });