Skip to content

Commit 69a016f

Browse files
committed
avoid signed overflow in cache memory limit
Read the cache values as unsigned integers and keep the megabyte to byte conversion in size_t, so the memory limit no longer wraps at 2048MB and above. Reject non-integer and negative values in the JavaScript layer.
1 parent ead32be commit 69a016f

3 files changed

Lines changed: 20 additions & 3 deletions

File tree

lib/utility.mjs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,12 @@ function cache (options) {
114114
return sharp.cache(0, 0, 0);
115115
}
116116
} else if (is.object(options)) {
117+
for (const property of ['memory', 'files', 'items']) {
118+
const value = options[property];
119+
if (is.defined(value) && !(is.integer(value) && value >= 0)) {
120+
throw is.invalidParameterError(property, 'a positive integer', value);
121+
}
122+
}
117123
return sharp.cache(options.memory, options.files, options.items);
118124
} else {
119125
return sharp.cache();

src/utilities.cc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,15 @@ Napi::Value cache(const Napi::CallbackInfo& info) {
2323

2424
// Set memory limit
2525
if (info[size_t(0)].IsNumber()) {
26-
vips_cache_set_max_mem(info[size_t(0)].As<Napi::Number>().Int32Value() * 1048576);
26+
vips_cache_set_max_mem(static_cast<size_t>(info[size_t(0)].As<Napi::Number>().Uint32Value()) * 1048576);
2727
}
2828
// Set file limit
2929
if (info[size_t(1)].IsNumber()) {
30-
vips_cache_set_max_files(info[size_t(1)].As<Napi::Number>().Int32Value());
30+
vips_cache_set_max_files(info[size_t(1)].As<Napi::Number>().Uint32Value());
3131
}
3232
// Set items limit
3333
if (info[size_t(2)].IsNumber()) {
34-
vips_cache_set_max(info[size_t(2)].As<Napi::Number>().Int32Value());
34+
vips_cache_set_max(info[size_t(2)].As<Napi::Number>().Uint32Value());
3535
}
3636

3737
// Get memory stats

test/unit/util.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,11 @@ suite('Utilities', () => {
5757
t.assert.strictEqual(cache.files.max, 100);
5858
t.assert.strictEqual(cache.items.max, 1000);
5959
});
60+
test('Can be set to a memory maximum of 4096MB', (t) => {
61+
t.plan(1);
62+
const cache = sharp.cache({ memory: 4096, files: 0, items: 0 });
63+
t.assert.strictEqual(cache.memory.max, 4096);
64+
});
6065
test('Ignores invalid values', (t) => {
6166
t.plan(3);
6267
sharp.cache(true);
@@ -65,6 +70,12 @@ suite('Utilities', () => {
6570
t.assert.strictEqual(cache.files.max, 20);
6671
t.assert.strictEqual(cache.items.max, 100);
6772
});
73+
test('Rejects negative values', (t) => {
74+
t.plan(3);
75+
t.assert.throws(() => sharp.cache({ memory: -1 }), /Expected a positive integer for memory but received -1 of type number/);
76+
t.assert.throws(() => sharp.cache({ files: -1 }), /Expected a positive integer for files but received -1 of type number/);
77+
t.assert.throws(() => sharp.cache({ items: 1.5 }), /Expected a positive integer for items but received 1.5 of type number/);
78+
});
6879
});
6980

7081
suite('Concurrency', () => {

0 commit comments

Comments
 (0)