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