X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=hv.c;h=eb2a1a5aa71e98b0c47a259ff90a433e4b44f811;hb=89e33a0587050e7ef2e88ba45c87444d8506f821;hp=68a95976ecc5c42c580de3a7532e54712cea4c48;hpb=658b4a4a328256e2a80066c57ca7866646757dad;p=p5sagit%2Fp5-mst-13.2.git diff --git a/hv.c b/hv.c index 68a9597..eb2a1a5 100644 --- a/hv.c +++ b/hv.c @@ -33,6 +33,9 @@ holds the key and hash value. #define HV_MAX_LENGTH_BEFORE_SPLIT 14 +static const char *const S_strtab_error + = "Cannot modify shared string table in hv_%s"; + STATIC void S_more_he(pTHX) { @@ -131,12 +134,12 @@ Perl_hek_dup(pTHX_ HEK *source, CLONE_PARAMS* param) if (shared) { /* We already shared this hash key. */ - share_hek_hek(shared); + (void)share_hek_hek(shared); } else { shared - = HeKEY_hek(share_hek_flags(HEK_KEY(source), HEK_LEN(source), - HEK_HASH(source), HEK_FLAGS(source))); + = share_hek_flags(HEK_KEY(source), HEK_LEN(source), + HEK_HASH(source), HEK_FLAGS(source)); ptr_table_store(PL_ptr_table, source, shared); } return shared; @@ -173,13 +176,12 @@ Perl_he_dup(pTHX_ HE *e, bool shared, CLONE_PARAMS* param) if (shared) { /* We already shared this hash key. */ - share_hek_hek(shared); + (void)share_hek_hek(shared); } else { shared - = HeKEY_hek(share_hek_flags(HEK_KEY(source), HEK_LEN(source), - HEK_HASH(source), - HEK_FLAGS(source))); + = share_hek_flags(HEK_KEY(source), HEK_LEN(source), + HEK_HASH(source), HEK_FLAGS(source)); ptr_table_store(PL_ptr_table, source, shared); } HeKEY_hek(ret) = shared; @@ -688,11 +690,19 @@ S_hv_fetch_common(pTHX_ HV *hv, SV *keysv, const char *key, STRLEN klen, /* Need to swap the key we have for a key with the flags we need. As keys are shared we can't just write to the flag, so we share the new one, unshare the old one. */ - HEK *new_hek = HeKEY_hek(share_hek_flags(key, klen, hash, - masked_flags)); + HEK *new_hek = share_hek_flags(key, klen, hash, + masked_flags); unshare_hek (HeKEY_hek(entry)); HeKEY_hek(entry) = new_hek; } + else if (hv == PL_strtab) { + /* PL_strtab is usually the only hash without HvSHAREKEYS, + so putting this test here is cheap */ + if (flags & HVhek_FREEKEY) + Safefree(key); + Perl_croak(aTHX_ S_strtab_error, + action & HV_FETCH_LVALUE ? "fetch" : "store"); + } else HeKFLAGS(entry) = masked_flags; if (masked_flags & HVhek_ENABLEHVKFLAGS) @@ -793,7 +803,15 @@ S_hv_fetch_common(pTHX_ HV *hv, SV *keysv, const char *key, STRLEN klen, /* share_hek_flags will do the free for us. This might be considered bad API design. */ if (HvSHAREKEYS(hv)) - HeKEY_hek(entry) = HeKEY_hek(share_hek_flags(key, klen, hash, flags)); + HeKEY_hek(entry) = share_hek_flags(key, klen, hash, flags); + else if (hv == PL_strtab) { + /* PL_strtab is usually the only hash without HvSHAREKEYS, so putting + this test here is cheap */ + if (flags & HVhek_FREEKEY) + Safefree(key); + Perl_croak(aTHX_ S_strtab_error, + action & HV_FETCH_LVALUE ? "fetch" : "store"); + } else /* gotta do the real thing */ HeKEY_hek(entry) = save_hek_flags(key, klen, hash, flags); HeVAL(entry) = val; @@ -1037,6 +1055,12 @@ S_hv_delete_common(pTHX_ HV *hv, SV *keysv, const char *key, STRLEN klen, if ((HeKFLAGS(entry) ^ masked_flags) & HVhek_UTF8) continue; + if (hv == PL_strtab) { + if (k_flags & HVhek_FREEKEY) + Safefree(key); + Perl_croak(aTHX_ S_strtab_error, "delete"); + } + /* if placeholder is here, it's already been deleted.... */ if (HeVAL(entry) == &PL_sv_placeholder) { @@ -1420,7 +1444,7 @@ Perl_newHVhv(pTHX_ HV *ohv) ent = new_HE(); HeVAL(ent) = newSVsv(HeVAL(oent)); HeKEY_hek(ent) - = shared ? HeKEY_hek(share_hek_flags(key, len, hash, flags)) + = shared ? share_hek_flags(key, len, hash, flags) : save_hek_flags(key, len, hash, flags); if (prev) HeNEXT(prev) = ent; @@ -2279,10 +2303,10 @@ Perl_share_hek(pTHX_ const char *str, I32 len, register U32 hash) flags |= HVhek_WASUTF8 | HVhek_FREEKEY; } - return HeKEY_hek(share_hek_flags (str, len, hash, flags)); + return share_hek_flags (str, len, hash, flags); } -STATIC HE * +STATIC HEK * S_share_hek_flags(pTHX_ const char *str, I32 len, register U32 hash, int flags) { register XPVHV* xhv; @@ -2363,7 +2387,7 @@ S_share_hek_flags(pTHX_ const char *str, I32 len, register U32 hash, int flags) if (flags & HVhek_FREEKEY) Safefree(str); - return entry; + return HeKEY_hek(entry); } I32 *