Skip to content

Commit b35fd57

Browse files
committed
fix: clamp numeric worker priorities before converting to int
1 parent 557139c commit b35fd57

2 files changed

Lines changed: 47 additions & 10 deletions

File tree

test-app/app/src/main/assets/app/tests/testWorkerOptions.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,22 @@ describe("Worker platform options", function () {
8181
});
8282
});
8383

84+
it("clamps a nice value past the range of a 32-bit integer", function (done) {
85+
reportPriority({ android: { priority: 4294967295 } }, done, function (priority) {
86+
expect(priority).toBe(19);
87+
});
88+
});
89+
90+
// Asserted by starting the worker rather than by the reported nice value,
91+
// for the same privilege reason as the negative names above.
92+
it("accepts a nice value past the negative end of a 32-bit integer", function () {
93+
var worker;
94+
expect(function () {
95+
worker = new Worker(entry, { android: { priority: -4294967296 } });
96+
}).not.toThrow();
97+
worker.terminate();
98+
});
99+
84100
it("still honors the deprecated androidPriority option", function (done) {
85101
reportPriority({ androidPriority: "lowest" }, done, function (priority) {
86102
expect(priority).toBe(19);
@@ -150,4 +166,10 @@ describe("Worker platform options", function () {
150166
new Worker(entry, { android: { priority: {} } });
151167
}).toThrowError(TypeError, /"android\.priority"/);
152168
});
169+
170+
it("throws a TypeError for a NaN android.priority", function () {
171+
expect(function () {
172+
new Worker(entry, { android: { priority: NaN } });
173+
}).toThrowError(TypeError, /"android\.priority"/);
174+
});
153175
});

test-app/runtime/src/main/cpp/CallbackHandlers.cpp

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1146,17 +1146,23 @@ bool MapWorkerPriorityName(const std::string &name, int &priority) {
11461146
return true;
11471147
}
11481148

1149-
// Nice values outside the kernel's range are clamped rather than rejected:
1150-
// a caller asking for "as low as possible" gets it.
1151-
int ClampWorkerPriority(Local<Context> context, Local<Value> value) {
1152-
int priority = value->Int32Value(context).FromMaybe(kDefaultWorkerPriority);
1149+
// Nice values outside the kernel's range are clamped rather than rejected: a
1150+
// caller asking for "as low as possible" gets it. Clamping happens on the
1151+
// double, before any integer conversion - ToInt32 wraps modulo 2^32, which
1152+
// would turn a value past the range into an in-range one. NaN sits on no point
1153+
// of the scale and is left to the caller to accept or reject.
1154+
std::optional<int> ClampWorkerPriority(Local<Value> value) {
1155+
double priority = value.As<Number>()->Value();
1156+
if (std::isnan(priority)) {
1157+
return std::nullopt;
1158+
}
11531159
if (priority < -20) {
11541160
return -20;
11551161
}
11561162
if (priority > 19) {
11571163
return 19;
11581164
}
1159-
return priority;
1165+
return static_cast<int>(priority);
11601166
}
11611167

11621168
// Carries a real TypeError instance so `catch (e) { e instanceof TypeError }`
@@ -1205,15 +1211,22 @@ bool GetWorkerThreadPriority(Isolate *isolate, Local<Context> context,
12051211
return false;
12061212
}
12071213
if (!priorityVal->IsUndefined()) {
1214+
std::optional<int> resolvedPriority;
12081215
if (priorityVal->IsNumber()) {
1209-
priority = ClampWorkerPriority(context, priorityVal);
1210-
} else if (!priorityVal->IsString() ||
1211-
!MapWorkerPriorityName(
1212-
ArgConverter::ConvertToString(priorityVal.As<String>()), priority)) {
1216+
resolvedPriority = ClampWorkerPriority(priorityVal);
1217+
} else if (priorityVal->IsString()) {
1218+
int named;
1219+
if (MapWorkerPriorityName(ArgConverter::ConvertToString(priorityVal.As<String>()),
1220+
named)) {
1221+
resolvedPriority = named;
1222+
}
1223+
}
1224+
if (!resolvedPriority) {
12131225
ThrowWorkerOptionTypeError(
12141226
isolate, std::string("Worker option \"android.priority\" must be one of ") +
12151227
kWorkerPriorityNames + ".");
12161228
}
1229+
priority = *resolvedPriority;
12171230
resolved = true;
12181231
}
12191232
}
@@ -1237,7 +1250,9 @@ bool GetWorkerThreadPriority(Isolate *isolate, Local<Context> context,
12371250
}
12381251

12391252
if (legacyVal->IsNumber()) {
1240-
priority = ClampWorkerPriority(context, legacyVal);
1253+
// The deprecated option takes NaN as nice 0 (THREAD_PRIORITY_DEFAULT)
1254+
// rather than rejecting it.
1255+
priority = ClampWorkerPriority(legacyVal).value_or(0);
12411256
return true;
12421257
}
12431258
if (legacyVal->IsString() &&

0 commit comments

Comments
 (0)