(perl #127663) create a separate random source for internal use
authorTony Cook <tony@develop-help.com>
Wed, 18 May 2016 05:03:14 +0000 (15:03 +1000)
committerTony Cook <tony@develop-help.com>
Mon, 11 Sep 2017 00:59:42 +0000 (10:59 +1000)
and use it to initialize hash randomization and to innoculate against
quadratic behaviour in pp_sort

embedvar.h
intrpvar.h
perl.c
pp_sort.c
util.c
util.h

index 8b9842f..76efb91 100644 (file)
 #define PL_incgv               (vTHX->Iincgv)
 #define PL_initav              (vTHX->Iinitav)
 #define PL_inplace             (vTHX->Iinplace)
+#define PL_internal_random_state       (vTHX->Iinternal_random_state)
 #define PL_isarev              (vTHX->Iisarev)
 #define PL_known_layers                (vTHX->Iknown_layers)
 #define PL_langinfo_buf                (vTHX->Ilanginfo_buf)
index b6b20bc..766e552 100644 (file)
@@ -830,6 +830,14 @@ PERLVAR(I, random_state, PL_RANDOM_STATE_TYPE)
 
 PERLVARI(I, dump_re_max_len, STRLEN, 0)
 
+/* For internal uses of randomness, this ensures the sequence of
+ * random numbers returned by rand() isn't modified by perl's internal
+ * use of randomness.
+ * This is important if the user has called srand() with a seed.
+ */
+
+PERLVAR(I, internal_random_state, PL_RANDOM_STATE_TYPE)
+
 /* If you are adding a U8 or U16, check to see if there are 'Space' comments
  * above on where there are gaps which currently will be structure padding.  */
 
diff --git a/perl.c b/perl.c
index a3f8ac3..8046013 100644 (file)
--- a/perl.c
+++ b/perl.c
@@ -261,6 +261,8 @@ perl_construct(pTHXx)
 
     init_constants();
 
+    Perl_drand48_init_r(&PL_internal_random_state, seed());
+
     SvREADONLY_on(&PL_sv_placeholder);
     SvREFCNT(&PL_sv_placeholder) = SvREFCNT_IMMORTAL;
 
index 5f39dba..6049509 100644 (file)
--- a/pp_sort.c
+++ b/pp_sort.c
@@ -788,7 +788,7 @@ S_qsortsvu(pTHX_ SV ** array, size_t num_elts, SVCOMPARE_t compare)
       size_t n;
       SV ** const q = array;
       for (n = num_elts; n > 1; ) {
-         const size_t j = (size_t)(n-- * Drand01());
+         const size_t j = (size_t)(n-- * Perl_internal_drand48());
          temp = q[j];
          q[j] = q[n];
          q[n] = temp;
diff --git a/util.c b/util.c
index b470681..136e4ca 100644 (file)
--- a/util.c
+++ b/util.c
@@ -4677,10 +4677,8 @@ Perl_get_hash_seed(pTHX_ unsigned char * const seed_buffer)
     else
 #endif /* NO_PERL_HASH_ENV */
     {
-        (void)seedDrand01((Rand_seed_t)seed());
-
         for( i = 0; i < PERL_HASH_SEED_BYTES; i++ ) {
-            seed_buffer[i] = (unsigned char)(Drand01() * (U8_MAX+1));
+            seed_buffer[i] = (unsigned char)(Perl_internal_drand48() * (U8_MAX+1));
         }
     }
 #ifdef USE_PERL_PERTURB_KEYS
diff --git a/util.h b/util.h
index 12a1c47..4589808 100644 (file)
--- a/util.h
+++ b/util.h
@@ -89,6 +89,12 @@ typedef struct PERL_DRAND48_T perl_drand48_t;
 #define Perl_drand48_init(seed) (Perl_drand48_init_r(&PL_random_state, (seed)))
 #define Perl_drand48() (Perl_drand48_r(&PL_random_state))
 
+#ifdef PERL_CORE
+/* uses a different source of randomness to avoid interfering with the results
+ * of rand() */
+#define Perl_internal_drand48() (Perl_drand48_r(&PL_internal_random_state))
+#endif
+
 #ifdef USE_C_BACKTRACE
 
 typedef struct {