[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/org 88f7bea169 1/2: org-babel-temp-stable-file: Avoid `
From: |
ELPA Syncer |
Subject: |
[elpa] externals/org 88f7bea169 1/2: org-babel-temp-stable-file: Avoid `sxhash' collisions |
Date: |
Wed, 29 Mar 2023 09:58:55 -0400 (EDT) |
branch: externals/org
commit 88f7bea169d96963daf2fbf05f5953f9964053f9
Author: Ihor Radchenko <yantar92@posteo.net>
Commit: Ihor Radchenko <yantar92@posteo.net>
org-babel-temp-stable-file: Avoid `sxhash' collisions
* lisp/org-macs.el (org-sxhash-safe): New function to calculate object
hashes. Unlike `sxhash', the new function ensures that
if (= (org-sxhash-safe A) (org-sxhash-safe b)) then (equal A B)
Not just the opposite.
* lisp/ob-core.el (org-babel-temp-stable-file): Use the new function.
Reported-by: Thomas Worthington <thomas.worthington@cosector.com>
Link: https://orgmode.org/list/877cwrcdh2.fsf@localhost
---
lisp/ob-core.el | 2 +-
lisp/org-macs.el | 18 ++++++++++++++++++
2 files changed, 19 insertions(+), 1 deletion(-)
diff --git a/lisp/ob-core.el b/lisp/ob-core.el
index ee00938f82..25074b3abd 100644
--- a/lisp/ob-core.el
+++ b/lisp/ob-core.el
@@ -3343,7 +3343,7 @@ constructed like the following: PREFIXDATAhashSUFFIX."
"%s%s%s%s"
(file-name-as-directory (org-babel-temp-stable-directory))
prefix
- (sxhash data)
+ (org-sxhash-safe data)
(or suffix ""))))
;; Create file.
(with-temp-file path)
diff --git a/lisp/org-macs.el b/lisp/org-macs.el
index 15a6f3e6a3..ad1d3cf14c 100644
--- a/lisp/org-macs.el
+++ b/lisp/org-macs.el
@@ -1624,6 +1624,24 @@ Credit:
https://stackoverflow.com/questions/11871245/knuth-multiplicative-hash#4
(cl-assert (and (<= 0 base 32)))
(ash (* number 2654435769) (- base 32)))
+(defvar org-sxhash-hashes (make-hash-table :weakness 'key :test 'equal))
+(defvar org-sxhash-objects (make-hash-table :weakness 'value))
+(defun org-sxhash-safe (obj &optional counter)
+ "Like `sxhash' for OBJ, but collision-free for in-memory objects.
+When COUNTER is non-nil, return safe hash for (COUNTER . OBJ)."
+ ;; Note: third-party code may modify OBJ by side effect.
+ ;; Should not affect anything as long as `org-sxhash-safe'
+ ;; is used to calculate hash.
+ (or (and (not counter) (gethash obj org-sxhash-hashes))
+ (let* ((hash (sxhash (if counter (cons counter obj) obj)))
+ (obj-old (gethash hash org-sxhash-objects)))
+ (if obj-old ; collision
+ (org-sxhash-safe obj (if counter (1+ counter) 1))
+ ;; No collision. Remember and return normal hash.
+ (puthash hash obj org-sxhash-objects)
+ (puthash obj hash org-sxhash-hashes)))))
+
+
(provide 'org-macs)
;; Local variables: