~ chicken-core (chicken-5) 0e97b648407d750f1e476e3c193e136126558346


commit 0e97b648407d750f1e476e3c193e136126558346
Author:     siiky <github-siiky@net-c.cat>
AuthorDate: Mon Mar 11 12:15:44 2024 +0100
Commit:     Mario Domenech Goulart <mario@parenteses.org>
CommitDate: Tue Mar 12 20:41:44 2024 +0100

    Add bounds-checks to substring=? and substring-ci=?
    
    Because the `start1`/`start2`/`n` parameters were not checked to be
    within bounds, it was possible to access arbitrary memory outside of
    the given strings. This could lead to wrong results (returning #t/#f
    when the opposite was true), or possibly crashing the program.
    
    Signed-off-by: felix <felix@call-with-current-continuation.org>
    Signed-off-by: Mario Domenech Goulart <mario@parenteses.org>

diff --git a/data-structures.scm b/data-structures.scm
index 8563fba2..642d2a59 100644
--- a/data-structures.scm
+++ b/data-structures.scm
@@ -155,11 +155,13 @@
 (define (##sys#substring=? s1 s2 start1 start2 n)
   (##sys#check-string s1 'substring=?)
   (##sys#check-string s2 'substring=?)
-  (let ((len (or n
-		 (fxmin (fx- (##sys#size s1) start1)
-			(fx- (##sys#size s2) start2) ) ) ) )
-    (##sys#check-fixnum start1 'substring=?)
-    (##sys#check-fixnum start2 'substring=?)
+  (##sys#check-range start1 0 (##sys#size s1) 'substring=?)
+  (##sys#check-range start2 0 (##sys#size s2) 'substring=?)
+  (let* ((maxlen (fxmin (fx- (##sys#size s1) start1)
+                        (fx- (##sys#size s2) start2)))
+         (len (if n
+                  (begin (##sys#check-range n 0 maxlen 'substring=?) n)
+                  maxlen)))
     (##core#inline "C_substring_compare" s1 s2 start1 start2 len) ) )
 
 (define (substring=? s1 s2 #!optional (start1 0) (start2 0) len)
@@ -168,11 +170,13 @@
 (define (##sys#substring-ci=? s1 s2 start1 start2 n)
   (##sys#check-string s1 'substring-ci=?)
   (##sys#check-string s2 'substring-ci=?)
-  (let ((len (or n
-		 (fxmin (fx- (##sys#size s1) start1)
-			(fx- (##sys#size s2) start2) ) ) ) )
-    (##sys#check-fixnum start1 'substring-ci=?)
-    (##sys#check-fixnum start2 'substring-ci=?)
+  (##sys#check-range start1 0 (##sys#size s1) 'substring-ci=?)
+  (##sys#check-range start2 0 (##sys#size s2) 'substring-ci=?)
+  (let* ((maxlen (fxmin (fx- (##sys#size s1) start1)
+                        (fx- (##sys#size s2) start2)))
+         (len (if n
+                  (begin (##sys#check-range n 0 maxlen 'substring-ci=?) n)
+                  maxlen)))
     (##core#inline "C_substring_compare_case_insensitive"
 		   s1 s2 start1 start2 len) ) )
 
diff --git a/tests/data-structures-tests.scm b/tests/data-structures-tests.scm
index 1d7820df..17a3dd58 100644
--- a/tests/data-structures-tests.scm
+++ b/tests/data-structures-tests.scm
@@ -50,6 +50,18 @@
 (assert (not (substring-index-ci "o\x00bar" "foo\x00baz")))
 (assert (= 0 (substring-index "" "")))
 (assert (= 1 (substring-index "" "a" 1)))
+(assert-error (substring=? "a" "a" 2))
+(assert-error (substring=? "a" "a" -2))
+(assert-error (substring=? "a" "a" 0 2))
+(assert-error (substring=? "a" "a" 0 -2))
+(assert-error (substring=? "a" "a" 0 0 2))
+(assert-error (substring=? "a" "a" 0 0 -2))
+(assert-error (substring-ci=? "a" "a" 2))
+(assert-error (substring-ci=? "a" "a" -2))
+(assert-error (substring-ci=? "a" "a" 0 2))
+(assert-error (substring-ci=? "a" "a" 0 -2))
+(assert-error (substring-ci=? "a" "a" 0 0 2))
+(assert-error (substring-ci=? "a" "a" 0 0 -2))
 (assert-error (substring-index "" "a" 2))
 (assert-error (substring-index "a" "b" 2))
 (assert (not (substring-index "a" "b" 1)))
Trap