[PATCH] power8: fix read past array bounds in strncasecmp (bug 34683)
Adhemerval Zanella Netto
adhemerval.zanella@linaro.org
Tue Sep 29 14:05:05 GMT 2026
On 29/09/26 10:58, Andreas Schwab wrote:
> Move the load of the characters to the top of the loops, so that they
> occur after the bounds check for the strncasecmp implementation. Amend
> the page test for strncasecmp to also test with non-null-terminated arrays
> that trigger this bug.
We have two slight different patches that fix the same issue [1]. Which should
we use?
[1] https://patchwork.sourceware.org/project/glibc/patch/20260929112822.2099581-1-smonga@linux.ibm.com/
> ---
> string/test-strncasecmp.c | 16 ++++++++++++++++
> sysdeps/powerpc/powerpc64/power8/strcasecmp.S | 14 ++++++--------
> 2 files changed, 22 insertions(+), 8 deletions(-)
>
> diff --git a/string/test-strncasecmp.c b/string/test-strncasecmp.c
> index 6b00113e66..3fced4202b 100644
> --- a/string/test-strncasecmp.c
> +++ b/string/test-strncasecmp.c
> @@ -199,6 +199,22 @@ do_page_tests (void)
> exp_result);
> }
> }
> +
> + /* Like strncmp, the arrays passed to strncasecmp are not required to be
> + null-terminated. Check that the implementations do not read beyond
> + the end of the arrays. */
> +
> + s1[maxoffset - 1] = 'a';
> + s2[maxoffset - 1] = 'a';
> + for (size_t off1 = 0; off1 < maxoffset; off1++)
> + {
> + for (size_t off2 = 0; off2 < maxoffset; off2++)
> + {
> + size_t off_max = off1 < off2 ? off2 : off1;
> + FOR_EACH_IMPL (impl, 0)
> + check_result (impl, s1 + off1, s2 + off2, maxoffset - off_max, 0);
> + }
> + }
> }
>
> static void
> diff --git a/sysdeps/powerpc/powerpc64/power8/strcasecmp.S b/sysdeps/powerpc/powerpc64/power8/strcasecmp.S
> index 3c45e9ea50..22db297855 100644
> --- a/sysdeps/powerpc/powerpc64/power8/strcasecmp.S
> +++ b/sysdeps/powerpc/powerpc64/power8/strcasecmp.S
> @@ -355,8 +355,6 @@ L(bytebybyte):
> offset and string descriptors are only updated in the end
> of loop unrolling. */
> ld rLOC, LOCALE_CTYPE_TOLOWER(rLOC)
> - lbz rCHAR1, 0(rSTR1) /* Load char from s1 */
> - lbz rCHAR2, 0(rSTR2) /* Load char from s2 */
> #ifdef USE_AS_STRNCASECMP
> rldicl rTMP, r5, 62, 2
> cmpdi cr7, rTMP, 0
> @@ -364,6 +362,8 @@ L(bytebybyte):
> mtctr rTMP
> #endif
> L(loop):
> + lbz rCHAR1, 0(rSTR1) /* Load char from s1 */
> + lbz rCHAR2, 0(rSTR2) /* Load char from s2 */
> cmpdi rCHAR1, 0 /* *s1 == '\0' ? */
> sldi rADDR1, rCHAR1, 2 /* Calculate address for tolower(*s1) */
> sldi rADDR2, rCHAR2, 2 /* Calculate address for tolower(*s2) */
> @@ -404,13 +404,11 @@ L(loop):
> lwzx rLWR2, rLOC, rADDR2
> cmpw cr1, rLWR1, rLWR2
> crorc 4*cr1+eq,eq,4*cr1+eq
> - beq cr1, L(done)
> - lbz rCHAR1, 0(rSTR1) /* Load char from s1 */
> - lbz rCHAR2, 0(rSTR2) /* Load char from s2 */
> #ifdef USE_AS_STRNCASECMP
> + beq cr1, L(done)
> bdnz L(loop)
> #else
> - b L(loop)
> + bne cr1, L(loop)
> #endif
> #ifdef USE_AS_STRNCASECMP
> L(lessthan4):
> @@ -419,6 +417,8 @@ L(lessthan4):
> beq cr7, L(retnull)
> mtctr r5
> L(loop1):
> + lbz rCHAR1, 0(rSTR1)
> + lbz rCHAR2, 0(rSTR2)
> cmpdi rCHAR1, 0
> sldi rADDR1, rCHAR1, 2
> sldi rADDR2, rCHAR2, 2
> @@ -429,8 +429,6 @@ L(loop1):
> beq cr1, L(done)
> addi rSTR1, rSTR1, 1
> addi rSTR2, rSTR2, 1
> - lbz rCHAR1, 0(rSTR1)
> - lbz rCHAR2, 0(rSTR2)
> bdnz L(loop1)
> #endif
> L(done):
More information about the Libc-alpha
mailing list