From c428218fd402c8eae74b51b02d31733b11a7ea86 Mon Sep 17 00:00:00 2001 From: Mark Atwood Date: Wed, 15 Jul 2026 12:15:01 -0700 Subject: [PATCH] fix: signed-shift UB in slhdsakey_base_2b The FORS digest accumulator 'total' was a signed int and is never masked, so 'total << 8' overflows INT32_MAX from the 4th consumed byte onward (C11 6.5.7p4 undefined behavior). Declare it word32. Output is unchanged: overflowed high bits were already discarded by the mask. Reproduced with -fsanitize=shift during the standard SLH-DSA KAT test; clean after this change. --- wolfcrypt/src/wc_slhdsa.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/wolfcrypt/src/wc_slhdsa.c b/wolfcrypt/src/wc_slhdsa.c index c64b006a52b..cd6955dcd13 100644 --- a/wolfcrypt/src/wc_slhdsa.c +++ b/wolfcrypt/src/wc_slhdsa.c @@ -1709,7 +1709,10 @@ static void slhdsakey_base_2b(const byte* x, byte b, byte outLen, word16* baseb) int j; int i = 0; int bits = 0; - int total = 0; + /* total accumulates unmasked via << 8 and must be unsigned: a signed + * type overflows from the 4th consumed byte (UB). High bits are + * discarded by mask, so the output is unaffected. */ + word32 total = 0; word16 mask = (word16)((1 << b) - 1); for (j = 0; j < outLen; j++) {