Bug 1440539 - Support time jitter in the JS Shell, and expose a function to enable it. r=luke

This adds jittering to the already existing logic for time clamping. It also exposes a
testing function allowing those interested to enable time clamping or time clamping and
jittering.

Neither (clamping nor jittering) is enabled by default.

MozReview-Commit-ID: JcHCEwRQPch

--HG--
extra : amend_source : 81d9a0c425ed2549561e5b6711f4c654614b1f38
This commit is contained in:
Tom Ritter 2018-03-02 13:47:44 -06:00
Родитель 5345bfb157
Коммит e120c89f6d
2 изменённых файлов: 63 добавлений и 2 удалений

Просмотреть файл

@ -4939,6 +4939,33 @@ IsLegacyIterator(JSContext* cx, unsigned argc, Value* vp)
return true;
}
static bool
SetTimeResolution(JSContext* cx, unsigned argc, Value* vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
RootedObject callee(cx, &args.callee());
if (!args.requireAtLeast(cx, "setTimeResolution", 2))
return false;
if (!args[0].isInt32()) {
ReportUsageErrorASCII(cx, callee, "First argument must be an Int32.");
return false;
}
int32_t resolution = args[0].toInt32();
if (!args[1].isBoolean()) {
ReportUsageErrorASCII(cx, callee, "Second argument must be a Boolean");
return false;
}
bool jitter = args[1].toBoolean();
JS::SetTimeResolutionUsec(resolution, jitter);
args.rval().setUndefined();
return true;
}
static bool
EnableExpressionClosures(JSContext* cx, unsigned argc, Value* vp)
{
@ -5705,6 +5732,11 @@ gc::ZealModeHelpText),
"getTimeZone()",
" Get the current time zone.\n"),
JS_FN_HELP("setTimeResolution", SetTimeResolution, 2, 0,
"setTimeResolution(resolution, jitter)",
" Enables time clamping and jittering. Specify a time resolution in\n"
" microseconds and whether or not to jitter\n"),
JS_FN_HELP("enableExpressionClosures", EnableExpressionClosures, 0, 0,
"enableExpressionClosures()",
" Enables the deprecated, non-standard expression closures.\n"),

33
js/src/jsdate.cpp Normal file → Executable file
Просмотреть файл

@ -1310,8 +1310,37 @@ NowAsMillis()
double now = PRMJ_Now();
if (sReduceMicrosecondTimePrecisionCallback)
now = sReduceMicrosecondTimePrecisionCallback(now);
else if (sResolutionUsec)
now = floor(now / sResolutionUsec) * sResolutionUsec;
else if (sResolutionUsec) {
double clamped = floor(now / sResolutionUsec) * sResolutionUsec;
if (sJitter) {
// Calculate a random midpoint for jittering. In the browser, we are adversarial:
// Web Content may try to calculate the midpoint themselves and use that to bypass
// it's security. In the JS Shell, we are not adversarial, we want to jitter the
// time to recreate the operating environment, but we do not concern ourselves
// with trying to prevent an attacker from calculating the midpoint themselves.
// So we use a very simple, very fast CRC with a hardcoded seed.
uint64_t midpoint = *((uint64_t*)&clamped);
midpoint ^= 0x0F00DD1E2BAD2DED; // XOR in a 'secret'
// MurmurHash3 internal component from
// https://searchfox.org/mozilla-central/rev/61d400da1c692453c2dc2c1cf37b616ce13dea5b/dom/canvas/MurmurHash3.cpp#85
midpoint ^= midpoint >> 33;
midpoint *= uint64_t{0xFF51AFD7ED558CCD};
midpoint ^= midpoint >> 33;
midpoint *= uint64_t{0xC4CEB9FE1A85EC53};
midpoint ^= midpoint >> 33;
midpoint %= sResolutionUsec;
if (now > clamped + midpoint) { // We're jittering up to the next step
now = clamped + sResolutionUsec;
} else { // We're staying at the clamped value
now = clamped;
}
} else { //No jitter, only clamping
now = clamped;
}
}
return TimeClip(now / PRMJ_USEC_PER_MSEC);
}