nodejs/deps/v8/test/mjsunit/sandbox/regress/regress-379774687.js
Michaël Zasso 918fe04351
deps: update V8 to 13.6.233.8
PR-URL: https://github.com/nodejs/node/pull/58070
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Reviewed-By: Darshan Sen <raisinten@gmail.com>
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
2025-05-02 15:06:53 +02:00

94 lines
3.1 KiB
JavaScript

// Copyright 2024 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --sandbox-testing --expose-gc
const kSeqStringType = Sandbox.getInstanceTypeIdFor("SEQ_TWO_BYTE_STRING_TYPE");
const kStringHashOffset = Sandbox.getFieldOffset(kSeqStringType, "hash");
let memory = new DataView(new Sandbox.MemoryView(0, 0x100000000));
// Will return random (but deterministic, if a --random-seed is used) numbers.
function randomIntUpTo(n) {
return Math.floor(Math.random() * n);
}
// Helper function that spawns a worker thread that corrupts memory in the
// background, constantly flipping the given address between two values.
function corruptInBackground(address, bitToFlip) {
function workerTemplate(address, bitToFlip) {
let memory = new DataView(new Sandbox.MemoryView(0, 0x100000000));
let oldValue = memory.getUint32(address, true);
let newValue = oldValue ^ bitToFlip;
while (true) {
memory.setUint32(address, newValue, true);
memory.setUint32(address, oldValue, true);
}
}
const workerCode = new Function(
`(${workerTemplate})(${address}, ${bitToFlip})`);
return new Worker(workerCode, {type: 'function'});
}
// Some random code for the parser...
// Need some unicode in here to get a Utf16 string (otherwise, we'd get a
// buffered stream during parsing, which probably complicates things a bit).
function test() {
function log(msg) {}
function launchRockets(n, destination) {
class RocketLauncher {
constructor(type) {
this.rocketType = type ?? '🚀';
this.launchCount = 0;
}
launch(destination) {
log(`Launching ${this.rocketType} to ${destination}!`);
this.launchCount++;
}
}
if (typeof destination === 'undefined') {
destination = "the moon";
}
let launcher = new RocketLauncher;
for (let i = 0; i < n; i++) {
launcher.launch(destination);
}
}
launchRockets(3);
launchRockets(2, "mars");
launchRockets(1, "pluto");
}
// Create a SeqTwoByteString (otherwise we have a slice string)
let source = (test.toString() + "\ntest();").split('').join('');
assertEquals(Sandbox.getInstanceTypeIdOf(source), kSeqStringType);
// Trigger some GCs to move the object to a stable position in memory.
gc();
gc();
// Start the worker thread to corrupt the string in the background.
let size = Sandbox.getSizeOf(source);
assertTrue(size > source.length * 2);
let offset = randomIntUpTo(size);
let string_address = Sandbox.getAddressOf(source);
let bitToFlip = 1 << randomIntUpTo(32);
corruptInBackground(string_address + offset, bitToFlip);
for (let i = 0; i < 1000; i++) {
// Modify the hash in between every attempt to avoid code caching.
// Use + 0x4 here to not change the type bits (see HashFieldTypeBits).
// Alternatively, use --no-compilation-cache.
let currentHash = memory.getUint32(string_address + kStringHashOffset, true);
let newHash = currentHash + 0x4;
memory.setUint32(string_address + kStringHashOffset, newHash, true);
try { eval(source); } catch {}
}