summaryrefslogtreecommitdiffstats
path: root/generic/tclHash.c
diff options
context:
space:
mode:
authorsebres <sebres@users.sourceforge.net>2024-04-12 21:44:05 (GMT)
committersebres <sebres@users.sourceforge.net>2024-04-12 21:44:05 (GMT)
commit95ba4d90b35db89ffba05ae1e25f9d1d03e7df55 (patch)
tree80257950fd27959f7d777dd412787a70d767eee6 /generic/tclHash.c
parent8ab9d1f58931108c9dabb055d2921121ce7efc47 (diff)
parentd57677488f057b142552a7611ebd5dd23e0cf359 (diff)
downloadtcl-95ba4d90b35db89ffba05ae1e25f9d1d03e7df55.zip
tcl-95ba4d90b35db89ffba05ae1e25f9d1d03e7df55.tar.gz
tcl-95ba4d90b35db89ffba05ae1e25f9d1d03e7df55.tar.bz2
merge 8.5, amend to [82f721a5a039596f]: the bug was fixed incompletely, this is full bug fix now - don't allow direct compare if keys contain values rather than pointers;
introduced new hash-key type flag TCL_HASH_KEY_DIRECT_COMPARE... I know it is public interface, but the bug is grave, and I don't know how one could fix it without that, by retaining same performance for pointer hashes (e. g. vars, dicts and all of TclObjs).
Diffstat (limited to 'generic/tclHash.c')
-rw-r--r--generic/tclHash.c40
1 files changed, 28 insertions, 12 deletions
diff --git a/generic/tclHash.c b/generic/tclHash.c
index f4b0a47..83bc0fb 100644
--- a/generic/tclHash.c
+++ b/generic/tclHash.c
@@ -318,22 +318,38 @@ CreateHashEntry(
if (typePtr->compareKeysProc) {
Tcl_CompareHashKeysProc *compareKeysProc = typePtr->compareKeysProc;
-
- for (hPtr = tablePtr->buckets[index]; hPtr != NULL;
- hPtr = hPtr->nextPtr) {
+ if (typePtr->flags & TCL_HASH_KEY_DIRECT_COMPARE) {
+ for (hPtr = tablePtr->buckets[index]; hPtr != NULL;
+ hPtr = hPtr->nextPtr) {
#if TCL_HASH_KEY_STORE_HASH
- if (hash != PTR2UINT(hPtr->hash)) {
- continue;
+ if (hash != PTR2UINT(hPtr->hash)) {
+ continue;
+ }
+#endif
+ /* if keys pointers or values are equal */
+ if ((key == hPtr->key.oneWordValue)
+ || compareKeysProc((void *) key, hPtr)
+ ) {
+ if (newPtr) {
+ *newPtr = 0;
+ }
+ return hPtr;
+ }
}
+ } else { /* no direct compare */
+ for (hPtr = tablePtr->buckets[index]; hPtr != NULL;
+ hPtr = hPtr->nextPtr) {
+#if TCL_HASH_KEY_STORE_HASH
+ if (hash != PTR2UINT(hPtr->hash)) {
+ continue;
+ }
#endif
- /* if keys pointers or values are equal */
- if ((key == hPtr->key.oneWordValue)
- || compareKeysProc((void *) key, hPtr)
- ) {
- if (newPtr) {
- *newPtr = 0;
+ if (compareKeysProc((void *) key, hPtr)) {
+ if (newPtr) {
+ *newPtr = 0;
+ }
+ return hPtr;
}
- return hPtr;
}
}
} else {