emacs-elpa-diffs
[Top][All Lists]
Advanced

[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:



reply via email to

[Prev in Thread] Current Thread [Next in Thread]