master: Fix out of bound writes in simd-copy-utf8-sap-to-character-string

stassats via Sbcl-commits <[email protected]> Wed, 08 Jul 2026 18:47:33 +0000
Newsgroups gmane.lisp.steel-bank.cvs
Message-ID <[email protected]>
The branch "master" has been updated in SBCL:
       via  262b56a6e88397ce1a02bd4a61a3e89b13d7e6ac (commit)
      from  16b40979320e0b45ee770ccaa8fbd1b766e1c068 (commit)

- Log -----------------------------------------------------------------
commit 262b56a6e88397ce1a02bd4a61a3e89b13d7e6ac
Author: Stas Boukarev <[email protected]>
Date:   Wed Jul 8 21:47:01 2026 +0300

    Fix out of bound writes in simd-copy-utf8-sap-to-character-string
---
 src/code/arm64-simd.lisp  | 30 +++++++++++++++++++++++++-----
 src/code/share-vm.lisp    |  2 +-
 src/code/x86-64-simd.lisp | 21 ++++++++++++++++++++-
 3 files changed, 46 insertions(+), 7 deletions(-)

diff --git a/src/code/arm64-simd.lisp b/src/code/arm64-simd.lisp
index 5cb746771..b4a4d3ed6 100644
--- a/src/code/arm64-simd.lisp
+++ b/src/code/arm64-simd.lisp
@@ -1676,6 +1676,7 @@
                    ((32-bit-array sap-reg t) (vector-sap string))
                    ((table sap-reg t) (vector-sap table))
                    ((n unsigned-reg) (- length 9))
+                   ((string-length unsigned-reg) (logand (+ (length string) 3) -4))
                    ((tmp unsigned-reg))
                    ((ptr unsigned-reg))
                    ((current double-reg))
@@ -1720,7 +1721,6 @@
                 (inst cmeq continuations sh mask-2 :8b)
                 (inst and starts powers continuations :8b)
                 (inst addv starts starts :8b)
-                (inst addv count continuations :8b)
                 (inst umov tmp starts 0 :b)
 
                 (inst ushll current16 :8h current :8b 0)
@@ -1742,22 +1742,42 @@
 
                 ;; Widen
                 (inst ushll p32-1 :4s packed :4h 0)
-                (inst ushll2 p32-2 :4s packed :8h 0)
-
                 (inst add ptr 32-bit-array (lsl char-index 2))
+
+                (inst sub tmp string-length char-index)
+                (inst cmp tmp 8)
+                (inst b :lt tail-16)
+
+                (inst ushll2 p32-2 :4s packed :8h 0)
+
+                (inst addv count continuations :8b)
                 (inst stp p32-1 p32-2 (@ ptr))
-
                 (inst smov tmp count 0 :b)
                 (inst add byte-index byte-index 8)
                 (inst add char-index char-index 8)
                 (inst add char-index char-index tmp) ;; subtract continuations
 
-                start
+                START
                 (inst cmp byte-index n)
                 (inst b :le LOOP)
 
                 ;; In the last iteration, did it consume 9 or 8 bytes?
                 (inst umov tmp current 7 :b)
+                (inst b ADJUST)
+
+                TAIL-16
+                (inst movi mask-2 #xFFFFFFFF)
+                (inst and continuations continuations mask-2 :8b)
+                (inst addv count continuations :8b)
+                (inst smov tmp count 0 :b)
+                (inst str p32-1 (@ ptr))
+                (inst add byte-index byte-index 4)
+                (inst add char-index char-index 4)
+                (inst add char-index char-index tmp)
+
+                ;; In the last iteration, did it consume 5 or 4 bytes?
+                (inst umov tmp current 3 :b)
+                ADJUST
                 ;; the last current byte is a leading byte, meaning
                 ;; the first next byte is a continuation byte
                 (inst cmp tmp #xC0)
diff --git a/src/code/share-vm.lisp b/src/code/share-vm.lisp
index dfcae8fea..8c7b1a36d 100644
--- a/src/code/share-vm.lisp
+++ b/src/code/share-vm.lisp
@@ -175,7 +175,7 @@
          ,@body)
        ;; Avoid STATICALLY-LINK-CORE from making it harder to redefine.
        (proclaim '(notinline ,name))
-       (let ((fun #',variant))
+       (let ((fun (symbol-function ',variant)))
          (setf (getf ,(package-symbolicate "SB-VM" '+ cpu-feature '-routines+) ',name) fun)
          ;; Redefinition at run-time.
          (when (eq (%fun-name #',name) ',variant)
diff --git a/src/code/x86-64-simd.lisp b/src/code/x86-64-simd.lisp
index 6e2b6d477..a6ec631d1 100644
--- a/src/code/x86-64-simd.lisp
+++ b/src/code/x86-64-simd.lisp
@@ -2296,6 +2296,7 @@
                    ((32-bit-array sap-reg t) (vector-sap string))
                    ((table sap-reg t) (vector-sap table))
                    ((n unsigned-reg) (- length 9))
+                   ((string-length unsigned-reg) (logand (+ (length string) 3) -4))
                    ((tmp unsigned-reg))
                    ((current complex-double-reg))
                    ((next complex-double-reg))
@@ -2365,8 +2366,10 @@
 
                 ;; Remove the gaps left over from using two bytes as one codepoint
                 (inst vpshufb packed packed (ea table tmp))
-
                 (inst xor :dword tmp #xFF0) ;; Count non-continuation bytes
+                (inst cmp string-length 8)
+                (inst jmp :l TAIL-16)
+
                 (inst popcnt :dword tmp tmp)
 
                 ;; Widen
@@ -2376,6 +2379,7 @@
 
                 (inst add byte-index 8)
                 (inst add char-index tmp)
+                (inst sub string-length tmp)
 
                 start
                 (inst cmp byte-index n)
@@ -2383,6 +2387,21 @@
 
                 ;; In the last iteration, did it consume 9 or 8 bytes?
                 (inst vpextrb tmp current 7)
+                (inst jmp ADJUST)
+                TAIL-16
+                (inst and :dword tmp #xF0)
+                (inst popcnt :dword tmp tmp)
+
+                ;; Widen
+                (inst vpmovzxwd combined packed)
+                (inst vmovdqu (ea 32-bit-array char-index 4) combined)
+
+                (inst add byte-index 4)
+                (inst add char-index tmp)
+
+                ;; In the last iteration, did it consume 5 or 4 bytes?
+                (inst vpextrb tmp current 3)
+                ADJUST
                 ;; the last current byte is a leading byte, meaning
                 ;; the first next byte is a continuation byte
                 (inst cmp tmp #xC0)

-----------------------------------------------------------------------


hooks/post-receive
-- 
SBCL