* [PATCH v1 0/1] arm64: Fix strrchr() matching of null terminator
@ 2026-05-18 23:43 Edgar E. Iglesias
2026-05-18 23:43 ` [PATCH v1 1/1] " Edgar E. Iglesias
0 siblings, 1 reply; 8+ messages in thread
From: Edgar E. Iglesias @ 2026-05-18 23:43 UTC (permalink / raw)
To: xen-devel
Cc: sstabellini, julien, bertrand.marquis, michal.orzel,
Volodymyr_Babchuk, edgar.iglesias
Found a problem with strrchr("", '\0') returning NULL when searching for the
terminating null byte. This fixes it.
Found while GDB-fuzzing xen/lib helpers under QEMU.
Cheers,
Edgar
Edgar E. Iglesias (1):
arm64: Fix strrchr() matching of null terminator
xen/arch/arm/arm64/lib/strrchr.S | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
--
2.43.0
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH v1 1/1] arm64: Fix strrchr() matching of null terminator 2026-05-18 23:43 [PATCH v1 0/1] arm64: Fix strrchr() matching of null terminator Edgar E. Iglesias @ 2026-05-18 23:43 ` Edgar E. Iglesias 2026-05-19 6:40 ` Jan Beulich 2026-05-19 12:45 ` Andrew Cooper 0 siblings, 2 replies; 8+ messages in thread From: Edgar E. Iglesias @ 2026-05-18 23:43 UTC (permalink / raw) To: xen-devel Cc: sstabellini, julien, bertrand.marquis, michal.orzel, Volodymyr_Babchuk, edgar.iglesias The generic Xen strrchr() implementation returns a pointer to the string terminator when searching for '\0', matching the standard C semantics. The ARM64 assembly version stopped as soon as it loaded the terminator and returned the previous match pointer instead. This made strrchr("", '\0') return NULL. Compare the loaded byte against the requested character before deciding whether to stop at the terminator, so the terminator itself can be returned when it is the requested character. Fixes: 42c4eb6a83 ("xen: arm64: assembly optimised mem* and str*") Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com> --- xen/arch/arm/arm64/lib/strrchr.S | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/xen/arch/arm/arm64/lib/strrchr.S b/xen/arch/arm/arm64/lib/strrchr.S index 81033c0822..31f304b183 100644 --- a/xen/arch/arm/arm64/lib/strrchr.S +++ b/xen/arch/arm/arm64/lib/strrchr.S @@ -30,11 +30,10 @@ FUNC(strrchr) mov x3, #0 and w1, w1, #0xff 1: ldrb w2, [x0], #1 - cbz w2, 2f cmp w2, w1 - b.ne 1b + b.ne 2f sub x3, x0, #1 - b 1b -2: mov x0, x3 +2: cbnz w2, 1b + mov x0, x3 ret END(strrchr) -- 2.43.0 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH v1 1/1] arm64: Fix strrchr() matching of null terminator 2026-05-18 23:43 ` [PATCH v1 1/1] " Edgar E. Iglesias @ 2026-05-19 6:40 ` Jan Beulich 2026-05-19 7:47 ` Julien Grall 2026-05-19 15:24 ` Edgar E. Iglesias 2026-05-19 12:45 ` Andrew Cooper 1 sibling, 2 replies; 8+ messages in thread From: Jan Beulich @ 2026-05-19 6:40 UTC (permalink / raw) To: Edgar E. Iglesias Cc: sstabellini, julien, bertrand.marquis, michal.orzel, Volodymyr_Babchuk, xen-devel On 19.05.2026 01:43, Edgar E. Iglesias wrote: > The generic Xen strrchr() implementation returns a pointer to the string > terminator when searching for '\0', matching the standard C semantics. > > The ARM64 assembly version stopped as soon as it loaded the terminator and > returned the previous match pointer instead. This made strrchr("", '\0') > return NULL. I wonder though: Why would one pass '\0' to strrchr()? If you want to find the end of a string, more efficient (at least in the general case) options exist (strchr(), memchr(), strlen()). > Compare the loaded byte against the requested character before deciding > whether to stop at the terminator, so the terminator itself can be returned > when it is the requested character. Nit: "..., so a pointer to the terminator ...". > Fixes: 42c4eb6a83 ("xen: arm64: assembly optimised mem* and str*") > Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com> Reviewed-by: Jan Beulich <jbeulich@suse.com> However, the function having come from Linux, imo the patch wants to go to Linux (ideally first, but at the very least also). Additionally, looking at strchr() - couldn't the code here be written in a similar way, allowing to get away with just a single branch? (Arm32's pair of functions is also pretty similar in this regard.) Jan > --- a/xen/arch/arm/arm64/lib/strrchr.S > +++ b/xen/arch/arm/arm64/lib/strrchr.S > @@ -30,11 +30,10 @@ FUNC(strrchr) > mov x3, #0 > and w1, w1, #0xff > 1: ldrb w2, [x0], #1 > - cbz w2, 2f > cmp w2, w1 > - b.ne 1b > + b.ne 2f > sub x3, x0, #1 > - b 1b > -2: mov x0, x3 > +2: cbnz w2, 1b > + mov x0, x3 > ret > END(strrchr) ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v1 1/1] arm64: Fix strrchr() matching of null terminator 2026-05-19 6:40 ` Jan Beulich @ 2026-05-19 7:47 ` Julien Grall 2026-05-19 15:28 ` Edgar E. Iglesias 2026-05-19 15:24 ` Edgar E. Iglesias 1 sibling, 1 reply; 8+ messages in thread From: Julien Grall @ 2026-05-19 7:47 UTC (permalink / raw) To: Jan Beulich, Edgar E. Iglesias Cc: sstabellini, bertrand.marquis, michal.orzel, Volodymyr_Babchuk, xen-devel Hi Edgar and Jan, On 19/05/2026 07:40, Jan Beulich wrote: > On 19.05.2026 01:43, Edgar E. Iglesias wrote: >> The generic Xen strrchr() implementation returns a pointer to the string >> terminator when searching for '\0', matching the standard C semantics. >>>> The ARM64 assembly version stopped as soon as it loaded the terminator and >> returned the previous match pointer instead. This made strrchr("", '\0') >> return NULL. > > I wonder though: Why would one pass '\0' to strrchr()? If you want to find > the end of a string, more efficient (at least in the general case) options > exist (strchr(), memchr(), strlen()). +1 I am interested to know the use-case for this change. Is this for compliance or real issue? If the latter, can we add some details. It might also be worth to write a selftest to avoid any regression (in particular if we decide to diverge from Linux). > >> Compare the loaded byte against the requested character before deciding >> whether to stop at the terminator, so the terminator itself can be returned >> when it is the requested character. > > Nit: "..., so a pointer to the terminator ...". > >> Fixes: 42c4eb6a83 ("xen: arm64: assembly optimised mem* and str*") >> Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com> > > Reviewed-by: Jan Beulich <jbeulich@suse.com> > > However, the function having come from Linux, imo the patch wants to go to > Linux (ideally first, but at the very least also). We are trying to keep the core implementation in lib the same as linux (see arch/arm/README.LinuxPrimitives). I would prefer if this is also first committed to Linux and then backported. Cheers, -- Julien Grall ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v1 1/1] arm64: Fix strrchr() matching of null terminator 2026-05-19 7:47 ` Julien Grall @ 2026-05-19 15:28 ` Edgar E. Iglesias 0 siblings, 0 replies; 8+ messages in thread From: Edgar E. Iglesias @ 2026-05-19 15:28 UTC (permalink / raw) To: Julien Grall Cc: Jan Beulich, sstabellini, bertrand.marquis, michal.orzel, Volodymyr_Babchuk, xen-devel On Tue, May 19, 2026 at 08:47:17AM +0100, Julien Grall wrote: > Hi Edgar and Jan, > > On 19/05/2026 07:40, Jan Beulich wrote: > > On 19.05.2026 01:43, Edgar E. Iglesias wrote: > > > The generic Xen strrchr() implementation returns a pointer to the string > > > terminator when searching for '\0', matching the standard C semantics. > >>>> The ARM64 assembly version stopped as soon as it loaded the terminator > and > > > returned the previous match pointer instead. This made strrchr("", '\0') > > > return NULL. > > > > I wonder though: Why would one pass '\0' to strrchr()? If you want to find > > the end of a string, more efficient (at least in the general case) options > > exist (strchr(), memchr(), strlen()). > > +1 I am interested to know the use-case for this change. Is this for > compliance or real issue? If the latter, can we add some details. > > It might also be worth to write a selftest to avoid any regression (in > particular if we decide to diverge from Linux). > > > > > > Compare the loaded byte against the requested character before deciding > > > whether to stop at the terminator, so the terminator itself can be returned > > > when it is the requested character. > > > > Nit: "..., so a pointer to the terminator ...". > > > > > Fixes: 42c4eb6a83 ("xen: arm64: assembly optimised mem* and str*") > > > Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com> > > > > Reviewed-by: Jan Beulich <jbeulich@suse.com> > > > > However, the function having come from Linux, imo the patch wants to go to > > Linux (ideally first, but at the very least also). > > We are trying to keep the core implementation in lib the same as linux (see > arch/arm/README.LinuxPrimitives). I would prefer if this is also first > committed to Linux and then backported. > Sounds good, thanks! ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v1 1/1] arm64: Fix strrchr() matching of null terminator 2026-05-19 6:40 ` Jan Beulich 2026-05-19 7:47 ` Julien Grall @ 2026-05-19 15:24 ` Edgar E. Iglesias 1 sibling, 0 replies; 8+ messages in thread From: Edgar E. Iglesias @ 2026-05-19 15:24 UTC (permalink / raw) To: Jan Beulich Cc: sstabellini, julien, bertrand.marquis, michal.orzel, Volodymyr_Babchuk, xen-devel On Tue, May 19, 2026 at 08:40:54AM +0200, Jan Beulich wrote: > On 19.05.2026 01:43, Edgar E. Iglesias wrote: > > The generic Xen strrchr() implementation returns a pointer to the string > > terminator when searching for '\0', matching the standard C semantics. > > > > The ARM64 assembly version stopped as soon as it loaded the terminator and > > returned the previous match pointer instead. This made strrchr("", '\0') > > return NULL. > > I wonder though: Why would one pass '\0' to strrchr()? If you want to find > the end of a string, more efficient (at least in the general case) options > exist (strchr(), memchr(), strlen()). Right, this came from a fuzzer checking standard strrchr() behavior, not from an explicit end-of-string use case. I agree strlen() or strchr(s, '\0') would be better for that, but strrchr(s, '\0') is valid input, so we should handle it to avoid surprises for existing or future callers. > > > Compare the loaded byte against the requested character before deciding > > whether to stop at the terminator, so the terminator itself can be returned > > when it is the requested character. > > Nit: "..., so a pointer to the terminator ...". Updated, thanks. > > > Fixes: 42c4eb6a83 ("xen: arm64: assembly optimised mem* and str*") > > Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com> > > Reviewed-by: Jan Beulich <jbeulich@suse.com> > > However, the function having come from Linux, imo the patch wants to go to > Linux (ideally first, but at the very least also). Yes, sounds good. > > Additionally, looking at strchr() - couldn't the code here be written in a > similar way, allowing to get away with just a single branch? (Arm32's pair > of functions is also pretty similar in this regard.) Hm, good point. I had a closer look and came up with a couple of options that look better. This one is not quite the same shape as strchr(), but it eliminates one branch and shortens the inner loop from 5 to 4 insns... FUNC(strrchr) mov x3, #0 /* Last match, or NULL */ sub x0, x0, #1 /* For the pre-indexed load */ and w1, w1, #0xff 1: ldrb w2, [x0, #1]! /* Load next byte */ cmp w2, w1 csel x3, x0, x3, eq /* Remember match */ cbnz w2, 1b /* Keep going until NUL */ mov x0, x3 ret END(strrchr) Cheers, Edgar > > Jan > > > --- a/xen/arch/arm/arm64/lib/strrchr.S > > +++ b/xen/arch/arm/arm64/lib/strrchr.S > > @@ -30,11 +30,10 @@ FUNC(strrchr) > > mov x3, #0 > > and w1, w1, #0xff > > 1: ldrb w2, [x0], #1 > > - cbz w2, 2f > > cmp w2, w1 > > - b.ne 1b > > + b.ne 2f > > sub x3, x0, #1 > > - b 1b > > -2: mov x0, x3 > > +2: cbnz w2, 1b > > + mov x0, x3 > > ret > > END(strrchr) > ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v1 1/1] arm64: Fix strrchr() matching of null terminator 2026-05-18 23:43 ` [PATCH v1 1/1] " Edgar E. Iglesias 2026-05-19 6:40 ` Jan Beulich @ 2026-05-19 12:45 ` Andrew Cooper 2026-05-19 16:27 ` Edgar E. Iglesias 1 sibling, 1 reply; 8+ messages in thread From: Andrew Cooper @ 2026-05-19 12:45 UTC (permalink / raw) To: Edgar E. Iglesias, xen-devel Cc: Andrew Cooper, sstabellini, julien, bertrand.marquis, michal.orzel, Volodymyr_Babchuk On 19/05/2026 12:43 am, Edgar E. Iglesias wrote: > The generic Xen strrchr() implementation returns a pointer to the string > terminator when searching for '\0', matching the standard C semantics. > > The ARM64 assembly version stopped as soon as it loaded the terminator and > returned the previous match pointer instead. This made strrchr("", '\0') > return NULL. > > Compare the loaded byte against the requested character before deciding > whether to stop at the terminator, so the terminator itself can be returned > when it is the requested character. > > Fixes: 42c4eb6a83 ("xen: arm64: assembly optimised mem* and str*") > Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com> > --- > xen/arch/arm/arm64/lib/strrchr.S | 7 +++---- > 1 file changed, 3 insertions(+), 4 deletions(-) A couple of tangential things. This file was inherited from Linux. Does the same bug need fixing there? What about the arm32 side? Looking at your example, it surely wasn't actually as simple as strrchr("", '\0') ? I'd expect the optimiser to be able to turn that into a constant and not call out to the library implementation. Elsewhere, I've created xen/common/bitops.c to be CONFIG_SELF_TESTS for the bit operations including the arch-optimised variations, because they're subtle and easy to get wrong. This looks like it's worth doing the same for the bits of libc we implement. ~Andrew ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v1 1/1] arm64: Fix strrchr() matching of null terminator 2026-05-19 12:45 ` Andrew Cooper @ 2026-05-19 16:27 ` Edgar E. Iglesias 0 siblings, 0 replies; 8+ messages in thread From: Edgar E. Iglesias @ 2026-05-19 16:27 UTC (permalink / raw) To: Andrew Cooper Cc: xen-devel, sstabellini, julien, bertrand.marquis, michal.orzel, Volodymyr_Babchuk On Tue, May 19, 2026 at 01:45:37PM +0100, Andrew Cooper wrote: > On 19/05/2026 12:43 am, Edgar E. Iglesias wrote: > > The generic Xen strrchr() implementation returns a pointer to the string > > terminator when searching for '\0', matching the standard C semantics. > > > > The ARM64 assembly version stopped as soon as it loaded the terminator and > > returned the previous match pointer instead. This made strrchr("", '\0') > > return NULL. > > > > Compare the loaded byte against the requested character before deciding > > whether to stop at the terminator, so the terminator itself can be returned > > when it is the requested character. > > > > Fixes: 42c4eb6a83 ("xen: arm64: assembly optimised mem* and str*") > > Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com> > > --- > > xen/arch/arm/arm64/lib/strrchr.S | 7 +++---- > > 1 file changed, 3 insertions(+), 4 deletions(-) > > A couple of tangential things. > > This file was inherited from Linux. Does the same bug need fixing > there? What about the arm32 side? Yes, I'll have a look at Linux. Arm32 looks fine to me. > > Looking at your example, it surely wasn't actually as simple as > strrchr("", '\0') ? I'd expect the optimiser to be able to turn that > into a constant and not call out to the library implementation. > We ran into this while exploring a new QEMU based test framework, we had it do some fuzzing and it tripped over this. > Elsewhere, I've created xen/common/bitops.c to be CONFIG_SELF_TESTS for > the bit operations including the arch-optimised variations, because > they're subtle and easy to get wrong. This looks like it's worth doing > the same for the bits of libc we implement. > Yes, that looks like a good fit, thanks. Cheers, Edgar ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2026-05-19 16:27 UTC | newest] Thread overview: 8+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-05-18 23:43 [PATCH v1 0/1] arm64: Fix strrchr() matching of null terminator Edgar E. Iglesias 2026-05-18 23:43 ` [PATCH v1 1/1] " Edgar E. Iglesias 2026-05-19 6:40 ` Jan Beulich 2026-05-19 7:47 ` Julien Grall 2026-05-19 15:28 ` Edgar E. Iglesias 2026-05-19 15:24 ` Edgar E. Iglesias 2026-05-19 12:45 ` Andrew Cooper 2026-05-19 16:27 ` Edgar E. Iglesias
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.