Skip to content

Commit b4ece1b

Browse files
committed
contextify: use offset/length from Uint8Array
Do not blindly take data from underlying `ArrayBuffer`, use `ByteOffset`/`ByteLength` of `Uint8Array` itself. Additionally, fix tests that weren't actually properly running because of V8's internal code cache. The code should be different, otherwise the cached data won't be used at all. Fix: #4939 PR-URL: #4947 Reviewed-By: Ben Noordhuis <[email protected]>
1 parent 137f53c commit b4ece1b

File tree

2 files changed

+51
-22
lines changed

2 files changed

+51
-22
lines changed

src/node_contextify.cc

+4-3
Original file line numberDiff line numberDiff line change
@@ -518,10 +518,11 @@ class ContextifyScript : public BaseObject {
518518

519519
ScriptCompiler::CachedData* cached_data = nullptr;
520520
if (!cached_data_buf.IsEmpty()) {
521-
ArrayBuffer::Contents contents =
522-
cached_data_buf.ToLocalChecked()->Buffer()->GetContents();
521+
Local<Uint8Array> ui8 = cached_data_buf.ToLocalChecked();
522+
ArrayBuffer::Contents contents = ui8->Buffer()->GetContents();
523523
cached_data = new ScriptCompiler::CachedData(
524-
static_cast<uint8_t*>(contents.Data()), contents.ByteLength());
524+
static_cast<uint8_t*>(contents.Data()) + ui8->ByteOffset(),
525+
ui8->ByteLength());
525526
}
526527

527528
ScriptOrigin origin(filename, lineOffset, columnOffset);

test/parallel/test-vm-cached-data.js

+47-19
Original file line numberDiff line numberDiff line change
@@ -4,30 +4,58 @@ const assert = require('assert');
44
const vm = require('vm');
55
const Buffer = require('buffer').Buffer;
66

7-
const originalSource = '(function bcd() { return \'original\'; })';
7+
function getSource(tag) {
8+
return `(function ${tag}() { return \'${tag}\'; })`;
9+
}
810

9-
// It should produce code cache
10-
const original = new vm.Script(originalSource, {
11-
produceCachedData: true
12-
});
13-
assert(original.cachedData instanceof Buffer);
11+
function produce(source) {
12+
const script = new vm.Script(source, {
13+
produceCachedData: true
14+
});
15+
assert(script.cachedData instanceof Buffer);
1416

15-
assert.equal(original.runInThisContext()(), 'original');
17+
return script.cachedData;
18+
}
1619

17-
// It should consume code cache
18-
const success = new vm.Script(originalSource, {
19-
cachedData: original.cachedData
20-
});
21-
assert(!success.cachedDataRejected);
20+
function testProduceConsume() {
21+
const source = getSource('original');
2222

23-
assert.equal(success.runInThisContext()(), 'original');
23+
const data = produce(source);
2424

25-
// It should reject invalid code cache
26-
const reject = new vm.Script('(function abc() { return \'invalid\'; })', {
27-
cachedData: original.cachedData
28-
});
29-
assert(reject.cachedDataRejected);
30-
assert.equal(reject.runInThisContext()(), 'invalid');
25+
// It should consume code cache
26+
const script = new vm.Script(source, {
27+
cachedData: data
28+
});
29+
assert(!script.cachedDataRejected);
30+
assert.equal(script.runInThisContext()(), 'original');
31+
}
32+
testProduceConsume();
33+
34+
function testRejectInvalid() {
35+
const source = getSource('invalid');
36+
37+
const data = produce(source);
38+
39+
// It should reject invalid code cache
40+
const script = new vm.Script(getSource('invalid_1'), {
41+
cachedData: data
42+
});
43+
assert(script.cachedDataRejected);
44+
assert.equal(script.runInThisContext()(), 'invalid_1');
45+
}
46+
testRejectInvalid();
47+
48+
function testRejectSlice() {
49+
const source = getSource('slice');
50+
51+
const data = produce(source).slice(4);
52+
53+
const script = new vm.Script(source, {
54+
cachedData: data
55+
});
56+
assert(script.cachedDataRejected);
57+
}
58+
testRejectSlice();
3159

3260
// It should throw on non-Buffer cachedData
3361
assert.throws(() => {

0 commit comments

Comments
 (0)