summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embed.fnc1
-rw-r--r--embed.h6
-rw-r--r--embedvar.h2
-rw-r--r--intrpvar.h2
-rw-r--r--perl.c35
-rw-r--r--perl.h2
-rw-r--r--perlapi.h2
-rw-r--r--pod/perlrun.pod4
-rw-r--r--proto.h1
-rw-r--r--util.c32
10 files changed, 60 insertions, 27 deletions
diff --git a/embed.fnc b/embed.fnc
index 19da53f0a6..c138f76ba3 100644
--- a/embed.fnc
+++ b/embed.fnc
@@ -839,6 +839,7 @@ p |void |vivify_ref |SV* sv|U32 to_what
p |I32 |wait4pid |Pid_t pid|int* statusp|int flags
p |U32 |parse_unicode_opts|char **popt
p |U32 |seed
+p |UV |get_seed
p |void |report_evil_fh |GV *gv|IO *io|I32 op
pd |void |report_uninit
Afpd |void |warn |const char* pat|...
diff --git a/embed.h b/embed.h
index 2ba996baa7..add142d317 100644
--- a/embed.h
+++ b/embed.h
@@ -1115,6 +1115,9 @@
#define seed Perl_seed
#endif
#ifdef PERL_CORE
+#define get_seed Perl_get_seed
+#endif
+#ifdef PERL_CORE
#define report_evil_fh Perl_report_evil_fh
#endif
#ifdef PERL_CORE
@@ -3603,6 +3606,9 @@
#define seed() Perl_seed(aTHX)
#endif
#ifdef PERL_CORE
+#define get_seed() Perl_get_seed(aTHX)
+#endif
+#ifdef PERL_CORE
#define report_evil_fh(a,b,c) Perl_report_evil_fh(aTHX_ a,b,c)
#endif
#ifdef PERL_CORE
diff --git a/embedvar.h b/embedvar.h
index f990f9f7c5..98d8b21665 100644
--- a/embedvar.h
+++ b/embedvar.h
@@ -255,6 +255,7 @@
#define PL_glob_index (vTHX->Iglob_index)
#define PL_globalstash (vTHX->Iglobalstash)
#define PL_hash_seed (vTHX->Ihash_seed)
+#define PL_hash_seed_set (vTHX->Ihash_seed_set)
#define PL_he_arenaroot (vTHX->Ihe_arenaroot)
#define PL_he_root (vTHX->Ihe_root)
#define PL_hintgv (vTHX->Ihintgv)
@@ -558,6 +559,7 @@
#define PL_Iglob_index PL_glob_index
#define PL_Iglobalstash PL_globalstash
#define PL_Ihash_seed PL_hash_seed
+#define PL_Ihash_seed_set PL_hash_seed_set
#define PL_Ihe_arenaroot PL_he_arenaroot
#define PL_Ihe_root PL_he_root
#define PL_Ihintgv PL_hintgv
diff --git a/intrpvar.h b/intrpvar.h
index 6d77cec2a1..6a34ea4e67 100644
--- a/intrpvar.h
+++ b/intrpvar.h
@@ -525,6 +525,8 @@ PERLVARI(Ippid, IV, 0)
PERLVARI(Ihash_seed, UV, 0) /* Hash initializer */
+PERLVARI(Ihash_seed_set, bool, FALSE) /* Hash initialized? */
+
PERLVAR(IDBassertion, SV *)
PERLVARI(Icv_has_eval, I32, 0) /* PL_compcv includes an entereval or similar */
diff --git a/perl.c b/perl.c
index 173848926f..32e046989c 100644
--- a/perl.c
+++ b/perl.c
@@ -900,31 +900,18 @@ setuid perl scripts securely.\n");
#if defined(USE_HASH_SEED) || defined(USE_HASH_SEED_EXPLICIT)
/* [perl #22371] Algorimic Complexity Attack on Perl 5.6.1, 5.8.0
* This MUST be done before any hash stores or fetches take place. */
+ if (!PL_hash_seed_set)
+ PL_hash_seed = get_seed();
{
- char *s = PerlEnv_getenv("PERL_HASH_SEED");
- if (s)
- while (isSPACE(*s)) s++;
- if (s && isDIGIT(*s))
- PL_hash_seed = (UV)Atoul(s);
-#ifndef USE_HASH_SEED_EXPLICIT
- else {
- /* Compute a random seed */
- (void)seedDrand01((Rand_seed_t)seed());
- PL_srand_called = TRUE;
- PL_hash_seed = (UV)(Drand01() * (NV)UV_MAX);
-#if RANDBITS < (UVSIZE * 8)
- /* Since there are not enough randbits to to reach all
- * the bits of a UV, the low bits might need extra
- * help. Sum in another random number that will
- * fill in the low bits. */
- PL_hash_seed +=
- (UV)(Drand01() * (NV)((1 << ((UVSIZE * 8 - RANDBITS))) - 1));
-#endif /* RANDBITS < (UVSIZE * 8) */
- }
-#endif /* #ifndef USE_HASH_SEED_EXPLICIT */
- if ((s = PerlEnv_getenv("PERL_HASH_SEED_DEBUG")))
- PerlIO_printf(Perl_debug_log, "HASH_SEED = %"UVuf"\n",
- PL_hash_seed);
+ char *s = PerlEnv_getenv("PERL_HASH_SEED_DEBUG");
+
+ if (s) {
+ int i = atoi(s);
+
+ if (i == 1)
+ PerlIO_printf(Perl_debug_log, "HASH_SEED = %"UVuf"\n",
+ PL_hash_seed);
+ }
}
#endif /* #if defined(USE_HASH_SEED) || defined(USE_HASH_SEED_EXPLICIT) */
diff --git a/perl.h b/perl.h
index cb43a3d6f1..24742c454d 100644
--- a/perl.h
+++ b/perl.h
@@ -2258,7 +2258,7 @@ typedef struct crypt_data { /* straight from /usr/include/crypt.h */
/* [perl #22371] Algorimic Complexity Attack on Perl 5.6.1, 5.8.0 */
#if !defined(NO_HASH_SEED) && !defined(USE_HASH_SEED) && !defined(USE_HASH_SEED_EXPLICIT)
-# define USE_HASH_SEED
+# define USE_HASH_SEED_EXPLICIT
#endif
#include "regexp.h"
diff --git a/perlapi.h b/perlapi.h
index 123a7d5126..524e84b1c7 100644
--- a/perlapi.h
+++ b/perlapi.h
@@ -268,6 +268,8 @@ END_EXTERN_C
#define PL_globalstash (*Perl_Iglobalstash_ptr(aTHX))
#undef PL_hash_seed
#define PL_hash_seed (*Perl_Ihash_seed_ptr(aTHX))
+#undef PL_hash_seed_set
+#define PL_hash_seed_set (*Perl_Ihash_seed_set_ptr(aTHX))
#undef PL_he_arenaroot
#define PL_he_arenaroot (*Perl_Ihe_arenaroot_ptr(aTHX))
#undef PL_he_root
diff --git a/pod/perlrun.pod b/pod/perlrun.pod
index 26d0bc424a..730c75da1e 100644
--- a/pod/perlrun.pod
+++ b/pod/perlrun.pod
@@ -1127,8 +1127,8 @@ See L<perlsec/"Algorithmic Complexity Attacks"> for more information.
=item PERL_HASH_SEED_DEBUG
-(Since Perl 5.8.1.) Set to (anything) to display (to STDERR)
-the value of the hash seed at the beginning of execution.
+(Since Perl 5.8.1.) Set to "1" to display (to STDERR) the value of
+the hash seed at the beginning of execution.
=item PERL_ROOT (specific to the VMS port)
diff --git a/proto.h b/proto.h
index bb91615627..57f7027800 100644
--- a/proto.h
+++ b/proto.h
@@ -799,6 +799,7 @@ PERL_CALLCONV void Perl_vivify_ref(pTHX_ SV* sv, U32 to_what);
PERL_CALLCONV I32 Perl_wait4pid(pTHX_ Pid_t pid, int* statusp, int flags);
PERL_CALLCONV U32 Perl_parse_unicode_opts(pTHX_ char **popt);
PERL_CALLCONV U32 Perl_seed(pTHX);
+PERL_CALLCONV UV Perl_get_seed(pTHX);
PERL_CALLCONV void Perl_report_evil_fh(pTHX_ GV *gv, IO *io, I32 op);
PERL_CALLCONV void Perl_report_uninit(pTHX);
PERL_CALLCONV void Perl_warn(pTHX_ const char* pat, ...)
diff --git a/util.c b/util.c
index 80af15519f..4f53a91417 100644
--- a/util.c
+++ b/util.c
@@ -4377,3 +4377,35 @@ Perl_seed(pTHX)
return u;
}
+UV
+Perl_get_seed(void)
+{
+ char *s = PerlEnv_getenv("PERL_HASH_SEED");
+ UV myseed = 0;
+
+ if (s)
+ while (isSPACE(*s)) s++;
+ if (s && isDIGIT(*s))
+ myseed = (UV)Atoul(s);
+ else
+#ifdef USE_HASH_SEED_EXPLICIT
+ if (s)
+#endif
+ {
+ /* Compute a random seed */
+ (void)seedDrand01((Rand_seed_t)seed());
+ PL_srand_called = TRUE;
+ myseed = (UV)(Drand01() * (NV)UV_MAX);
+#if RANDBITS < (UVSIZE * 8)
+ /* Since there are not enough randbits to to reach all
+ * the bits of a UV, the low bits might need extra
+ * help. Sum in another random number that will
+ * fill in the low bits. */
+ myseed +=
+ (UV)(Drand01() * (NV)((1 << ((UVSIZE * 8 - RANDBITS))) - 1));
+#endif /* RANDBITS < (UVSIZE * 8) */
+ }
+ PL_hash_seed_set = TRUE;
+
+ return myseed;
+}