Created
February 26, 2025 21:51
-
-
Save bulk88/6ad8066b5677e9ffe276d4a968f67a91 to your computer and use it in GitHub Desktop.
hv hasher fn prototype fix.diff
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
embed.fnc | 5 ++ | |
embed.h | 2 + | |
hv_func.h | 32 +++++++++---- | |
perl_siphash.h | 138 +++++++++++++++++++++++++++++++++++++++----------------- | |
perlstatic.h | 31 +++++++++++-- | |
proto.h | 11 +++++ | |
sbox32_hash.h | 16 ++++--- | |
util.c | 22 ++++++++- | |
zaphod32_hash.h | 53 ++++++++++++++++++++-- | |
9 files changed, 244 insertions(+), 66 deletions(-) | |
diff --git a/embed.fnc b/embed.fnc | |
index b5b0b42b89..f025f49f1f 100644 | |
--- a/embed.fnc | |
+++ b/embed.fnc | |
@@ -1009,6 +1009,7 @@ ETXdp |char * |delimcpy_no_escape \ | |
Cp |void |despatch_signals | |
Adfprv |OP * |die |NULLOK const char *pat \ | |
|... | |
+TXpr |void |die_hashlen | |
Adpr |OP * |die_sv |NN SV *baseex | |
: Used in util.c | |
pr |void |die_unwind |NN SV *msv | |
@@ -1478,6 +1479,10 @@ Adp |HV * |gv_stashsv |NN SV *sv \ | |
|I32 flags | |
Xdpx |void |gv_try_downgrade \ | |
|NN GV *gv | |
+: in util.c, used by PERL_HASH_WITH_SEED() | |
+RTXp |U32 |hash_with_seed |NN const U8 *seed \ | |
+ |NN const U8 *str \ | |
+ |STRLEN len | |
op |struct xpvhv_aux *|hv_auxalloc \ | |
|NN HV *hv | |
: Used in dump.c and hv.c | |
diff --git a/embed.h b/embed.h | |
index e7942159f1..4a1f8d082a 100644 | |
--- a/embed.h | |
+++ b/embed.h | |
@@ -1033,6 +1033,7 @@ | |
# define debug_hash_seed(a) Perl_debug_hash_seed(aTHX_ a) | |
# define defelem_target(a,b) Perl_defelem_target(aTHX_ a,b) | |
# define delete_eval_scope() Perl_delete_eval_scope(aTHX) | |
+# define die_hashlen Perl_die_hashlen | |
# define die_unwind(a) Perl_die_unwind(aTHX_ a) | |
# define do_aexec(a,b,c) Perl_do_aexec(aTHX,a,b,c) | |
# define do_aexec5(a,b,c,d,e) Perl_do_aexec5(aTHX_ a,b,c,d,e) | |
@@ -1066,6 +1067,7 @@ | |
# define gv_setref(a,b) Perl_gv_setref(aTHX_ a,b) | |
# define gv_stashpvs_p(a,b) Perl_gv_stashpvs_p(aTHX_ a,b) | |
# define gv_try_downgrade(a) Perl_gv_try_downgrade(aTHX_ a) | |
+# define hash_with_seed Perl_hash_with_seed | |
# define hv_ename_add(a,b,c,d) Perl_hv_ename_add(aTHX_ a,b,c,d) | |
# define hv_ename_delete(a,b,c,d) Perl_hv_ename_delete(aTHX_ a,b,c,d) | |
# define hv_pushkv(a,b) Perl_hv_pushkv(aTHX_ a,b) | |
diff --git a/hv_func.h b/hv_func.h | |
index 700bab2fc0..926d1196f8 100644 | |
--- a/hv_func.h | |
+++ b/hv_func.h | |
@@ -10,6 +10,29 @@ | |
#define PERL_SEEN_HV_FUNC_H_ | |
#include "hv_macro.h" | |
+#if defined(PERL_IN_XS_APITEST) || defined(PERL_IN_UTIL_C) || defined(PERL_IN_PERL_C) | |
+# define HV_FUNC_FULL_API | |
+#endif | |
+ | |
+ | |
+/* borrowed from perl.h, always C++ file win32/perllib.c requires it */ | |
+#ifndef PERL_NO_INLINE_FUNCTIONS | |
+ | |
+START_EXTERN_C | |
+ | |
+PERL_STATIC_NO_RET void | |
+S_die_hashlen(void); | |
+ | |
+PERL_STATIC_FORCE_INLINE U8* | |
+S_perl_hash_get_state(); | |
+ | |
+PERL_STATIC_FORCE_INLINE U8* | |
+S_perl_hash_get_prvpv_state(); | |
+ | |
+END_EXTERN_C | |
+ | |
+#endif | |
+ | |
#if !( 0 \ | |
|| defined(PERL_HASH_FUNC_SIPHASH) \ | |
|| defined(PERL_HASH_FUNC_SIPHASH13) \ | |
@@ -135,7 +158,7 @@ | |
#endif | |
#define PERL_HASH_WITH_SEED(seed,hash,str,len) \ | |
- (hash) = S_perl_hash_with_seed((const U8 *) seed, (const U8 *) str,len) | |
+ (hash) = Perl_hash_with_seed((const U8 *) seed, (const U8 *) str,len) | |
#define PERL_HASH_WITH_STATE(state,hash,str,len) \ | |
(hash) = PVT_PERL_HASH_WITH_STATE((state),(const U8*)(str),(len)) | |
#define PERL_HASH_WITH_PL_STATE(hash,str,len) \ | |
@@ -187,13 +210,6 @@ | |
#define PERL_HASH_INTERNAL(hash,str,len) PERL_HASH(hash,str,len) | |
#endif | |
-PERL_STATIC_INLINE U32 | |
-S_perl_hash_with_seed(const U8 * seed, const U8 *str, STRLEN len) { | |
- PVT__PERL_HASH_WORD_TYPE state[PERL_HASH_STATE_WORDS]; | |
- PVT_PERL_HASH_SEED_STATE(seed,(U8*)state); | |
- return PVT_PERL_HASH_WITH_STATE((U8*)state,str,len); | |
-} | |
- | |
#endif /*compile once*/ | |
/* | |
diff --git a/perl_siphash.h b/perl_siphash.h | |
index fe6ab46e24..3d66d2d6f9 100644 | |
--- a/perl_siphash.h | |
+++ b/perl_siphash.h | |
@@ -36,19 +36,14 @@ do { \ | |
PERL_STATIC_FORCE_INLINE | |
U8 * S_perl_hash_get_state(); | |
-PERL_STATIC_INLINE | |
-void S_perl_siphash_seed_state(const unsigned char * const seed_buf, unsigned char * state_buf) { | |
- U64 *v= (U64*) state_buf; | |
- SIPHASH_SEED_STATE(seed_buf, v[0],v[1],v[2],v[3]); | |
-} | |
- | |
- | |
- | |
-#define PERL_SIPHASH_FNC_P1(FNC,SIP_ROUNDS,SIP_FINAL_ROUNDS) \ | |
-PERL_STATIC_INLINE U64 \ | |
-CAT2(FNC,FNC_STATE_M_SUF64) \ | |
+#define PERL_SIPHASH_FNC_HW(FNC,SIP_RETV_T,SIP_DORET,SIP_ROUNDS,SIP_FINAL_ROUNDS) \ | |
+PERL_STATIC_INLINE SIP_RETV_T \ | |
+CAT2(FNC,FNC_STATE_M_SUF) \ | |
( FNC_STATE_M_INCPARG_ const unsigned char *in, const STRLEN inlen) \ | |
{ \ | |
+ if(UNLIKELY(inlen > (STRLEN) I32_MAX)) \ | |
+ S_die_hashlen(); \ | |
+ { \ | |
FNC_STATE_M_INCDECL \ | |
const int left = inlen & 7; \ | |
const U8 *end = in + inlen - left; \ | |
@@ -93,23 +88,11 @@ CAT2(FNC,FNC_STATE_M_SUF64) \ | |
SIP_FINAL_ROUNDS \ | |
\ | |
b = v0 ^ v1 ^ v2 ^ v3; \ | |
- return b; \ | |
-} \ | |
- \ | |
- \ | |
-PERL_STATIC_INLINE U32 \ | |
-CAT2(FNC,FNC_STATE_M_SUF) \ | |
- ( FNC_STATE_M_INCPARG_ const unsigned char *in, const STRLEN inlen) \ | |
-{ \ | |
- union { \ | |
- U64 h64; \ | |
- U32 h32[2]; \ | |
- } h; \ | |
- h.h64= CAT2(FNC,FNC_STATE_M_SUF64) ( FNC_STATE_M_INCAARG_ in,inlen); \ | |
- return h.h32[0] ^ h.h32[1]; \ | |
-} \ | |
+ SIP_DORET \ | |
+ } \ | |
+} | |
-#define PERL_SIPHASH_FNC_P2(FNC,SIP_ROUNDS,SIP_FINAL_ROUNDS) \ | |
+#define PERL_SIPHASH_FNC_SW(FNC,SIP_ROUNDS,SIP_FINAL_ROUNDS) \ | |
PERL_STATIC_INLINE U32 \ | |
FNC (const unsigned char * const seed, const unsigned char *in, const STRLEN inlen) \ | |
{ \ | |
@@ -118,84 +101,155 @@ FNC (const unsigned char * const seed, const unsigned char *in, const STRLEN inl | |
return FNC ## _with_state((U8*)state,in,inlen); \ | |
} | |
-/* XS::APITest variant with an explicit state buffer. Not used elsewhere. */ | |
+#define SIP_RETV_T_U64 U64 | |
+#define SIP_RETV_T_U32 U32 | |
+#define SIP_DORET_U64 return b; | |
+#define SIP_DORET_CASTU32 { \ | |
+ union { \ | |
+ U64 h64; \ | |
+ U32 h32[2]; \ | |
+ } h; \ | |
+ h.h64 = b; \ | |
+ return h.h32[0] ^ h.h32[1]; \ | |
+ } | |
+ | |
+/* XS::APITest variant with an explicit state buffer for unit testing. | |
+ perl.c and util.c need this because they need to see the full API inside | |
+ hv_func.h. The rest of the interp and CPAN only require a subset of | |
+ static inline functions, just enough to implement PERL_HASH(). | |
+ Note, macro PERL_HASH() is designed to be extremely const foldable by a | |
+ C compiler inside a XS module, if STRLEN arg is a C compile time constant. */ | |
-#ifdef PERL_IN_XS_APITEST | |
+#ifdef HV_FUNC_FULL_API | |
# undef FNC_STATE_M_SUF | |
-# undef FNC_STATE_M_SUF64 | |
# undef FNC_STATE_M_INCPARG_ | |
# undef FNC_STATE_M_INCAARG_ | |
# undef FNC_STATE_M_INCDECL | |
# define FNC_STATE_M_SUF _with_state | |
-# define FNC_STATE_M_SUF64 _with_state_64 | |
# define FNC_STATE_M_INCPARG_ const unsigned char * const state, | |
# define FNC_STATE_M_INCAARG_ state, | |
# define FNC_STATE_M_INCDECL | |
-PERL_SIPHASH_FNC_P1( | |
+PERL_SIPHASH_FNC_HW( | |
S_perl_hash_siphash_1_3 | |
+ ,SIP_RETV_T_U32 | |
+ ,SIP_DORET_CASTU32 | |
,SIPROUND; | |
,SIPROUND;SIPROUND;SIPROUND; | |
) | |
-PERL_SIPHASH_FNC_P1( | |
+PERL_SIPHASH_FNC_HW( | |
S_perl_hash_siphash_2_4 | |
+ ,SIP_RETV_T_U32 | |
+ ,SIP_DORET_CASTU32 | |
,SIPROUND;SIPROUND; | |
,SIPROUND;SIPROUND;SIPROUND;SIPROUND; | |
) | |
-PERL_SIPHASH_FNC_P2( | |
+PERL_SIPHASH_FNC_SW( | |
S_perl_hash_siphash_1_3 | |
,SIPROUND; | |
,SIPROUND;SIPROUND;SIPROUND; | |
) | |
-PERL_SIPHASH_FNC_P2( | |
+PERL_SIPHASH_FNC_SW( | |
S_perl_hash_siphash_2_4 | |
,SIPROUND;SIPROUND; | |
,SIPROUND;SIPROUND;SIPROUND;SIPROUND; | |
) | |
+PERL_STATIC_INLINE | |
+void S_perl_siphash_seed_state(const unsigned char * const seed_buf, unsigned char * state_buf) { | |
+ U64 *v= (U64*) state_buf; | |
+ SIPHASH_SEED_STATE(seed_buf, v[0],v[1],v[2],v[3]); | |
+} | |
+ | |
+# undef FNC_STATE_M_SUF | |
+# define FNC_STATE_M_SUF _with_state_64 | |
+ | |
+PERL_SIPHASH_FNC_HW( | |
+ S_perl_hash_siphash_1_3 | |
+ ,SIP_RETV_T_U64 | |
+ ,SIP_DORET_U64 | |
+ ,SIPROUND; | |
+ ,SIPROUND;SIPROUND;SIPROUND; | |
+) | |
+ | |
+PERL_SIPHASH_FNC_HW( | |
+ S_perl_hash_siphash_2_4 | |
+ ,SIP_RETV_T_U64 | |
+ ,SIP_DORET_U64 | |
+ ,SIPROUND;SIPROUND; | |
+ ,SIPROUND;SIPROUND;SIPROUND;SIPROUND; | |
+) | |
+ | |
+# undef FNC_STATE_M_SUF | |
+ | |
#endif | |
/* Use PL_hash_state directly. Used by CORE and XS. */ | |
#undef FNC_STATE_M_SUF | |
-#undef FNC_STATE_M_SUF64 | |
#undef FNC_STATE_M_INCPARG_ | |
#undef FNC_STATE_M_INCAARG_ | |
#undef FNC_STATE_M_INCDECL | |
#define FNC_STATE_M_SUF _with_pl_state | |
-#define FNC_STATE_M_SUF64 _with_pl_state_64 | |
#define FNC_STATE_M_INCPARG_ | |
#define FNC_STATE_M_INCAARG_ | |
+/* S_perl_hash_get_state() also in zaphod32_hash_with_pl_state() */ | |
#define FNC_STATE_M_INCDECL const unsigned char * const state = S_perl_hash_get_state(); | |
-PERL_SIPHASH_FNC_P1( | |
+PERL_SIPHASH_FNC_HW( | |
+ S_perl_hash_siphash_1_3 | |
+ ,SIP_RETV_T_U32 | |
+ ,SIP_DORET_CASTU32 | |
+ ,SIPROUND; | |
+ ,SIPROUND;SIPROUND;SIPROUND; | |
+) | |
+ | |
+PERL_SIPHASH_FNC_HW( | |
+ S_perl_hash_siphash_2_4 | |
+ ,SIP_RETV_T_U32 | |
+ ,SIP_DORET_CASTU32 | |
+ ,SIPROUND;SIPROUND; | |
+ ,SIPROUND;SIPROUND;SIPROUND;SIPROUND; | |
+) | |
+ | |
+#undef FNC_STATE_M_SUF | |
+#define FNC_STATE_M_SUF _with_pl_state_64 | |
+ | |
+PERL_SIPHASH_FNC_HW( | |
S_perl_hash_siphash_1_3 | |
+ ,SIP_RETV_T_U64 | |
+ ,SIP_DORET_U64 | |
,SIPROUND; | |
,SIPROUND;SIPROUND;SIPROUND; | |
) | |
-PERL_SIPHASH_FNC_P1( | |
+PERL_SIPHASH_FNC_HW( | |
S_perl_hash_siphash_2_4 | |
+ ,SIP_RETV_T_U64 | |
+ ,SIP_DORET_U64 | |
,SIPROUND;SIPROUND; | |
,SIPROUND;SIPROUND;SIPROUND;SIPROUND; | |
) | |
#undef FNC_STATE_M_SUF | |
-#undef FNC_STATE_M_SUF64 | |
#undef FNC_STATE_M_INCPARG_ | |
#undef FNC_STATE_M_INCAARG_ | |
#undef FNC_STATE_M_INCDECL | |
-#undef PERL_SIPHASH_FNC_P1 | |
-#undef PERL_SIPHASH_FNC_P2 | |
+#undef PERL_SIPHASH_FNC_HW | |
+#undef PERL_SIPHASH_FNC_SW | |
#undef SIPHASH_SEED_STATE | |
#undef SIPROUND | |
+#undef SIP_RETV_T_U32 | |
+#undef SIP_DORET_CASTU32 | |
+#undef SIP_RETV_T_U64 | |
+#undef SIP_DORET_U64 | |
#endif /* defined(CAN64BITHASH) */ | |
diff --git a/perlstatic.h b/perlstatic.h | |
index a698de68bf..9e37866bb7 100644 | |
--- a/perlstatic.h | |
+++ b/perlstatic.h | |
@@ -11,19 +11,44 @@ | |
* This file is a home for static functions that we don't consider suitable for | |
* inlining, but for which giving the compiler full knowledge of may be | |
* advantageous. Functions that have potential tail call optimizations are a | |
- * likely component. | |
- | |
+ * likely component. We want them as static, but we do NOT want the CC | |
+ * to inline them, and we dont want to use an extern/exported C symbol/C func. | |
+ * | |
+ * Examples are certain NO_RETURN croak/die/panic type functions with very | |
+ * high usage, in terms of unique call-sites in each perl or XS binary, but | |
+ * they are very cold and can't execute in practice, but also C compilers, | |
+ * correctly, can't optimized them away. | |
+ * | |
+ * They are optimized to be as small as possible, in machine code bytes or | |
+ * CPU instruction count, in each call site, because they are referenced so | |
+ * many times inside core and XS. They take no arguments to maximize tail-call | |
+ * opportunity on any CC/OS. They the error branch of macros that check for | |
+ * low level fatal C errors, like pointer overflows, signed math, or interp | |
+ * mem corruption. | |
+ * They are static, instead of extern/exported, so a CC has the opportunity to | |
+ * optimize them to exactly 1 conditional jump/branch instruction | |
+ * like ==, >, <, or if(!var){}, instead of 3+ instructions, something like | |
+ * cond-jump + &OS-sym-table + *read-sym + invoke-with-frame() | |
+ * to execute a extern, dyn-linked C func, through the OS's symbol table. | |
*/ | |
/* saves machine code for a common noreturn idiom typically used in Newx*() */ | |
GCC_DIAG_IGNORE_DECL(-Wunused-function); | |
-STATIC void | |
+PERL_STATIC_NO_RET void | |
Perl_croak_memory_wrap(void) | |
{ | |
Perl_croak_nocontext("%s",PL_memory_wrap); | |
} | |
+/* Solves a #include order problem with hv_func.h | |
+ Inline-able and very foldable macro PERL_HASH() uses this. */ | |
+ | |
+PERL_STATIC_NO_RET void | |
+S_die_hashlen(void) { | |
+ Perl_die_hashlen(); | |
+} | |
+ | |
GCC_DIAG_RESTORE_DECL; | |
diff --git a/proto.h b/proto.h | |
index 1ccc554a38..2bcaaf6be6 100644 | |
--- a/proto.h | |
+++ b/proto.h | |
@@ -834,6 +834,11 @@ Perl_die(pTHX_ const char *pat, ...) | |
__attribute__format__null_ok__(__printf__,pTHX_1,pTHX_2); | |
#define PERL_ARGS_ASSERT_DIE | |
+PERL_CALLCONV_NO_RET void | |
+Perl_die_hashlen(void) | |
+ __attribute__noreturn__; | |
+#define PERL_ARGS_ASSERT_DIE_HASHLEN | |
+ | |
PERL_CALLCONV_NO_RET OP * | |
Perl_die_sv(pTHX_ SV *baseex) | |
__attribute__noreturn__; | |
@@ -1586,6 +1591,12 @@ Perl_gv_try_downgrade(pTHX_ GV *gv); | |
#define PERL_ARGS_ASSERT_GV_TRY_DOWNGRADE \ | |
assert(gv) | |
+PERL_CALLCONV U32 | |
+Perl_hash_with_seed(const U8 *seed, const U8 *str, STRLEN len) | |
+ __attribute__warn_unused_result__; | |
+#define PERL_ARGS_ASSERT_HASH_WITH_SEED \ | |
+ assert(seed); assert(str) | |
+ | |
PERL_CALLCONV struct xpvhv_aux * | |
Perl_hv_auxalloc(pTHX_ HV *hv) | |
__attribute__visibility__("hidden"); | |
diff --git a/sbox32_hash.h b/sbox32_hash.h | |
index a33656e6f9..d560fb4d79 100644 | |
--- a/sbox32_hash.h | |
+++ b/sbox32_hash.h | |
@@ -4,10 +4,13 @@ | |
* the same templates. | |
*/ | |
#if !defined(PERL_IN_SBOX32_HASH_H) | |
-# define PERL_IN_SBOX32_HASH_H 1 | |
+# ifndef HV_FUNC_FULL_API | |
+# define PERL_IN_SBOX32_HASH_H 2 | |
+# else | |
+# define PERL_IN_SBOX32_HASH_H 1 | |
+# endif | |
#endif | |
-#if defined(PERL_IN_SBOX32_HASH_H) && PERL_IN_SBOX32_HASH_H == 1 | |
#ifndef DEBUG_SBOX32_HASH | |
#define DEBUG_SBOX32_HASH 0 | |
@@ -64,9 +67,6 @@ | |
#endif | |
#endif | |
-PERL_STATIC_FORCE_INLINE | |
-U8 * S_perl_hash_get_prvpv_state(); | |
- | |
#ifndef STMT_START | |
#define STMT_START do | |
#define STMT_END while(0) | |
@@ -1467,7 +1467,6 @@ SBOX32_STATIC_INLINE void sbox32_seed_state128 ( | |
} | |
#endif /* #ifndef DEBUG_SBOX32_HASH */ | |
-#endif /* #if defined(PERL_IN_SBOX32_HASH_H) && PERL_IN_SBOX32_HASH_H == 1 */ | |
#if defined(PERL_IN_SBOX32_HASH_H) && PERL_IN_SBOX32_HASH_H == 1 | |
SBOX32_STATIC_INLINE U32 sbox32_hash_with_state( | |
@@ -1487,8 +1486,13 @@ SBOX32_STATIC_INLINE U32 sbox32_hash_with_pl_state( | |
#endif | |
const U32 *state = (const U32 *)state_ch; | |
U32 hash = *state; | |
+ /* overflow chk in zaphod32_hash_with_*() */ | |
switch (key_len) { | |
+#if defined(PERL_IN_SBOX32_HASH_H) && PERL_IN_SBOX32_HASH_H == 1 | |
default: return zaphod32_hash_with_state(state_ch, key, key_len); | |
+#elif defined(PERL_IN_SBOX32_HASH_H) && PERL_IN_SBOX32_HASH_H == 2 | |
+ default: return zaphod32_hash_with_pl_state(key, key_len); | |
+#endif | |
case_256_SBOX32(hash,state,key) | |
case_255_SBOX32(hash,state,key) | |
case_254_SBOX32(hash,state,key) | |
diff --git a/util.c b/util.c | |
index 76b01740f2..b0dce71fa4 100644 | |
--- a/util.c | |
+++ b/util.c | |
@@ -1994,6 +1994,18 @@ Perl_croak_no_mem(void) | |
croak_no_mem_ext(STR_WITH_LEN("???")); | |
} | |
+/* used by S_die_hashlen() from hv_func.h and its downstream #includes */ | |
+void | |
+Perl_die_hashlen(void) | |
+{ | |
+/* As per "revert the Perl_croak_nocontext() change to PERL_HASH()" | |
+ f92b68087fa16c181807b1e16f020d76b45c4274 - 6/1/2017 10:17:51 PM | |
+ PERL_HASH_*() has very early/late calls inside perl_construct/perl_destruct. | |
+ Or perhaps, without any interp/my_perl, or before the 1st PERL_SYS_INIT3(), | |
+ by some libperl embedder. */ | |
+ noperl_die("Sorry, hash keys must be smaller than 2**31 bytes"); | |
+} | |
+ | |
/* does not return, used only in POPSTACK */ | |
void | |
Perl_croak_popstack(void) | |
@@ -4893,8 +4905,14 @@ Perl_debug_hash_seed(pTHX_ bool via_debug_h) | |
#endif /* #if (defined(USE_HASH_SEED) ... */ | |
} | |
- | |
- | |
+/* Private function for macro PERL_HASH_WITH_SEED(). Not for direct use. | |
+ PERL_HASH_WITH_SEED() has XS users. Ex. Hash::Util and/or ::FieldHash */ | |
+U32 | |
+Perl_hash_with_seed(const U8 * seed, const U8 *str, STRLEN len) { | |
+ PVT__PERL_HASH_WORD_TYPE state[PERL_HASH_STATE_WORDS]; | |
+ PVT_PERL_HASH_SEED_STATE(seed,(U8*)state); | |
+ return PVT_PERL_HASH_WITH_STATE((U8*)state,str,len); | |
+} | |
#ifdef PERL_MEM_LOG | |
diff --git a/zaphod32_hash.h b/zaphod32_hash.h | |
index 834d8cb3fd..1d26a34484 100644 | |
--- a/zaphod32_hash.h | |
+++ b/zaphod32_hash.h | |
@@ -124,7 +124,6 @@ | |
v2 = ROTR32(v2, 7) ^ v0; \ | |
} STMT_END | |
- | |
ZAPHOD32_STATIC_INLINE | |
void zaphod32_seed_state ( | |
const U8 *seed_ch, | |
@@ -177,12 +176,36 @@ void zaphod32_seed_state ( | |
} | |
+#endif /* #ifndef DEBUG_ZAPHOD32_HASH */ | |
+ | |
+#ifndef HV_FUNC_FULL_API | |
+# if !defined(ZAPHOD32_HASH_INC_PASS) | |
+# define ZAPHOD32_HASH_INC_PASS 2 | |
+# define HASH_WITH_FN_NAME zaphod32_hash_with_pl_state | |
+# define HASH_WITH_FN_INCPARG_ | |
+/* same as in sbox32_hash_with_pl_state() */ | |
+# define HASH_WITH_FN_INCDECL const U8 *state_ch = S_perl_hash_get_prvpv_state(); | |
+# endif | |
+#else | |
+# if !defined(ZAPHOD32_HASH_INC_PASS) | |
+# define ZAPHOD32_HASH_INC_PASS 1 | |
+# define HASH_WITH_FN_NAME zaphod32_hash_with_state | |
+# define HASH_WITH_FN_INCPARG_ const U8 *state_ch, | |
+# define HASH_WITH_FN_INCDECL | |
+# endif | |
+#endif /* #ifndef DEBUG_ZAPHOD32_HASH */ | |
+ | |
+ | |
+#if defined(ZAPHOD32_HASH_INC_PASS) && \ | |
+ (ZAPHOD32_HASH_INC_PASS == 1 || ZAPHOD32_HASH_INC_PASS == 2) | |
+ | |
ZAPHOD32_STATIC_INLINE | |
-U32 zaphod32_hash_with_state( | |
- const U8 *state_ch, | |
+U32 HASH_WITH_FN_NAME( | |
+ HASH_WITH_FN_INCPARG_ | |
const U8 *key, | |
const STRLEN key_len | |
) { | |
+ HASH_WITH_FN_INCDECL | |
const U32 *state= (const U32 *)state_ch; | |
const U8 *end; | |
STRLEN len = key_len; | |
@@ -195,7 +218,7 @@ U32 zaphod32_hash_with_state( | |
(unsigned int)state[2], (unsigned int)key_len); | |
{ | |
switch (len) { | |
- default: goto zaphod32_read8; | |
+ default: goto zaphod32_read8; /* does overflow check */ | |
case 12: v2 += (U32)key[11] << 24; /* FALLTHROUGH */ | |
case 11: v2 += (U32)key[10] << 16; /* FALLTHROUGH */ | |
case 10: v2 += (U32)U8TO16_LE(key+8); | |
@@ -244,6 +267,8 @@ U32 zaphod32_hash_with_state( | |
be necessary to use this. */ | |
{ | |
zaphod32_read8: | |
+ if(UNLIKELY(key_len > (STRLEN) I32_MAX)) | |
+ S_die_hashlen(); | |
len = key_len & 0x7; | |
end = key + key_len - len; | |
do { | |
@@ -279,6 +304,19 @@ zaphod32_finalize: | |
return v0 ^ v1 ^ v2; | |
} | |
+# undef HASH_WITH_FN_NAME | |
+# undef HASH_WITH_FN_INCPARG_ | |
+# undef HASH_WITH_FN_INCDECL | |
+ | |
+# if defined(ZAPHOD32_HASH_INC_PASS) && ZAPHOD32_HASH_INC_PASS== 1 | |
+# undef ZAPHOD32_HASH_INC_PASS | |
+# define ZAPHOD32_HASH_INC_PASS 2 | |
+# define HASH_WITH_FN_NAME zaphod32_hash_with_pl_state | |
+# define HASH_WITH_FN_INCPARG_ | |
+/* same as in sbox32_hash_with_pl_state() */ | |
+# define HASH_WITH_FN_INCDECL const U8 *state_ch = S_perl_hash_get_prvpv_state(); | |
+# include "zaphod32_hash.h" | |
+ | |
ZAPHOD32_STATIC_INLINE U32 zaphod32_hash( | |
const U8 *seed_ch, | |
const U8 *key, | |
@@ -289,4 +327,9 @@ ZAPHOD32_STATIC_INLINE U32 zaphod32_hash( | |
return zaphod32_hash_with_state((U8*)state,key,key_len); | |
} | |
-#endif | |
+# elif defined(ZAPHOD32_HASH_INC_PASS) == 2 | |
+# undef ZAPHOD32_HASH_INC_PASS | |
+# define ZAPHOD32_HASH_INC_PASS 3 | |
+# endif | |
+ | |
+#endif /* #if defined(Z32_H_INC_PASS) && (PASS == 1 || PASS == 2) */ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment