branch: externals/hotfuzz
commit 50ea5b54c21dc6a2437e37b17c7ea14f8ba06771
Author: Axel Forsman <[email protected]>
Commit: Axel Forsman <[email protected]>

    Check for too long haystack
    
    Fixes #4
---
 hotfuzz.el    | 19 +++++++++++--------
 test/tests.el |  8 ++++++++
 2 files changed, 19 insertions(+), 8 deletions(-)

diff --git a/hotfuzz.el b/hotfuzz.el
index 97c6d03c09..fe8e738532 100644
--- a/hotfuzz.el
+++ b/hotfuzz.el
@@ -46,9 +46,10 @@ Emacs `completion-styles' interface."
 ;; allocate min(#needle, #haystack) for C/D when only calculating the
 ;; cost does not apply.
 (defconst hotfuzz--max-needle-len 128)
+(defconst hotfuzz--max-haystack-len 512)
 (defvar hotfuzz--c (make-vector hotfuzz--max-needle-len 0))
 (defvar hotfuzz--d (make-vector hotfuzz--max-needle-len 0))
-(defvar hotfuzz--bonus (make-vector 512 0))
+(defvar hotfuzz--bonus (make-vector hotfuzz--max-haystack-len 0))
 
 (defconst hotfuzz--bonus-prev-luts
   (eval-when-compile
@@ -104,11 +105,13 @@ and ND/PD respectively may alias."
   "Return the difference score of NEEDLE and the match HAYSTACK."
   (let ((n (length haystack)) (m (length needle))
         (c hotfuzz--c) (d hotfuzz--d))
-    (fillarray c 10000)
-    (fillarray d 10000)
-    (hotfuzz--calc-bonus haystack)
-    (dotimes (i n) (hotfuzz--match-row haystack needle i c d c d))
-    (aref c (1- m)))) ; Final cost
+    (if (> n hotfuzz--max-haystack-len)
+        10000
+      (fillarray c 10000)
+      (fillarray d 10000)
+      (hotfuzz--calc-bonus haystack)
+      (dotimes (i n) (hotfuzz--match-row haystack needle i c d c d))
+      (aref c (1- m))))) ; Final cost
 
 (defun hotfuzz-highlight (needle haystack)
   "Highlight the characters that NEEDLE matched in HAYSTACK.
@@ -116,8 +119,8 @@ HAYSTACK has to be a match according to `hotfuzz-filter'."
   (let ((n (length haystack)) (m (length needle))
         (c hotfuzz--c) (d hotfuzz--d)
         (case-fold-search completion-ignore-case))
-    (if (> m hotfuzz--max-needle-len)
-        haystack ; Bail out if search string is too long
+    (if (or (> n hotfuzz--max-haystack-len) (> m hotfuzz--max-needle-len))
+        haystack ; Bail out if is too long
       (fillarray c 10000)
       (fillarray d 10000)
       (hotfuzz--calc-bonus haystack)
diff --git a/test/tests.el b/test/tests.el
index 690381f4cc..118fc46df3 100644
--- a/test/tests.el
+++ b/test/tests.el
@@ -51,6 +51,14 @@
       (should (equal (hotfuzz-filter "a" xs) xs))
       (should (equal (hotfuzz-filter "A" xs) xs)))))
 
+(ert-deftest long-candidates-test ()
+  (let ((a (make-string 4096 ?x))
+        (b (concat (make-string 2047 ?y) "x" (make-string 2048 ?y))))
+    ;; Too long candidates should still be filtered with matches
+    ;; lumped together at the end in their original order.
+    (should (equal (hotfuzz-filter "x" (list (make-string 4096 ?y) b a "x"))
+                   (list "x" b a)))))
+
 (ert-deftest all-completions-test ()
   (let* ((completion-styles '(hotfuzz))
          (s "fb")

Reply via email to