Bug 25824 - Abnormal function of strnlen in aarch64
Summary: Abnormal function of strnlen in aarch64
Status: RESOLVED FIXED
Alias: None
Product: glibc
Classification: Unclassified
Component: libc (show other bugs)
Version: 2.31
: P2 normal
Target Milestone: 2.32
Assignee: Not yet assigned to anyone
URL:
Keywords:
: 25825 (view as bug list)
Depends on:
Blocks:
 
Reported: 2020-04-15 13:25 UTC by Yan Zhu
Modified: 2020-07-31 09:12 UTC (History)
3 users (show)

See Also:
Host: aarch64_be-*-*
Target:
Build:
Last reconfirmed: 2020-05-15 00:00:00
fweimer: security-


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Yan Zhu 2020-04-15 13:25:39 UTC
In aarch64, the strnlen interface has a problem when the string length is more than 9
Comment 1 Andreas Schwab 2020-04-15 13:32:52 UTC
*** Bug 25825 has been marked as a duplicate of this bug. ***
Comment 2 Yan Zhu 2020-04-15 14:13:24 UTC
There is a testcase.

#include <stdio.h>
#include <string.h>

void init_base(char *base, int len)
{
	int i;
	for (i = 0; i < len; i++) {
		base[i] = 'x';
	}
	base[len] = '\0';
}

int main(int argc, char *argv[])
{
	int i;
	char base[1000];
	char buff[1000];
	size_t n;
	
	for (i = 1; i < 1000; i++) {
		memset(buff, 0, 1000);
		init_base(base, i);		
		n = strnlen(base, 1000);      
		if ( i == n )
			printf("size=%d is equel\n", i);
		else
			printf("size=%d is not equel%s\n", i);
	}

    return 0;
}


The execution log is as follows:

arm64be /tmp # ./arm64be-test_strnlen
size=1 is equel
size=2 is equel
size=3 is equel
size=4 is equel
size=5 is equel
size=6 is equel
size=7 is equel
size=8 is equel
size=9 is not equel
size=10 is not equel
size=11 is not equel
size=12 is not equel
size=13 is not equel
Comment 3 Yan Zhu 2020-04-15 14:13:44 UTC
There is a testcase.

#include <stdio.h>
#include <string.h>

void init_base(char *base, int len)
{
	int i;
	for (i = 0; i < len; i++) {
		base[i] = 'x';
	}
	base[len] = '\0';
}

int main(int argc, char *argv[])
{
	int i;
	char base[1000];
	char buff[1000];
	size_t n;
	
	for (i = 1; i < 1000; i++) {
		memset(buff, 0, 1000);
		init_base(base, i);		
		n = strnlen(base, 1000);      
		if ( i == n )
			printf("size=%d is equel\n", i);
		else
			printf("size=%d is not equel%s\n", i);
	}

    return 0;
}


The execution log is as follows:

arm64be /tmp # ./arm64be-test_strnlen
size=1 is equel
size=2 is equel
size=3 is equel
size=4 is equel
size=5 is equel
size=6 is equel
size=7 is equel
size=8 is equel
size=9 is not equel
size=10 is not equel
size=11 is not equel
size=12 is not equel
size=13 is not equel
Comment 4 Andreas Schwab 2020-04-15 14:35:06 UTC
This does not fail on little-endian aarch64.
Comment 5 Wilco 2020-04-15 16:53:53 UTC
(In reply to Yan Zhu from comment #0)
> In aarch64, the strnlen interface has a problem when the string length is
> more than 9

In big-endian? Yes that rev64 only swaps bytes in each 64-bit word, so you still need to swap the index in mov data1, datav2.d[0].

This sequence comes from strlen_asimd.S originally. And now strcpy.S has it too.
Comment 6 Wilco 2020-05-11 15:33:04 UTC
(In reply to Wilco from comment #5)
> (In reply to Yan Zhu from comment #0)
> > In aarch64, the strnlen interface has a problem when the string length is
> > more than 9
> 
> In big-endian? Yes that rev64 only swaps bytes in each 64-bit word, so you
> still need to swap the index in mov data1, datav2.d[0].
> 
> This sequence comes from strlen_asimd.S originally. And now strcpy.S has it
> too.

Btw I have a faster strnlen I'll post soon that will fix one of the 3 cases.
Comment 7 Szabolcs Nagy 2020-05-15 13:22:29 UTC
bigendian strnlen, strcpy (and stpcpy) are fixed for glibc 2.32 in

commit 59b64f9cbbf1e98c6d187873de6c363994aee19d
Author:     Lexi Shao <shaolexi@huawei.com>
AuthorDate: 2020-05-15 18:48:59 +0800

    aarch64: fix strcpy and strnlen for big-endian [BZ #25824]

falkor and kunpeng920 specific strlen_asimd still needs to be fixed.
Comment 8 Sourceware Commits 2020-07-17 14:07:57 UTC
The master branch has been updated by Wilco Dijkstra <wilco@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=f46ef33ad134bec7ac992f28ee4b8b0614590e3e

commit f46ef33ad134bec7ac992f28ee4b8b0614590e3e
Author: Wilco Dijkstra <wdijkstr@arm.com>
Date:   Fri Jul 17 14:09:36 2020 +0100

    AArch64: Improve strlen_asimd performance (bug 25824)
    
    Optimize strlen using a mix of scalar and SIMD code.  On modern micro
    architectures large strings are 2.6 times faster than existing
    strlen_asimd and 35% faster than the new MTE version of strlen.
    
    On a random strlen benchmark using small sizes the speedup is 7% vs
    strlen_asimd and 40% vs the MTE strlen.  This fixes the main strlen
    regressions on Cortex-A53 and other cores with a simple Neon unit.
    
    Rename __strlen_generic to __strlen_mte, and select strlen_asimd when
    MTE is not enabled (this is waiting on support for a HWCAP_MTE bit).
    
    This fixes big-endian bug 25824. Passes GLIBC regression tests.
    
    Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
Comment 9 Szabolcs Nagy 2020-07-17 14:56:12 UTC
fixed for 2.32