summaryrefslogtreecommitdiff
path: root/hv.c
diff options
context:
space:
mode:
authorNicholas Clark <nick@ccl4.org>2006-05-28 10:40:48 +0000
committerNicholas Clark <nick@ccl4.org>2006-05-28 10:40:48 +0000
commit9f76984545c78a615ef3f2522fb5b77578e41023 (patch)
tree887de5508973ef722c2714e691af75d638f19430 /hv.c
parenteb7d7d25d2f780edcbedc124a5bdca0d53ad8687 (diff)
downloadperl-9f76984545c78a615ef3f2522fb5b77578e41023.tar.gz
Perl_refcounted_he_chain_2hv()'s code to skip duplicate keys was far
too lax. p4raw-id: //depot/perl@28320
Diffstat (limited to 'hv.c')
-rw-r--r--hv.c21
1 files changed, 20 insertions, 1 deletions
diff --git a/hv.c b/hv.c
index 04439fa09a..750988c198 100644
--- a/hv.c
+++ b/hv.c
@@ -2634,7 +2634,26 @@ Perl_refcounted_he_chain_2hv(pTHX_ const struct refcounted_he *chain)
for (; entry; entry = HeNEXT(entry)) {
if (HeHASH(entry) == hash) {
- goto next_please;
+ /* We might have a duplicate key here. If so, entry is older
+ than the key we've already put in the hash, so if they are
+ the same, skip adding entry. */
+#ifdef USE_ITHREADS
+ const STRLEN klen = HeKLEN(entry);
+ const char *const key = HeKEY(entry);
+ if (klen == chain->refcounted_he_keylen
+ && (!!HeKUTF8(entry)
+ == !!(chain->refcounted_he_data[0] & HVhek_UTF8))
+ && memEQ(key, REF_HE_KEY(chain), klen))
+ goto next_please;
+#else
+ if (HeKEY_hek(entry) == chain->refcounted_he_hek)
+ goto next_please;
+ if (HeKLEN(entry) == HEK_LEN(chain->refcounted_he_hek)
+ && HeKUTF8(entry) == HEK_UTF8(chain->refcounted_he_hek)
+ && memEQ(HeKEY(entry), HEK_KEY(chain->refcounted_he_hek),
+ HeKLEN(entry)))
+ goto next_please;
+#endif
}
}
assert (!entry);