[patch] strncpy.S bug on ia64
Randolph Chung
randolph@tausq.org
Mon Dec 2 23:35:00 GMT 2002
> - Test case?
>
> - The formatting of the ChangeLog entry is wrong.
ok, second try. bootstrapped and tested against 2.3.1 (Debian).
2002-11-19 Kenneth W. Chen <kenneth.w.chen@intel.com>
* sysdeps/ia64/strncpy.S: (strncpy) initialize ar.ec,
ec is not guaranteed to be zero upon function entry;
fix segfault in recovery 4 section when src length
ends exactly at a page boundary, and there are no
mapping after that page.
2002-12-02 Randolph Chung <tausq@debian.org>
* string/bug-strncpy.c: test case for strncpy segfault
* string/Makefile: add bug-strncpy test case
--- glibc/sysdeps/ia64/strncpy.S.orig Tue Nov 19 10:22:01 2002
+++ glibc/sysdeps/ia64/strncpy.S Tue Nov 19 10:29:21 2002
@@ -63,6 +63,7 @@
mov saved_pr = pr // save the predicate registers
.save ar.lc, saved_lc
mov saved_lc = ar.lc // save the loop counter
+ mov ar.ec = 0
.body
cmp.geu p6, p5 = 24, in2
(p6) br.cond.spnt .short_len
@@ -221,7 +222,9 @@
ld8 r[MEMLAT] = [tmp]
br.cond.sptk .back3
.recovery4:
+ cmp.eq p8,p9=0,len
add tmp = -MEMLAT * 8, src ;;
- ld8 r[MEMLAT - 1] = [tmp]
+(p8) mov r[MEMLAT - 1] = r0
+(p9) ld8 r[MEMLAT - 1] = [tmp]
br.cond.sptk .back4
END(strncpy)
--- glibc/string/Makefile.orig 2002-12-02 22:26:22.000000000 -0800
+++ glibc/string/Makefile 2002-12-02 22:27:46.000000000 -0800
@@ -48,7 +48,7 @@
tests := tester inl-tester noinl-tester testcopy test-ffs \
tst-strlen stratcliff tst-svc tst-inlcall \
bug-strncat1 bug-strspn1 bug-strpbrk1 tst-bswap \
- tst-strtok tst-strxfrm bug-strcoll1
+ tst-strtok tst-strxfrm bug-strcoll1 bug-strncpy
distribute := memcopy.h pagecopy.h tst-svc.expect
--- glibc/string/bug-strncpy.c 2002-12-02 23:35:42.000000000 -0800
+++ glibc/string/bug-strncpy.c 2002-12-02 23:35:42.000000000 -0800
@@ -0,0 +1,81 @@
+/* Test case from Kenneth W Chen <kenneth.w.chen@intel.com>; adapted
+ * for glibc by Randolph Chung <tausq@debian.org>
+ *
+ * Tests the case where the src length ends at a page boundary
+ * and the next page is not mapped
+ */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/shm.h>
+#include <signal.h>
+
+#define MCPYSIZE 2048
+#define SHMSIZE (MCPYSIZE * sizeof(long))
+static int shmid = -1;
+static char* shmaddr;
+
+void sighandler(int sig)
+{
+ if (shmid != -1)
+ {
+ shmdt(shmaddr);
+ shmctl(shmid, IPC_RMID, NULL);
+ }
+
+ exit(1);
+}
+
+int main(int argc, char **argv)
+{
+ long buffer[MCPYSIZE];
+ int i, j, k, x;
+ char *src, *dst;
+ size_t len;
+
+ shmid = shmget(1, SHMSIZE, IPC_CREAT|SHM_R|SHM_W);
+ shmaddr = (char*) shmat(shmid, NULL, SHM_RND);
+
+ signal(SIGSEGV, sighandler);
+
+ for (i=0; i<SHMSIZE; i++)
+ shmaddr[i] = i;
+
+ dst = (char*) buffer;
+
+ for (k=1; k<1000; k+=1) {
+ for (i=0; i<8; i++) {
+ for (j=0; j<8; j++) {
+
+ src = (char*) shmaddr + SHMSIZE - k - i;
+ dst = (char*) buffer + j;
+ len = k;
+
+ // printf("dst %p src %p n %4d\n", dst, src, len);
+ strncpy(dst, src, len);
+
+ for (x=0; x<len; x++) {
+ if (src[x] == 0) break;
+ if ( dst[x] != src[x] ) {
+ unsigned long * l_src = (unsigned long*) ((unsigned long) &src[x] & -8);
+ unsigned long * l_dst = (unsigned long*) ((unsigned long) &dst[x] & -8);
+
+ printf("error\t");
+ printf("dst %p src %p n %4zd\n", dst, src, len);
+
+ printf("%d: %x %x\n", x, dst[x], src[x]);
+
+ printf("%d: %16lx %16lx\n", x, *l_dst, *l_src);
+ exit(1);
+ }
+ }
+ } /* for (j=0 ... */
+ } /* for (i=0 ... */
+ } /* for (k=0 ... */
+
+ shmdt(shmaddr);
+ shmctl(shmid, IPC_RMID, NULL);
+
+ return 0;
+}
+
--
Randolph Chung
Debian GNU/Linux Developer, hppa/ia64 ports
http://www.tausq.org/
More information about the Libc-alpha
mailing list