[PATCH] D44143: Create properly seeded random generator check

Aaron Ballman via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Tue Mar 6 05:52:36 PST 2018


aaron.ballman added a comment.

Thank you for working on this check!

Do you think it might be possible to also add a check for `cert-msc32-c` that handles the C side of things, and use a common check to implement both? C won't ever have the C++'isms, but C++ can certainly abuse `std::srand()` so it seems like there's at least some overlap.



================
Comment at: clang-tidy/cert/CERTTidyModule.cpp:43
+    CheckFactories.registerCheck<ProperlySeededRandomGeneratorCheck>(
+        "cert-properly-seeded-random-generator");
     CheckFactories.registerCheck<VariadicFunctionDefCheck>("cert-dcl50-cpp");
----------------
The name should be `cert-msc51-cpp` (and categorized with the other msc checks).


================
Comment at: clang-tidy/cert/ProperlySeededRandomGeneratorCheck.cpp:22-24
+      hasAnyName("linear_congruential_engine", "mersenne_twister_engine",
+                 "subtract_with_carry_engine", "discard_block_engine",
+                 "independent_bits_engine", "shuffle_order_engine"));
----------------
These should be using fully-qualified names, like `::std::mersenne_twister_engine`. Also, I think this list should be configurable so that users can add their own engines if needed.


================
Comment at: clang-tidy/cert/ProperlySeededRandomGeneratorCheck.cpp:66
+
+  template<class T>
+void ProperlySeededRandomGeneratorCheck::checkSeed(
----------------
Formatting looks off here.


================
Comment at: clang-tidy/cert/ProperlySeededRandomGeneratorCheck.cpp:71
+    diag(Func->getExprLoc(), "random number generator must be seeded with "
+                             "a random_device instead of default argument");
+    return;
----------------
The diagnostics here aren't quite correct -- a `random_device` isn't *required*. For instance, it's also fine to open up /dev/random and read a seed's worth of bytes. I think a better phrasing might be: `random number generator seeded with a default argument will generate a predictable sequence of values`.


================
Comment at: clang-tidy/cert/ProperlySeededRandomGeneratorCheck.cpp:77-78
+  if (Func->getArg(0)->EvaluateAsInt(Value, *Result.Context)) {
+    diag(Func->getExprLoc(), "random number generator must be seeded with "
+                             "a random_device instead of a constant");
+    return;
----------------
I'd probably use similar wording here: `random number generator seeded with a constant value will generate a predictable sequence of values`.

You can combine these diagnostics and use %select{}0 to choose between the variants.


================
Comment at: clang-tidy/cert/ProperlySeededRandomGeneratorCheck.h:33-34
+  template<class T>
+  void checkSeed(const ast_matchers::MatchFinder::MatchResult &Result,
+                 const T *Func);
+};
----------------
It seems like this should be a private function rather than public.


================
Comment at: docs/clang-tidy/checks/cert-properly-seeded-random-generator.rst:3
+
+cert-properly-seeded-random-generator
+=====================================
----------------
When renaming the check, be sure to update titles, file names, etc.


================
Comment at: docs/clang-tidy/checks/cert-properly-seeded-random-generator.rst:7
+This check flags all pseudo-random number engines and engine adaptors
+instantiations when it initialized or seeded with default argument or constant
+expression. Pseudo-random number engines seeded with a predictable value may
----------------
Remove "it".


================
Comment at: docs/clang-tidy/checks/cert-properly-seeded-random-generator.rst:22-23
+    
+    std::time_t t;
+    engine1.seed(std::time(&t)); // Bad, system time might be controlled by user
+
----------------
There's no test case for this test, and I don't think this code would generate a diagnostic in the current check form. This might require a (user-configurable) list of disallowed sources of seed values. For instance, it should diagnose when called with a `time_t` value or a direct call to a time function, but it need not diagnose if the value is somehow obscured. e.g.,
```
unsigned get_seed() { std::time_t t; return std::time(&t); }
engine1.seed(get_seed()); // No diagnostic required
```


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D44143





More information about the cfe-commits mailing list