From 8c9c070caf6ba859c36ba69d51a5640bb624dfe2 Mon Sep 17 00:00:00 2001 From: kentongray Date: Mon, 4 Apr 2016 02:35:11 -0500 Subject: [PATCH] Ability to disable limitInputPixels #250 Update docs Added a giant image for testing Adding myself to contributors Added tests to verify giant image can be opened Extend test-win time limit (because of large images) --- docs/api.md | 3 ++- index.js | 11 +++++++++-- package.json | 5 +++-- src/pipeline.cc | 3 ++- test/fixtures/giant-image.png | Bin 0 -> 52205 bytes test/fixtures/index.js | 1 + test/unit/io.js | 18 ++++++++++++++++++ 7 files changed, 35 insertions(+), 6 deletions(-) create mode 100644 test/fixtures/giant-image.png diff --git a/docs/api.md b/docs/api.md index 540f1e24..52ee10f3 100644 --- a/docs/api.md +++ b/docs/api.md @@ -113,7 +113,8 @@ This will reduce memory usage and can improve performance on some systems. Do not process input images where the number of pixels (width * height) exceeds this limit. -`pixels` is the integral Number of pixels, with a value between 1 and the default 268402689 (0x3FFF * 0x3FFF). +`pixels` is either an integral Number of pixels, with a value between 1 and the default 268402689 (0x3FFF * 0x3FFF) or + a boolean. `false` will disable checking while `true` will revert to the default limit. ### Resizing diff --git a/index.js b/index.js index 8becf8d3..6972bd42 100644 --- a/index.js +++ b/index.js @@ -722,10 +722,17 @@ Sharp.prototype.resize = function(width, height) { /* Limit the total number of pixels for input images - Assumes the image dimensions contained in the file header can be trusted + Assumes the image dimensions contained in the file header can be trusted. + Alternatively can use boolean to disable or reset to default (maximum pixels) */ Sharp.prototype.limitInputPixels = function(limit) { - if (typeof limit === 'number' && !Number.isNaN(limit) && limit % 1 === 0 && limit > 0) { + //if we pass in false we represent the integer as 0 to disable + if(limit === false) { + limit = 0; + } else if(limit === true) { + limit = maximum.pixels; + } + if (typeof limit === 'number' && !Number.isNaN(limit) && limit % 1 === 0 && limit >= 0) { this.options.limitInputPixels = limit; } else { throw new Error('Invalid pixel limit (1 to ' + maximum.pixels + ') ' + limit); diff --git a/package.json b/package.json index aa6a96e8..961761cf 100644 --- a/package.json +++ b/package.json @@ -19,13 +19,14 @@ "Bernhard K. Weisshuhn ", "Chris Riley ", "David Carley ", - "John Tobin " + "John Tobin ", + "Kenton Gray " ], "description": "High performance Node.js module to resize JPEG, PNG, WebP and TIFF images using the libvips library", "scripts": { "clean": "rm -rf node_modules/ build/ include/ lib/ coverage/ test/fixtures/output.*", "test": "VIPS_WARNING=0 node ./node_modules/istanbul/lib/cli.js cover ./node_modules/mocha/bin/_mocha -- --slow=5000 --timeout=30000 ./test/unit/*.js", - "test-win": "node ./node_modules/mocha/bin/mocha --slow=5000 --timeout=30000 ./test/unit/*.js", + "test-win": "node ./node_modules/mocha/bin/mocha --slow=5000 --timeout=60000 ./test/unit/*.js", "test-leak": "./test/leak/leak.sh", "test-packaging": "./packaging/test.sh", "test-clean": "rm -rf coverage/ test/fixtures/output.* && npm install && npm test" diff --git a/src/pipeline.cc b/src/pipeline.cc index 16b25cde..63aef9d9 100644 --- a/src/pipeline.cc +++ b/src/pipeline.cc @@ -158,7 +158,8 @@ class PipelineWorker : public AsyncWorker { } // Limit input images to a given number of pixels, where pixels = width * height - if (image.width() * image.height() > baton->limitInputPixels) { + // Ignore if 0 + if (baton->limitInputPixels > 0 && image.width() * image.height() > baton->limitInputPixels) { (baton->err).append("Input image exceeds pixel limit"); return Error(); } diff --git a/test/fixtures/giant-image.png b/test/fixtures/giant-image.png new file mode 100644 index 0000000000000000000000000000000000000000..92c08a77c928d2ed83a39a9287b475b2f3a77b79 GIT binary patch literal 52205 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 literal 0 HcmV?d00001 diff --git a/test/fixtures/index.js b/test/fixtures/index.js index 28bb96ad..6d80af16 100644 --- a/test/fixtures/index.js +++ b/test/fixtures/index.js @@ -79,6 +79,7 @@ module.exports = { inputPngOverlayLayer2LowAlpha: getPath('alpha-layer-2-ink-low-alpha.png'), inputPngAlphaPremultiplicationSmall: getPath('alpha-premultiply-1024x768-paper.png'), inputPngAlphaPremultiplicationLarge: getPath('alpha-premultiply-2048x1536-paper.png'), + inputPngLarge: getPath('giant-image.png'), inputWebP: getPath('4.webp'), // http://www.gstatic.com/webp/gallery/4.webp inputWebPWithTransparency: getPath('5_webp_a.webp'), // http://www.gstatic.com/webp/gallery3/5_webp_a.webp diff --git a/test/unit/io.js b/test/unit/io.js index 923b4d9e..30df745f 100644 --- a/test/unit/io.js +++ b/test/unit/io.js @@ -876,6 +876,24 @@ describe('Input/output', function() { }); }); + it('Disabling limit works', function(done) { + sharp(fixtures.inputPngLarge) + .limitInputPixels(false) + .toBuffer(function(err) { + assert.strictEqual(true, !err); + done(); + }); + }); + + it('Enabling default limit fails works and fails with a large image', function(done) { + sharp(fixtures.inputPngLarge) + .limitInputPixels(true) + .toBuffer(function(err) { + assert.strictEqual(true, !!err); + done(); + }); + }); + it('Smaller than input fails', function(done) { sharp(fixtures.inputJpg).metadata(function(err, metadata) { if (err) throw err;