~ chicken-core (master) f27519f14ea303bf2867e6230f128522a38de378


commit f27519f14ea303bf2867e6230f128522a38de378
Author:     felix <felix@call-with-current-continuation.org>
AuthorDate: Fri May 15 12:36:48 2026 +0200
Commit:     felix <felix@call-with-current-continuation.org>
CommitDate: Fri May 15 12:36:48 2026 +0200

    integer->char: check argument for proper range

diff --git a/library.scm b/library.scm
index 63878f1a..1576aad9 100644
--- a/library.scm
+++ b/library.scm
@@ -566,10 +566,21 @@ EOF
   (##sys#check-char c 'char->integer)
   (##core#inline "C_fix" (##core#inline "C_character_code" c)) )
 
-(define (integer->char n)
-  (##sys#check-fixnum n 'integer->char)
+(define (##sys#check-char-code n loc)
+  (if (or (##core#inline "C_fixnum_lessp" n 0)
+          (##core#inline "C_fixnum_greaterp" n #x10ffff))
+    (##sys#signal-hook
+      #:domain-error loc "character code is out of valid range" n)
+    n))
+
+(define-inline (fast-i->c n)
   (##core#inline "C_make_character" (##core#inline "C_unfix" n)) )
 
+(define (integer->char n)
+  (##sys#check-fixnum n 'integer->char)
+  (##sys#check-char-code n 'integer->char)
+  (fast-i->c n))
+ 
 (define (char=? c1 c2 . more)
   (##sys#check-char c1 'char=?)
   (##sys#check-char c2 'char=?)
@@ -1229,7 +1240,7 @@ EOF
                      #!eof
                      (let ((c (##core#inline "C_i_bytevector_ref" bv index)))
                        (set! index (##core#inline "C_fixnum_plus" index 1))
-                       (integer->char c))))
+                       (fast-i->c c))))
                (lambda (_) ; peek-char
                  (if (eq? index bv-len)
                      #!eof
@@ -3039,9 +3050,9 @@ EOF
     ;; CHICKENs and it just makes more sense.
     (##core#inline_allocate ("C_a_i_flonum_quotient" 4) 0.0 0.0))
   (let* ((len (string-length str))
-         (0..r (integer->char (fx+ (char->integer #\0) (fx- radix 1))))
-         (a..r (integer->char (fx+ (char->integer #\a) (fx- radix 11))))
-         (A..r (integer->char (fx+ (char->integer #\A) (fx- radix 11))))
+         (0..r (fast-i->c (fx+ (char->integer #\0) (fx- radix 1))))
+         (a..r (fast-i->c (fx+ (char->integer #\a) (fx- radix 11))))
+         (A..r (fast-i->c (fx+ (char->integer #\A) (fx- radix 11))))
          ;; Ugly flag which we need (note that "exactness" is mutated too!)
          ;; Since there is (almost) no backtracking we can do this.
          (seen-hashes? #f)
@@ -4645,6 +4656,7 @@ EOF
 	(parentheses-synonyms parentheses-synonyms)
         (case-sensitive case-sensitive)
 	(symbol-escape symbol-escape)
+        (integer->char integer->char)
 	(current-read-table ##sys#current-read-table))
     (lambda (port infohandler)
       (let ((csp (and (case-sensitive) (##sys#slot port 13)))
Trap