diff options
| author | sebres <sebres@users.sourceforge.net> | 2024-04-12 21:44:05 (GMT) |
|---|---|---|
| committer | sebres <sebres@users.sourceforge.net> | 2024-04-12 21:44:05 (GMT) |
| commit | 95ba4d90b35db89ffba05ae1e25f9d1d03e7df55 (patch) | |
| tree | 80257950fd27959f7d777dd412787a70d767eee6 /generic/tclHash.c | |
| parent | 8ab9d1f58931108c9dabb055d2921121ce7efc47 (diff) | |
| parent | d57677488f057b142552a7611ebd5dd23e0cf359 (diff) | |
| download | tcl-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.c | 40 |
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 { |
