[PATCH v3] riscv: lib: Fix ZBB strnlen wrap-around regression on huge counts
Qingfang Deng
qingfang.deng at linux.dev
Mon Sep 14 20:43:58 PDT 2026
Hi,
On 2026/9/14 16:21, shao.mingyin at zte.com.cn wrote:
> diff --git a/arch/riscv/lib/strnlen.S b/arch/riscv/lib/strnlen.S
> index a8911605c248..528ee7995969 100644
> --- a/arch/riscv/lib/strnlen.S
> +++ b/arch/riscv/lib/strnlen.S
> @@ -67,7 +67,7 @@ strnlen_zbb:
> * a1 - Max length of string
> *
> * Clobbers
> - * t0, t1, t2, t3, t4
> + * t0, t1, t2, t3, t4, t5
> */
>
> /* If maxlen is 0, return 0. */
> @@ -87,9 +87,22 @@ strnlen_zbb:
> * Aligned boundary. Use the address of the last valid byte
> * (s + count - 1) to avoid loading a word past the count
> * boundary in the loop below. count == 0 is handled above.
> + *
> + * Saturate the boundary when s + count wraps around (very large
> + * counts, e.g. SIZE_MAX passed by FORTIFY strcat/strlcat with a
> + * destination whose size is unknown at compile time). Without
> + * this, the wrapped boundary lands before s and the pre-loop
> + * guard below always exits, returning a truncated length.
> + * Saturating makes the scan equivalent to strlen().
> + *
> + * Keep the saturation branchless so that the normal path does
> + * not carry a taken branch that could be mispredicted.
> */
> add t4, a0, a1
> addi t4, t4, -1
> + sltu t5, t4, a0 /* Did s + count wrap around? */
> + sub t5, zero, t5 /* -1 if wrapped, 0 otherwise */
> + or t4, t4, t5 /* Saturate to the top of the address space */
You can save one instruction by using Zbb minu instruction.
Equation: saturating_add(s, count - 1) == s + min(count - 1, ~s), given
that count >= 1.
addi t4, a1, -1
not t1, a0
minu t4, t4, t1
add t4, a0, t4
> andi t4, t4, -SZREG
>
> /* Get the first word. */
Kind regards,
Qingfang
More information about the linux-riscv
mailing list