Skip to content

Commit 6da57c5

Browse files
fix(worker): throw when an environment-data key cannot be converted to a string
setEnvironmentData and getEnvironmentData converted the key with a helper that swallows a throwing toString() and returns an empty string, so such a key silently read, overwrote or deleted the unrelated empty-string entry. The conversion is checked now and the exception reaches the caller.
1 parent 4ae32eb commit 6da57c5

2 files changed

Lines changed: 48 additions & 2 deletions

File tree

‎NativeScript/runtime/Messaging.cpp‎

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -958,13 +958,28 @@ void SetEmitMessageCallback(const FunctionCallbackInfo<Value>& info) {
958958
state->emitMessage.Reset(isolate, info[0].As<v8::Function>());
959959
}
960960

961+
// The key as the string the store files it under. A key whose conversion throws
962+
// leaves that exception pending for the caller rather than standing in for "".
963+
static bool EnvironmentDataKey(Isolate* isolate, Local<Value> value,
964+
std::string& key) {
965+
Local<v8::String> str;
966+
if (!value->ToString(isolate->GetCurrentContext()).ToLocal(&str)) {
967+
return false;
968+
}
969+
key = tns::ToString(isolate, str);
970+
return true;
971+
}
972+
961973
void SetEnvironmentDataCallback(const FunctionCallbackInfo<Value>& info) {
962974
Isolate* isolate = info.GetIsolate();
963975
if (info.Length() < 1) {
964976
return;
965977
}
966978
Local<Context> context = isolate->GetCurrentContext();
967-
std::string key = tns::ToString(isolate, info[0]);
979+
std::string key;
980+
if (!EnvironmentDataKey(isolate, info[0], key)) {
981+
return;
982+
}
968983
if (info.Length() < 2 || info[1]->IsUndefined()) {
969984
std::lock_guard<std::mutex> lock(g_environmentDataMutex);
970985
g_environmentData.erase(key);
@@ -988,7 +1003,10 @@ void GetEnvironmentDataCallback(const FunctionCallbackInfo<Value>& info) {
9881003
if (info.Length() < 1) {
9891004
return;
9901005
}
991-
std::string key = tns::ToString(isolate, info[0]);
1006+
std::string key;
1007+
if (!EnvironmentDataKey(isolate, info[0], key)) {
1008+
return;
1009+
}
9921010
std::shared_ptr<serialization::SerializedValue> stored;
9931011
{
9941012
std::lock_guard<std::mutex> lock(g_environmentDataMutex);

‎TestRunner/app/tests/MessagingTests.js‎

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,34 @@ describe("Messaging runtime edges", function () {
295295
});
296296
});
297297

298+
describe("environment data keys", function () {
299+
function thrownMessage(fn) {
300+
try {
301+
fn();
302+
} catch (e) {
303+
return e && e.message;
304+
}
305+
return "nothing thrown";
306+
}
307+
308+
it("throws what a key's toString throws instead of using the empty-string key", function () {
309+
var wt = require("node:worker_threads");
310+
var key = { toString: function () { throw new Error("key toString failed"); } };
311+
wt.setEnvironmentData("", "empty");
312+
try {
313+
expect(thrownMessage(function () { wt.setEnvironmentData(key, "other"); }))
314+
.toBe("key toString failed");
315+
expect(thrownMessage(function () { wt.getEnvironmentData(key); }))
316+
.toBe("key toString failed");
317+
expect(thrownMessage(function () { wt.setEnvironmentData(key); }))
318+
.toBe("key toString failed");
319+
expect(wt.getEnvironmentData("")).toBe("empty");
320+
} finally {
321+
wt.setEnvironmentData("");
322+
}
323+
});
324+
});
325+
298326
describe("worker error reporting", function () {
299327
// A worker boots on its own thread, so the first error arrives whenever
300328
// the runner gets to it; specs wait for it and only then settle for

0 commit comments

Comments
 (0)