mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 820180 - Isolate JS pseudorandom number generator state per compartment. r=luke.
This commit is contained in:
parent
1aa3ee7e8c
commit
ca9e2f24e6
@ -267,7 +267,7 @@ private:
|
||||
static size_t pageSize;
|
||||
static size_t largeAllocSize;
|
||||
#if WTF_OS_WINDOWS
|
||||
static int64_t rngSeed;
|
||||
static uint64_t rngSeed;
|
||||
#endif
|
||||
|
||||
static const size_t OVERSIZE_ALLOCATION = size_t(-1);
|
||||
|
@ -30,12 +30,12 @@
|
||||
#include "jswin.h"
|
||||
#include "prmjtime.h"
|
||||
|
||||
extern void random_setSeed(int64_t *, int64_t);
|
||||
extern uint64_t random_next(int64_t *, int);
|
||||
extern void random_setSeed(uint64_t *, uint64_t);
|
||||
extern uint64_t random_next(uint64_t *, int);
|
||||
|
||||
namespace JSC {
|
||||
|
||||
int64_t ExecutableAllocator::rngSeed;
|
||||
uint64_t ExecutableAllocator::rngSeed;
|
||||
|
||||
void ExecutableAllocator::initSeed()
|
||||
{
|
||||
|
@ -890,7 +890,8 @@ JSRuntime::JSRuntime(JSUseHelperThreads useHelperThreads)
|
||||
ctypesActivityCallback(NULL),
|
||||
ionReturnOverride_(MagicValue(JS_ARG_POISON)),
|
||||
useHelperThreads_(useHelperThreads),
|
||||
requestedHelperThreadCount(-1)
|
||||
requestedHelperThreadCount(-1),
|
||||
rngNonce(0)
|
||||
{
|
||||
/* Initialize infallibly first, so we can goto bad and JS_DestroyRuntime. */
|
||||
JS_INIT_CLIST(&onNewGlobalObjectWatchers);
|
||||
|
@ -265,8 +265,6 @@ js::NewContext(JSRuntime *rt, size_t stackChunkSize)
|
||||
bool first = rt->contextList.isEmpty();
|
||||
rt->contextList.insertBack(cx);
|
||||
|
||||
js_InitRandom(cx);
|
||||
|
||||
/*
|
||||
* If cx is the first context on this runtime, initialize well-known atoms,
|
||||
* keywords, numbers, strings and self-hosted scripts. If one of these
|
||||
@ -1117,7 +1115,6 @@ JSContext::JSContext(JSRuntime *rt)
|
||||
outstandingRequests(0),
|
||||
#endif
|
||||
resolveFlags(0),
|
||||
rngSeed(0),
|
||||
iterValue(MagicValue(JS_NO_ITER_VALUE)),
|
||||
#ifdef JS_METHODJIT
|
||||
methodJitEnabled(false),
|
||||
|
@ -1220,6 +1220,16 @@ struct JSRuntime : js::RuntimeFriendFields
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
/*
|
||||
* Used to ensure that compartments created at the same time get different
|
||||
* random number sequences. See js::InitRandom.
|
||||
*/
|
||||
uint64_t rngNonce;
|
||||
|
||||
public:
|
||||
uint64_t nextRNGNonce() { return rngNonce++; }
|
||||
};
|
||||
|
||||
/* Common macros to access thread-local caches in JSRuntime. */
|
||||
@ -1583,9 +1593,6 @@ struct JSContext : js::ContextFriendFields,
|
||||
/* Stored here to avoid passing it around as a parameter. */
|
||||
unsigned resolveFlags;
|
||||
|
||||
/* Random number generator state, used by jsmath.cpp. */
|
||||
int64_t rngSeed;
|
||||
|
||||
/* Location to stash the iteration value between JSOP_MOREITER and JSOP_ITERNEXT. */
|
||||
js::Value iterValue;
|
||||
|
||||
|
@ -80,6 +80,7 @@ JSCompartment::JSCompartment(JSRuntime *rt)
|
||||
gcGrayRoots(),
|
||||
gcMallocBytes(0),
|
||||
debugModeBits(rt->debugMode ? DebugFromC : 0),
|
||||
rngState(0),
|
||||
watchpointMap(NULL),
|
||||
scriptCountsMap(NULL),
|
||||
debugScriptMap(NULL),
|
||||
@ -128,6 +129,9 @@ JSCompartment::init(JSContext *cx)
|
||||
if (!regExps.init(cx))
|
||||
return false;
|
||||
|
||||
if (cx)
|
||||
InitRandom(cx->runtime, &rngState);
|
||||
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
/*
|
||||
* If we are in the middle of post-barrier verification, we need to
|
||||
|
@ -470,6 +470,9 @@ struct JSCompartment : private JS::shadow::Compartment, public js::gc::GraphNode
|
||||
|
||||
js::DtoaCache dtoaCache;
|
||||
|
||||
/* Random number generator state, used by jsmath.cpp. */
|
||||
uint64_t rngState;
|
||||
|
||||
private:
|
||||
/*
|
||||
* Weak reference to each global in this compartment that is a debuggee.
|
||||
|
@ -517,47 +517,48 @@ js_math_pow(JSContext *cx, unsigned argc, Value *vp)
|
||||
# pragma optimize("", on)
|
||||
#endif
|
||||
|
||||
static const int64_t RNG_MULTIPLIER = 0x5DEECE66DLL;
|
||||
static const int64_t RNG_ADDEND = 0xBLL;
|
||||
static const int64_t RNG_MASK = (1LL << 48) - 1;
|
||||
static const uint64_t RNG_MULTIPLIER = 0x5DEECE66DLL;
|
||||
static const uint64_t RNG_ADDEND = 0xBLL;
|
||||
static const uint64_t RNG_MASK = (1LL << 48) - 1;
|
||||
static const double RNG_DSCALE = double(1LL << 53);
|
||||
|
||||
/*
|
||||
* Math.random() support, lifted from java.util.Random.java.
|
||||
*/
|
||||
extern void
|
||||
random_setSeed(int64_t *rngSeed, int64_t seed)
|
||||
random_setSeed(uint64_t *rngState, uint64_t seed)
|
||||
{
|
||||
*rngSeed = (seed ^ RNG_MULTIPLIER) & RNG_MASK;
|
||||
*rngState = (seed ^ RNG_MULTIPLIER) & RNG_MASK;
|
||||
}
|
||||
|
||||
void
|
||||
js_InitRandom(JSContext *cx)
|
||||
js::InitRandom(JSRuntime *rt, uint64_t *rngState)
|
||||
{
|
||||
/*
|
||||
* Set the seed from current time. Since we have a RNG per context and we often bring
|
||||
* up several contexts at the same time, we xor in some additional values, namely
|
||||
* the context and its successor. We don't just use the context because it might be
|
||||
* possible to reverse engineer the context pointer if one guesses the time right.
|
||||
* Set the seed from current time. Since we have a RNG per compartment and
|
||||
* we often bring up several compartments at the same time, mix in a
|
||||
* different integer each time. This is only meant to prevent all the new
|
||||
* compartments from getting the same sequence of pseudo-random
|
||||
* numbers. There's no security guarantee.
|
||||
*/
|
||||
random_setSeed(&cx->rngSeed, (PRMJ_Now() / 1000) ^ int64_t(cx) ^ int64_t(cx->getNext()));
|
||||
random_setSeed(rngState, (uint64_t(PRMJ_Now()) << 8) ^ rt->nextRNGNonce());
|
||||
}
|
||||
|
||||
extern uint64_t
|
||||
random_next(int64_t *rngSeed, int bits)
|
||||
random_next(uint64_t *rngState, int bits)
|
||||
{
|
||||
uint64_t nextseed = *rngSeed * RNG_MULTIPLIER;
|
||||
nextseed += RNG_ADDEND;
|
||||
nextseed &= RNG_MASK;
|
||||
*rngSeed = nextseed;
|
||||
return nextseed >> (48 - bits);
|
||||
uint64_t nextstate = *rngState * RNG_MULTIPLIER;
|
||||
nextstate += RNG_ADDEND;
|
||||
nextstate &= RNG_MASK;
|
||||
*rngState = nextstate;
|
||||
return nextstate >> (48 - bits);
|
||||
}
|
||||
|
||||
static inline double
|
||||
random_nextDouble(JSContext *cx)
|
||||
{
|
||||
return double((random_next(&cx->rngSeed, 26) << 27) + random_next(&cx->rngSeed, 27)) /
|
||||
RNG_DSCALE;
|
||||
uint64_t *rng = &cx->compartment->rngState;
|
||||
return double((random_next(rng, 26) << 27) + random_next(rng, 27)) / RNG_DSCALE;
|
||||
}
|
||||
|
||||
double
|
||||
|
@ -45,6 +45,9 @@ class MathCache
|
||||
size_t sizeOfIncludingThis(JSMallocSizeOfFun mallocSizeOf);
|
||||
};
|
||||
|
||||
extern void
|
||||
InitRandom(JSRuntime *rt, uint64_t *rngState);
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
/*
|
||||
@ -54,9 +57,6 @@ class MathCache
|
||||
extern JSObject *
|
||||
js_InitMathClass(JSContext *cx, js::HandleObject obj);
|
||||
|
||||
extern void
|
||||
js_InitRandom(JSContext *cx);
|
||||
|
||||
extern double
|
||||
math_random_no_outparam(JSContext *cx);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user