CertC++-MSC50¶
Do not use std::rand() for generating pseudorandom numbers
Required inputs: IR
Pseudorandom number generators use mathematical algorithms to produce a sequence of numbers with good statistical properties, but the numbers produced are not genuinely random.
The C Standard
rand() function, exposed through the C++ standard library
through
<cstdlib> as
std::rand(), makes no guarantees as to the quality of the random
sequence produced. The numbers generated by some implementations of
std::rand() have a comparatively short cycle, and the numbers
can be predictable. Applications that have strong pseudorandom number
requirements must use a generator that is known to be sufficient for their
needs.
Noncompliant Code Example
The following noncompliant code generates an ID with a numeric part produced by
calling the
rand() function. The IDs produced are predictable and have limited
randomness. Further, depending on the value of
RAND_MAX, the resulting value can have modulo bias.
#include <cstdlib>
#include <string>
void f() {
std::string id("ID"); // Holds the ID, starting with the characters "ID" followed
// by a random integer in the range [0-10000].
id += std::to_string(std::rand() % 10000);
// ...
}
Compliant Solution
The C++ standard library provides mechanisms for fine-grained control over pseudorandom number generation. It breaks random number generation into two parts: one is the algorithm responsible for providing random values (the engine), and the other is responsible for distribution of the random values via a density function (the distribution). The distribution object is not strictly required, but it works to ensure that values are properly distributed within a given range instead of improperly distributed due to bias issues. This compliant solution uses the Mersenne Twister algorithm as the engine for generating random values and a uniform distribution to negate the modulo bias from the noncompliant code example.
#include <random>
#include <string>
void f() {
std::string id("ID"); // Holds the ID, starting with the characters "ID" followed
// by a random integer in the range [0-10000].
std::uniform_int_distribution<int> distribution(0, 10000);
std::random_device rd;
std::mt19937 engine(rd());
id += std::to_string(distribution(engine));
// ...
}
This compliant solution also seeds the random number engine, in conformance with MSC51-CPP. Ensure your random number generator is properly seeded.
Risk Assessment
Using the
std::rand() function could lead to predictable random numbers.
| Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
|---|---|---|---|---|---|
| MSC50-CPP | Medium | Unlikely | Low | P6 | L2 |
Related Guidelines
| SEI CERT C++ Coding Standard | MSC51-CPP. Ensure your random number generator is properly seeded |
| SEI CERT C Coding Standard | MSC30-C. Do not use the rand() function for generating pseudorandom numbers |
| CERT Oracle Secure Coding Standard for Java | MSC02-J. Generate strong random numbers |
| MITRE CWE |
CWE-327, Use of a Broken or Risky Cryptographic
Algorithm CWE-330, Use of Insufficiently Random Values |
Bibliography
| [ ISO/IEC 9899:2011] | Subclause 7.22.2, "Pseudo-random Sequence Generation Functions" |
| [ ISO/IEC 14882-2014] | Subclause 26.5, "Random Number Generation" |
Possible Messages
Key |
Text |
Severity |
Disabled |
|---|---|---|---|
forbidden_libfunc_call |
Call to forbidden function. |
None |
False |
Options¶
This rule shares the following common options: exclude_in_macros, exclude_messages_in_system_headers, excludes, extend_exclude_to_macro_invocations, includes, justification_checker, languages, post_processing, provider, report_at, severity
The following places define options that affect this rule: Stylechecks, Analysis-GlobalOptions
blacklist¶
blacklist
Dictionary of header globbing to (list of) function name globbing(s) of forbidden functions.Type: dict[bauhaus.analysis.config.FileGlobPattern, list[bauhaus.analysis.config.GlobPattern]]
Default:
{ '*stdlib.h': ['rand'] }