Skip to content

Instantly share code, notes, and snippets.

@bulk88
Created February 26, 2025 21:51
Show Gist options
  • Save bulk88/6ad8066b5677e9ffe276d4a968f67a91 to your computer and use it in GitHub Desktop.
Save bulk88/6ad8066b5677e9ffe276d4a968f67a91 to your computer and use it in GitHub Desktop.
hv hasher fn prototype fix.diff
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