Expose ability to (un)block libvips ops by name

This commit is contained in:
Lovell Fuller 2023-07-19 16:53:52 +01:00
parent a0e1c39785
commit 739b317a6f
8 changed files with 178 additions and 1 deletions

View File

@ -165,4 +165,59 @@ const simd = sharp.simd();
```js ```js
const simd = sharp.simd(false); const simd = sharp.simd(false);
// prevent libvips from using liborc at runtime // prevent libvips from using liborc at runtime
```
## block
Block libvips operations at runtime.
This is in addition to the `VIPS_BLOCK_UNTRUSTED` environment variable,
which when set will block all "untrusted" operations.
**Since**: 0.32.4
| Param | Type | Description |
| --- | --- | --- |
| options | <code>Object</code> | |
| options.operation | <code>Array.&lt;string&gt;</code> | List of libvips low-level operation names to block. |
**Example** *(Block all TIFF input.)*
```js
sharp.block({
operation: ['VipsForeignLoadTiff']
});
```
## unblock
Unblock libvips operations at runtime.
This is useful for defining a list of allowed operations.
**Since**: 0.32.4
| Param | Type | Description |
| --- | --- | --- |
| options | <code>Object</code> | |
| options.operation | <code>Array.&lt;string&gt;</code> | List of libvips low-level operation names to unblock. |
**Example** *(Block all input except WebP from the filesystem.)*
```js
sharp.block({
operation: ['VipsForeignLoad']
});
sharp.unblock({
operation: ['VipsForeignLoadWebpFile']
});
```
**Example** *(Block all input except JPEG and PNG from a Buffer or Stream.)*
```js
sharp.block({
operation: ['VipsForeignLoad']
});
sharp.unblock({
operation: ['VipsForeignLoadJpegBuffer', 'VipsForeignLoadPngBuffer']
});
``` ```

View File

@ -4,6 +4,10 @@
Requires libvips v8.14.2 Requires libvips v8.14.2
### v0.32.4 - TBD
* Expose ability to (un)block low-level libvips operations by name.
### v0.32.3 - 14th July 2023 ### v0.32.3 - 14th July 2023
* Expose `preset` option for WebP output. * Expose `preset` option for WebP output.

File diff suppressed because one or more lines are too long

View File

@ -202,6 +202,72 @@ function simd (simd) {
} }
simd(true); simd(true);
/**
* Block libvips operations at runtime.
*
* This is in addition to the `VIPS_BLOCK_UNTRUSTED` environment variable,
* which when set will block all "untrusted" operations.
*
* @since 0.32.4
*
* @example <caption>Block all TIFF input.</caption>
* sharp.block({
* operation: ['VipsForeignLoadTiff']
* });
*
* @param {Object} options
* @param {Array<string>} options.operation - List of libvips low-level operation names to block.
*/
function block (options) {
if (is.object(options)) {
if (Array.isArray(options.operation) && options.operation.every(is.string)) {
sharp.block(options.operation, true);
} else {
throw is.invalidParameterError('operation', 'Array<string>', options.operation);
}
} else {
throw is.invalidParameterError('options', 'object', options);
}
}
/**
* Unblock libvips operations at runtime.
*
* This is useful for defining a list of allowed operations.
*
* @since 0.32.4
*
* @example <caption>Block all input except WebP from the filesystem.</caption>
* sharp.block({
* operation: ['VipsForeignLoad']
* });
* sharp.unblock({
* operation: ['VipsForeignLoadWebpFile']
* });
*
* @example <caption>Block all input except JPEG and PNG from a Buffer or Stream.</caption>
* sharp.block({
* operation: ['VipsForeignLoad']
* });
* sharp.unblock({
* operation: ['VipsForeignLoadJpegBuffer', 'VipsForeignLoadPngBuffer']
* });
*
* @param {Object} options
* @param {Array<string>} options.operation - List of libvips low-level operation names to unblock.
*/
function unblock (options) {
if (is.object(options)) {
if (Array.isArray(options.operation) && options.operation.every(is.string)) {
sharp.block(options.operation, false);
} else {
throw is.invalidParameterError('operation', 'Array<string>', options.operation);
}
} else {
throw is.invalidParameterError('options', 'object', options);
}
}
/** /**
* Decorate the Sharp class with utility-related functions. * Decorate the Sharp class with utility-related functions.
* @private * @private
@ -216,4 +282,6 @@ module.exports = function (Sharp) {
Sharp.versions = versions; Sharp.versions = versions;
Sharp.vendor = vendor; Sharp.vendor = vendor;
Sharp.queue = queue; Sharp.queue = queue;
Sharp.block = block;
Sharp.unblock = unblock;
}; };

View File

@ -31,6 +31,7 @@ Napi::Object init(Napi::Env env, Napi::Object exports) {
exports.Set("simd", Napi::Function::New(env, simd)); exports.Set("simd", Napi::Function::New(env, simd));
exports.Set("libvipsVersion", Napi::Function::New(env, libvipsVersion)); exports.Set("libvipsVersion", Napi::Function::New(env, libvipsVersion));
exports.Set("format", Napi::Function::New(env, format)); exports.Set("format", Napi::Function::New(env, format));
exports.Set("block", Napi::Function::New(env, block));
exports.Set("_maxColourDistance", Napi::Function::New(env, _maxColourDistance)); exports.Set("_maxColourDistance", Napi::Function::New(env, _maxColourDistance));
exports.Set("_isUsingJemalloc", Napi::Function::New(env, _isUsingJemalloc)); exports.Set("_isUsingJemalloc", Napi::Function::New(env, _isUsingJemalloc));
exports.Set("stats", Napi::Function::New(env, stats)); exports.Set("stats", Napi::Function::New(env, stats));

View File

@ -164,6 +164,17 @@ Napi::Value format(const Napi::CallbackInfo& info) {
return format; return format;
} }
/*
(Un)block libvips operations at runtime.
*/
void block(const Napi::CallbackInfo& info) {
Napi::Array ops = info[size_t(0)].As<Napi::Array>();
bool const state = info[size_t(1)].As<Napi::Boolean>().Value();
for (unsigned int i = 0; i < ops.Length(); i++) {
vips_operation_block_set(ops.Get(i).As<Napi::String>().Utf8Value().c_str(), state);
}
}
/* /*
Synchronous, internal-only method used by some of the functional tests. Synchronous, internal-only method used by some of the functional tests.
Calculates the maximum colour distance using the DE2000 algorithm Calculates the maximum colour distance using the DE2000 algorithm

View File

@ -12,6 +12,7 @@ Napi::Value counters(const Napi::CallbackInfo& info);
Napi::Value simd(const Napi::CallbackInfo& info); Napi::Value simd(const Napi::CallbackInfo& info);
Napi::Value libvipsVersion(const Napi::CallbackInfo& info); Napi::Value libvipsVersion(const Napi::CallbackInfo& info);
Napi::Value format(const Napi::CallbackInfo& info); Napi::Value format(const Napi::CallbackInfo& info);
void block(const Napi::CallbackInfo& info);
Napi::Value _maxColourDistance(const Napi::CallbackInfo& info); Napi::Value _maxColourDistance(const Napi::CallbackInfo& info);
Napi::Value _isUsingJemalloc(const Napi::CallbackInfo& info); Napi::Value _isUsingJemalloc(const Napi::CallbackInfo& info);

View File

@ -153,4 +153,41 @@ describe('Utilities', function () {
assert.strictEqual(true, Array.isArray(sharp.vendor.installed)); assert.strictEqual(true, Array.isArray(sharp.vendor.installed));
}); });
}); });
describe('Block', () => {
it('Can block a named operation', () => {
sharp.block({ operation: ['test'] });
});
it('Can unblock a named operation', () => {
sharp.unblock({ operation: ['test'] });
});
it('Invalid block operation throws', () => {
assert.throws(() => sharp.block(1),
/Expected object for options but received 1 of type number/
);
assert.throws(() => sharp.block({}),
/Expected Array<string> for operation but received undefined of type undefined/
);
assert.throws(() => sharp.block({ operation: 'fail' }),
/Expected Array<string> for operation but received fail of type string/
);
assert.throws(() => sharp.block({ operation: ['maybe', false] }),
/Expected Array<string> for operation but received maybe,false of type object/
);
});
it('Invalid unblock operation throws', () => {
assert.throws(() => sharp.unblock(1),
/Expected object for options but received 1 of type number/
);
assert.throws(() => sharp.unblock({}),
/Expected Array<string> for operation but received undefined of type undefined/
);
assert.throws(() => sharp.unblock({ operation: 'fail' }),
/Expected Array<string> for operation but received fail of type string/
);
assert.throws(() => sharp.unblock({ operation: ['maybe', false] }),
/Expected Array<string> for operation but received maybe,false of type object/
);
});
});
}); });