[SERVER-24437] Use a platform-independent PRNG in the mongo shell for Random.rand() Created: 07/Jun/16  Updated: 26/Aug/19  Resolved: 20/Aug/19

Status: Closed
Project: Core Server
Component/s: Shell
Affects Version/s: None
Fix Version/s: 4.3.1

Type: Improvement Priority: Major - P3
Reporter: Max Hirschhorn Assignee: Jason Chan
Resolution: Done Votes: 0
Labels: neweng, platforms-re-triaged
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Problem/Incident
Backwards Compatibility: Fully Compatible
Sprint: Repl 2019-08-26
Participants:
Linked BF Score: 0

 Description   

The Math.random() function in JavaScript isn't seeded, so the mongo shell provides a Random.rand() function that can be seeded using the Random.srand() function. The C++ function that underlies Random.rand() uses the rand_r() function on POSIX systems and the rand() function on Windows. The RAND_MAX value used to scale the results to be a floating-point number between 0 and 1 is platform-specific. This means that even for the same seed, the pseudo-random number generator will produce different sequences on Windows, Linux, and OS X.

The Random.setRandomSeed() function seeds the pseudo-random number generator with a value generated by a SecureRandom instance. Some of our more complex JavaScript integration tests use a pseudo-random number generator to vary the test data and/or operations to make the test case more interesting each time. Having the pseudo-random number generator in the mongo shell be platform-independent would greatly aid in reproducing the exact test setup without requiring using the same platform as what the test failure occurred on.

#if !defined(_WIN32)
ThreadLocalValue<unsigned int> _randomSeed;
#endif
 
BSONObj JSSrand(const BSONObj& a, void* data) {
    unsigned int seed;
    // grab the least significant bits of either the supplied argument or
    // a random number from SecureRandom.
    if (a.nFields() == 1 && a.firstElement().isNumber())
        seed = static_cast<unsigned int>(a.firstElement().numberLong());
    else {
        std::unique_ptr<SecureRandom> rand(SecureRandom::create());
        seed = static_cast<unsigned int>(rand->nextInt64());
    }
#if !defined(_WIN32)
    _randomSeed.set(seed);
#else
    srand(seed);
#endif
    return BSON("" << static_cast<double>(seed));
}
 
BSONObj JSRand(const BSONObj& a, void* data) {
    uassert(12519, "rand accepts no arguments", a.nFields() == 0);
    unsigned r;
#if !defined(_WIN32)
    r = rand_r(&_randomSeed.getRef());
#else
    r = rand();
#endif
    return BSON("" << double(r) / (double(RAND_MAX) + 1));
}



 Comments   
Comment by Githook User [ 20/Aug/19 ]

Author:

{'username': 'jasonjhchan', 'email': 'jason.chan@mongodb.com', 'name': 'Jason Chan'}

Message: SERVER-24437 Use a platform-independent PRNG in the mongo shell for Random.rand()
Branch: master
https://github.com/mongodb/mongo/commit/34c846207cd732e90524487ce0d050d834abc9f7

Comment by Jason Chan [ 12/Aug/19 ]

PseudoRandom might do the trick here.

Generated at Thu Feb 08 04:06:21 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.