~ chicken-core (chicken-5) cd1b9775005ebe220ba11265dbf5396142e65f26


commit cd1b9775005ebe220ba11265dbf5396142e65f26
Author:     Peter Bex <peter.bex@xs4all.nl>
AuthorDate: Sun Sep 22 11:37:09 2013 +0200
Commit:     Peter Bex <peter.bex@xs4all.nl>
CommitDate: Tue Sep 24 09:05:48 2013 +0200

    Read no more than the buffer length when a length of #f is passed in
    
    Signed-off-by: Mario Domenech Goulart <mario.goulart@gmail.com>
    Signed-off-by: Peter Bex <peter.bex@xs4all.nl>

diff --git a/NEWS b/NEWS
index 5b3cfdb3..d4e65e98 100644
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,8 @@
 4.8.3
 
+- Security fixes
+  - read-string! no longer reads beyond its buffer when length is #f.
+
 - Runtime system
   - The procedure trace buffer has been made resizable.
 
diff --git a/extras.scm b/extras.scm
index 49ab5cf2..8f17e1f3 100644
--- a/extras.scm
+++ b/extras.scm
@@ -176,10 +176,10 @@
 (define (read-string! n dest #!optional (port ##sys#standard-input) (start 0))
   (##sys#check-input-port port #t 'read-string!)
   (##sys#check-string dest 'read-string!)
-  (when n
-    (##sys#check-exact n 'read-string!)
-    (when (fx> (fx+ start n) (##sys#size dest))
-      (set! n (fx- (##sys#size dest) start))))
+  (when n (##sys#check-exact n 'read-string!))
+  (let ((dest-size (##sys#size dest)))
+    (unless (and n (fx<= (fx+ start n) dest-size))
+      (set! n (fx- dest-size start))))
   (##sys#check-exact start 'read-string!)
   (##sys#read-string! n dest port start) )
 
diff --git a/tests/port-tests.scm b/tests/port-tests.scm
index 409c552a..bd7c8586 100644
--- a/tests/port-tests.scm
+++ b/tests/port-tests.scm
@@ -295,7 +295,49 @@ EOF
 
 (test-group
  "read-line string port position tests"
-(test-port-position read-string-line/pos))
+ (test-port-position read-string-line/pos))
+
+(test-group "read-string!"
+  (let ((in (open-input-string "1234567890"))
+        (buf (make-string 5)))
+    (test-equal "read-string! won't read past buffer if given #f"
+                (read-string! #f buf in)
+                5)
+    (test-equal "read-string! reads the requested bytes with #f"
+                buf
+                "12345")
+    (test-equal "read-string! won't read past buffer if given #f and offset"
+                (read-string! #f buf in 3)
+                2)
+    (test-equal "read-string! reads the requested bytes with #f and offset"
+                buf
+                "12367")
+    (test-equal "read-string! reads until the end correctly"
+                (read-string! #f buf in)
+                3)
+    (test-equal "read-string! leaves the buffer's tail intact"
+                buf
+                "89067"))
+  (let ((in (open-input-string "1234567890"))
+        (buf (make-string 5)))
+    (test-equal "read-string! won't read past buffer if given size"
+                (read-string! 10 buf in)
+                5)
+    (test-equal "read-string! reads the requested bytes with buffer size"
+                buf
+                "12345")
+    (test-equal "read-string! won't read past buffer if given size and offset"
+                (read-string! 10 buf in 3)
+                2)
+    (test-equal "read-string! reads the requested bytes with buffer size and offset"
+                buf
+                "12367")
+    (test-equal "read-string! reads until the end correctly with buffer size"
+                (read-string! 10 buf in)
+                3)
+    (test-equal "read-string! leaves the buffer's tail intact"
+                buf
+                "89067")))
 
 ;; Disabled because it requires `echo -n` for
 ;; the EOF test, and that is not available on all systems.
Trap