mirror of
https://github.com/lovell/sharp.git
synced 2025-07-09 18:40:16 +02:00
Expose unlimited option for SVG and PNG input #2984
This commit is contained in:
parent
549219f32a
commit
407bfcb42a
@ -18,6 +18,9 @@ Requires libvips v8.12.0
|
|||||||
[#2976](https://github.com/lovell/sharp/pull/2976)
|
[#2976](https://github.com/lovell/sharp/pull/2976)
|
||||||
[@driannaude](https://github.com/driannaude)
|
[@driannaude](https://github.com/driannaude)
|
||||||
|
|
||||||
|
* Expose `unlimited` option for SVG and PNG input, switches off safety features.
|
||||||
|
[#2984](https://github.com/lovell/sharp/issues/2984)
|
||||||
|
|
||||||
## v0.29 - *circle*
|
## v0.29 - *circle*
|
||||||
|
|
||||||
Requires libvips v8.11.3
|
Requires libvips v8.11.3
|
||||||
|
@ -103,6 +103,7 @@ const debuglog = util.debuglog('sharp');
|
|||||||
* @param {number|boolean} [options.limitInputPixels=268402689] - Do not process input images where the number of pixels
|
* @param {number|boolean} [options.limitInputPixels=268402689] - Do not process input images where the number of pixels
|
||||||
* (width x height) exceeds this limit. Assumes image dimensions contained in the input metadata can be trusted.
|
* (width x height) exceeds this limit. Assumes image dimensions contained in the input metadata can be trusted.
|
||||||
* An integral Number of pixels, zero or false to remove limit, true to use default limit of 268402689 (0x3FFF x 0x3FFF).
|
* An integral Number of pixels, zero or false to remove limit, true to use default limit of 268402689 (0x3FFF x 0x3FFF).
|
||||||
|
* @param {boolean} [options.unlimited=false] - Set this to `true` to remove safety features that help prevent memory exhaustion (SVG, PNG).
|
||||||
* @param {boolean} [options.sequentialRead=false] - Set this to `true` to use sequential rather than random access where possible.
|
* @param {boolean} [options.sequentialRead=false] - Set this to `true` to use sequential rather than random access where possible.
|
||||||
* This can reduce memory usage and might improve performance on some systems.
|
* This can reduce memory usage and might improve performance on some systems.
|
||||||
* @param {number} [options.density=72] - number representing the DPI for vector images in the range 1 to 100000.
|
* @param {number} [options.density=72] - number representing the DPI for vector images in the range 1 to 100000.
|
||||||
|
15
lib/input.js
15
lib/input.js
@ -9,9 +9,9 @@ const sharp = require('./sharp');
|
|||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
function _inputOptionsFromObject (obj) {
|
function _inputOptionsFromObject (obj) {
|
||||||
const { raw, density, limitInputPixels, sequentialRead, failOnError, animated, page, pages, subifd } = obj;
|
const { raw, density, limitInputPixels, unlimited, sequentialRead, failOnError, animated, page, pages, subifd } = obj;
|
||||||
return [raw, density, limitInputPixels, sequentialRead, failOnError, animated, page, pages, subifd].some(is.defined)
|
return [raw, density, limitInputPixels, unlimited, sequentialRead, failOnError, animated, page, pages, subifd].some(is.defined)
|
||||||
? { raw, density, limitInputPixels, sequentialRead, failOnError, animated, page, pages, subifd }
|
? { raw, density, limitInputPixels, unlimited, sequentialRead, failOnError, animated, page, pages, subifd }
|
||||||
: undefined;
|
: undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -23,6 +23,7 @@ function _createInputDescriptor (input, inputOptions, containerOptions) {
|
|||||||
const inputDescriptor = {
|
const inputDescriptor = {
|
||||||
failOnError: true,
|
failOnError: true,
|
||||||
limitInputPixels: Math.pow(0x3FFF, 2),
|
limitInputPixels: Math.pow(0x3FFF, 2),
|
||||||
|
unlimited: false,
|
||||||
sequentialRead: false
|
sequentialRead: false
|
||||||
};
|
};
|
||||||
if (is.string(input)) {
|
if (is.string(input)) {
|
||||||
@ -83,6 +84,14 @@ function _createInputDescriptor (input, inputOptions, containerOptions) {
|
|||||||
throw is.invalidParameterError('limitInputPixels', 'integer >= 0', inputOptions.limitInputPixels);
|
throw is.invalidParameterError('limitInputPixels', 'integer >= 0', inputOptions.limitInputPixels);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// unlimited
|
||||||
|
if (is.defined(inputOptions.unlimited)) {
|
||||||
|
if (is.bool(inputOptions.unlimited)) {
|
||||||
|
inputDescriptor.unlimited = inputOptions.unlimited;
|
||||||
|
} else {
|
||||||
|
throw is.invalidParameterError('unlimited', 'boolean', inputOptions.unlimited);
|
||||||
|
}
|
||||||
|
}
|
||||||
// sequentialRead
|
// sequentialRead
|
||||||
if (is.defined(inputOptions.sequentialRead)) {
|
if (is.defined(inputOptions.sequentialRead)) {
|
||||||
if (is.bool(inputOptions.sequentialRead)) {
|
if (is.bool(inputOptions.sequentialRead)) {
|
||||||
|
@ -132,6 +132,8 @@ namespace sharp {
|
|||||||
descriptor->limitInputPixels = AttrAsUint32(input, "limitInputPixels");
|
descriptor->limitInputPixels = AttrAsUint32(input, "limitInputPixels");
|
||||||
// Allow switch from random to sequential access
|
// Allow switch from random to sequential access
|
||||||
descriptor->access = AttrAsBool(input, "sequentialRead") ? VIPS_ACCESS_SEQUENTIAL : VIPS_ACCESS_RANDOM;
|
descriptor->access = AttrAsBool(input, "sequentialRead") ? VIPS_ACCESS_SEQUENTIAL : VIPS_ACCESS_RANDOM;
|
||||||
|
// Remove safety features and allow unlimited SVG/PNG input
|
||||||
|
descriptor->unlimited = AttrAsBool(input, "unlimited");
|
||||||
return descriptor;
|
return descriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -328,7 +330,7 @@ namespace sharp {
|
|||||||
vips::VOption *option = VImage::option()
|
vips::VOption *option = VImage::option()
|
||||||
->set("access", descriptor->access)
|
->set("access", descriptor->access)
|
||||||
->set("fail", descriptor->failOnError);
|
->set("fail", descriptor->failOnError);
|
||||||
if (imageType == ImageType::SVG) {
|
if (descriptor->unlimited && (imageType == ImageType::SVG || imageType == ImageType::PNG)) {
|
||||||
option->set("unlimited", TRUE);
|
option->set("unlimited", TRUE);
|
||||||
}
|
}
|
||||||
if (imageType == ImageType::SVG || imageType == ImageType::PDF) {
|
if (imageType == ImageType::SVG || imageType == ImageType::PDF) {
|
||||||
@ -403,7 +405,7 @@ namespace sharp {
|
|||||||
vips::VOption *option = VImage::option()
|
vips::VOption *option = VImage::option()
|
||||||
->set("access", descriptor->access)
|
->set("access", descriptor->access)
|
||||||
->set("fail", descriptor->failOnError);
|
->set("fail", descriptor->failOnError);
|
||||||
if (imageType == ImageType::SVG) {
|
if (descriptor->unlimited && (imageType == ImageType::SVG || imageType == ImageType::PNG)) {
|
||||||
option->set("unlimited", TRUE);
|
option->set("unlimited", TRUE);
|
||||||
}
|
}
|
||||||
if (imageType == ImageType::SVG || imageType == ImageType::PDF) {
|
if (imageType == ImageType::SVG || imageType == ImageType::PDF) {
|
||||||
|
@ -50,6 +50,7 @@ namespace sharp {
|
|||||||
char *buffer;
|
char *buffer;
|
||||||
bool failOnError;
|
bool failOnError;
|
||||||
int limitInputPixels;
|
int limitInputPixels;
|
||||||
|
bool unlimited;
|
||||||
VipsAccess access;
|
VipsAccess access;
|
||||||
size_t bufferLength;
|
size_t bufferLength;
|
||||||
bool isBuffer;
|
bool isBuffer;
|
||||||
@ -75,6 +76,7 @@ namespace sharp {
|
|||||||
buffer(nullptr),
|
buffer(nullptr),
|
||||||
failOnError(TRUE),
|
failOnError(TRUE),
|
||||||
limitInputPixels(0x3FFF * 0x3FFF),
|
limitInputPixels(0x3FFF * 0x3FFF),
|
||||||
|
unlimited(FALSE),
|
||||||
access(VIPS_ACCESS_RANDOM),
|
access(VIPS_ACCESS_RANDOM),
|
||||||
bufferLength(0),
|
bufferLength(0),
|
||||||
isBuffer(FALSE),
|
isBuffer(FALSE),
|
||||||
|
@ -648,6 +648,19 @@ describe('Input/output', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('Switch off safety limits for PNG/SVG input', () => {
|
||||||
|
it('Valid', () => {
|
||||||
|
assert.doesNotThrow(() => {
|
||||||
|
sharp({ unlimited: true });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('Invalid', () => {
|
||||||
|
assert.throws(() => {
|
||||||
|
sharp({ unlimited: -1 });
|
||||||
|
}, /Expected boolean for unlimited but received -1 of type number/);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('Limit pixel count of input image', () => {
|
describe('Limit pixel count of input image', () => {
|
||||||
it('Invalid fails - negative', () => {
|
it('Invalid fails - negative', () => {
|
||||||
assert.throws(() => {
|
assert.throws(() => {
|
||||||
@ -671,7 +684,9 @@ describe('Input/output', function () {
|
|||||||
sharp(fixtures.inputJpg)
|
sharp(fixtures.inputJpg)
|
||||||
.metadata()
|
.metadata()
|
||||||
.then(({ width, height }) =>
|
.then(({ width, height }) =>
|
||||||
sharp(fixtures.inputJpg, { limitInputPixels: width * height }).toBuffer()
|
sharp(fixtures.inputJpg, { limitInputPixels: width * height })
|
||||||
|
.resize(2)
|
||||||
|
.toBuffer()
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user