<p dir="ltr">What problem are you trying to fix and do you really need to fix it?</p>
<p dir="ltr">-- kcc (sent from phone)</p>
<div class="gmail_extra"><br><div class="gmail_quote">On Jun 10, 2016 1:22 AM, "Dan Liew" <<a href="mailto:dan@su-root.co.uk">dan@su-root.co.uk</a>> wrote:<br type="attribution"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">delcypher created this revision.<br>
delcypher added reviewers: kcc, aizatsky.<br>
delcypher added subscribers: kcc, aizatsky, zaks.anna, kubabrecka, dcoughlin, llvm-commits.<br>
<br>
[LibFuzzer] Avoid using std::random_swap() due to platform differences<br>
and implement our own version.<br>
<br>
It turns out that the behavior of std::random_swap is different between<br>
libstdc++ and libcxx (even with the same random number source).<br>
Therefore if we want consistent behavior between platforms we have to<br>
use our own implementation.<br>
<br>
This change (plus a change to the number of iterations of the Mutator in<br>
the test required for the particular shuffle implementation used) fixes<br>
the ``FuzzerMutate.ShuffleBytes2`` unit test on OSX.<br>
<br>
I have verified that for the above unittest identical mutations are<br>
now generated on both Linux and on OSX.<br>
<br>
<br>
<a href="http://reviews.llvm.org/D21218" rel="noreferrer" target="_blank">http://reviews.llvm.org/D21218</a><br>
<br>
Files:<br>
  lib/Fuzzer/FuzzerInternal.h<br>
  lib/Fuzzer/FuzzerLoop.cpp<br>
  lib/Fuzzer/FuzzerMutate.cpp<br>
  lib/Fuzzer/test/FuzzerUnittest.cpp<br>
<br>
Index: lib/Fuzzer/test/FuzzerUnittest.cpp<br>
===================================================================<br>
--- lib/Fuzzer/test/FuzzerUnittest.cpp<br>
+++ lib/Fuzzer/test/FuzzerUnittest.cpp<br>
@@ -259,7 +259,7 @@<br>
   TestShuffleBytes(&MutationDispatcher::Mutate_ShuffleBytes, 1 << 16);<br>
 }<br>
 TEST(FuzzerMutate, ShuffleBytes2) {<br>
-  TestShuffleBytes(&MutationDispatcher::Mutate, 1 << 19);<br>
+  TestShuffleBytes(&MutationDispatcher::Mutate, 566171);<br>
 }<br>
<br>
 void TestAddWordFromDictionary(Mutator M, int NumIter) {<br>
Index: lib/Fuzzer/FuzzerMutate.cpp<br>
===================================================================<br>
--- lib/Fuzzer/FuzzerMutate.cpp<br>
+++ lib/Fuzzer/FuzzerMutate.cpp<br>
@@ -96,8 +96,7 @@<br>
       Rand(std::min(Size, (size_t)8)) + 1; // [1,8] and <= Size.<br>
   size_t ShuffleStart = Rand(Size - ShuffleAmount);<br>
   assert(ShuffleStart + ShuffleAmount <= Size);<br>
-  std::random_shuffle(Data + ShuffleStart, Data + ShuffleStart + ShuffleAmount,<br>
-                      Rand);<br>
+  Rand.Shuffle(Data + ShuffleStart, Data + ShuffleStart + ShuffleAmount);<br>
   return Size;<br>
 }<br>
<br>
Index: lib/Fuzzer/FuzzerLoop.cpp<br>
===================================================================<br>
--- lib/Fuzzer/FuzzerLoop.cpp<br>
+++ lib/Fuzzer/FuzzerLoop.cpp<br>
@@ -321,7 +321,7 @@<br>
 }<br>
<br>
 void Fuzzer::ShuffleCorpus(UnitVector *V) {<br>
-  std::random_shuffle(V->begin(), V->end(), MD.GetRand());<br>
+  MD.GetRand().Shuffle(V->begin(), V->end());<br>
   if (Options.PreferSmall)<br>
     std::stable_sort(V->begin(), V->end(), [](const Unit &A, const Unit &B) {<br>
       return A.size() < B.size();<br>
Index: lib/Fuzzer/FuzzerInternal.h<br>
===================================================================<br>
--- lib/Fuzzer/FuzzerInternal.h<br>
+++ lib/Fuzzer/FuzzerInternal.h<br>
@@ -137,6 +137,22 @@<br>
   size_t RandBool() { return Rand() % 2; }<br>
   size_t operator()(size_t n) { return n ? Rand() % n : 0; }<br>
   std::mt19937 &Get_mt19937() { return R; }<br>
+  // Shuffle data in the range [First, End)<br>
+  //<br>
+  // We do not use std::random_shuffle() here because its<br>
+  // behavior is not consistent across different platforms.<br>
+  //<br>
+  // The algorithm used here will pick a permutation at<br>
+  // random where every permutation has equal probability<br>
+  // (provided the random source is uniformly distributed).<br>
+  template<typename RndAccessIt><br>
+  void Shuffle(RndAccessIt First, RndAccessIt End) {<br>
+    typename std::iterator_traits<RndAccessIt>::difference_type Offset, N;<br>
+    N = End - First;<br>
+    for (Offset = 0; Offset < N; ++Offset) {<br>
+      std::swap(First[Offset], First[Offset + (*this)(N - Offset)]);<br>
+    }<br>
+  }<br>
  private:<br>
   std::mt19937 R;<br>
 };<br>
<br>
<br>
</blockquote></div></div>