OOB reading when using strings and surrogates

Peter McGoron via Chicken-users <[email protected]> Wed, 24 Jun 2026 17:49:16 -0400
Newsgroups gmane.lisp.scheme.chicken
Message-ID <[email protected]>
I read in <https://www.more-magic.net/posts/chicken-6.html> about the 
surrogate byte escape mechanism.

I was experimenting with ways to break it, and found this using 
valgrind. I don't have specific buggy behavior associated with this, but 
the OOB reads might cause one in another scenario.

/tmp $ valgrind ~/.local/chicken-master/bin/csi -n
==32144== Memcheck, a memory error detector
==32144== Copyright (C) 2002-2024, and GNU GPL'd, by Julian Seward et al.
==32144== Using Valgrind-3.25.1 and LibVEX; rerun with -h for copyright info
==32144== Command: /home/user/.local/chicken-master/bin/csi -n
==32144==
CHICKEN
(c)2000-2007 Felix L. Winkelmann, (c)2008 The CHICKEN Team
Version 6.0.0 (rev 5b1982d8)
linux-unix-gnu-x86-64 [ 64bit dload ptables ]

Type ,? for help.
#;1> (import (scheme base))
#;2> (define s (make-string 3 #\x20))
#;3> s
"   "
#;4> (string-set! s 0 #\xDCC2)
#;5> (string-set! s 1 #\xDCA1) ;; #xC2 #xA1 is UTF-8 encoding for ¡
#;6> s
==32144== Conditional jump or move depends on uninitialised value(s)
==32144==    at 0x5145E22: utf8_decode (utf.c:3206)
==32144==    by 0x5146D92: C_utf_subchar (utf.c:3294)
==32144==    by 0x50FFF88: C_i_string_ref (runtime.c:5919)
==32144==    by 0x4AE30AB: f_30914 (library.c:53074)
==32144==    by 0x4AE348F: f_30930 (library.c:53109)
==32144==    by 0x4B86600: f_42115 (library.c:80213)
==32144==    by 0x4ADCD0E: f_30283 (library.c:51986)
==32144==    by 0x4AE339A: f_30914 (library.c:53097)
==32144==    by 0x4AE2F62: f_30905 (library.c:53051)
==32144==    by 0x4B86600: f_42115 (library.c:80213)
==32144==    by 0x4ADCD0E: f_30283 (library.c:51986)
==32144==    by 0x4AE1040: f_30689 (library.c:52730)
==32144==
==32144== Conditional jump or move depends on uninitialised value(s)
==32144==    at 0x5145E6F: utf8_decode (utf.c:3208)
==32144==    by 0x5146D92: C_utf_subchar (utf.c:3294)
==32144==    by 0x50FFF88: C_i_string_ref (runtime.c:5919)
==32144==    by 0x4AE30AB: f_30914 (library.c:53074)
==32144==    by 0x4AE348F: f_30930 (library.c:53109)
==32144==    by 0x4B86600: f_42115 (library.c:80213)
==32144==    by 0x4ADCD0E: f_30283 (library.c:51986)
==32144==    by 0x4AE339A: f_30914 (library.c:53097)
==32144==    by 0x4AE2F62: f_30905 (library.c:53051)
==32144==    by 0x4B86600: f_42115 (library.c:80213)
==32144==    by 0x4ADCD0E: f_30283 (library.c:51986)
==32144==    by 0x4AE1040: f_30689 (library.c:52730)
==32144==
"¡ "
#;8> (string-ref s 0)
#\¡
#;9> (string-ref s 1)
==32144== Conditional jump or move depends on uninitialised value(s)
==32144==    at 0x5145E22: utf8_decode (utf.c:3206)
==32144==    by 0x5146D92: C_utf_subchar (utf.c:3294)
==32144==    by 0x50FFF88: C_i_string_ref (runtime.c:5919)
==32144==    by 0x49E1782: f_12138 (library.c:11213)
==32144==    by 0x4C07AB2: f_7623 (eval.c:18553)
==32144==    by 0x4BC8760: f_4194 (eval.c:10055)
==32144==    by 0x4C07928: f_7619 (eval.c:18529)
==32144==    by 0x4BC66AB: f_4001 (eval.c:9811)
==32144==    by 0x4C0770B: f_7612 (eval.c:18504)
==32144==    by 0x4BC66AB: f_4001 (eval.c:9811)
==32144==    by 0x4C074D5: f_7605 (eval.c:18479)
==32144==    by 0x4BBD411: f_11729 (eval.c:8313)
==32144==
==32144== Conditional jump or move depends on uninitialised value(s)
==32144==    at 0x5145E6F: utf8_decode (utf.c:3208)
==32144==    by 0x5146D92: C_utf_subchar (utf.c:3294)
==32144==    by 0x50FFF88: C_i_string_ref (runtime.c:5919)
==32144==    by 0x49E1782: f_12138 (library.c:11213)
==32144==    by 0x4C07AB2: f_7623 (eval.c:18553)
==32144==    by 0x4BC8760: f_4194 (eval.c:10055)
==32144==    by 0x4C07928: f_7619 (eval.c:18529)
==32144==    by 0x4BC66AB: f_4001 (eval.c:9811)
==32144==    by 0x4C0770B: f_7612 (eval.c:18504)
==32144==    by 0x4BC66AB: f_4001 (eval.c:9811)
==32144==    by 0x4C074D5: f_7605 (eval.c:18479)
==32144==    by 0x4BBD411: f_11729 (eval.c:8313)
==32144==
#\