This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH][BZ #16004] Check overlaps in strcpy.


Hi,

This adds overlap checks to strcpy and considerably improves performance
as used implementation did not use sse.

I generated new implementation by compiling folling c file and replacing
rdx argument by rcx.

char *__chk_fail ();
char *strcpy_chk (char *dest, char *src, char *to)
{
  char *t = stpcpy (dest, src);
  if (dest > src && src + (t - dest) > dest)
    return __chk_fail ();
  if (dest < src && t > src)
    return __chk_fail ();
  if (t > to)
    return __chk_fail ();
  return dest;
}

Also is omitting strcat from checked implementations intentional?

OK to commit?

	* sysdeps/x86_64/strcpy_chk.S: Optimize implementation and add
	overlap checks.

---
 sysdeps/x86_64/strcpy_chk.S | 231 +++++++++++---------------------------------
 1 file changed, 54 insertions(+), 177 deletions(-)

diff --git a/sysdeps/x86_64/strcpy_chk.S b/sysdeps/x86_64/strcpy_chk.S
index 7e171de..114c21b 100644
--- a/sysdeps/x86_64/strcpy_chk.S
+++ b/sysdeps/x86_64/strcpy_chk.S
@@ -1,8 +1,5 @@
 /* strcpy/stpcpy checking implementation for x86-64.
-   Copyright (C) 2002-2013 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Andreas Jaeger <aj@suse.de>, 2002.
-   Adopted into checking version by Jakub Jelinek <jakub@redhat.com>.
+   Copyright (C) 2013 Free Software Foundation, Inc.
 
    The GNU C Library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
@@ -27,182 +24,62 @@
 
 	.text
 ENTRY (STRCPY_CHK)
-	movq	%rsi, %rcx	/* Source register. */
-	andl	$7, %ecx	/* mask alignment bits */
-#ifndef USE_AS_STPCPY_CHK
-	movq	%rdi, %r10	/* Duplicate destination pointer.  */
+	pushq	%r12
+	.cfi_def_cfa_offset 16
+	.cfi_offset 12, -16
+	movq	%rcx, %r12
+	pushq	%rbp
+	.cfi_def_cfa_offset 24
+	.cfi_offset 6, -24
+	movq	%rsi, %rbp
+	pushq	%rbx
+	.cfi_def_cfa_offset 32
+	.cfi_offset 3, -32
+	movq	%rdi, %rbx
+	call	stpcpy
+#ifdef USE_AS_STPCPY_CHK
+	movq	%rax, %r8
 #endif
-	jz 5f			/* aligned => start loop */
-
-	cmpq	$8, %rdx	/* Check if only few bytes left in
-				   destination.  */
-	jb	50f
-
-	subq	$8, %rcx	/* We need to align to 8 bytes.  */
-	addq	%rcx, %rdx	/* Subtract count of stored bytes
-				   in the cycle below from destlen.  */
-
-	/* Search the first bytes directly.  */
-0:
-	movb	(%rsi), %al	/* Fetch a byte */
-	testb	%al, %al	/* Is it NUL? */
-	movb	%al, (%rdi)	/* Store it */
-	jz	4f		/* If it was NUL, done! */
-	incq	%rsi
-	incq	%rdi
-	incl	%ecx
-	jnz	0b
-
-5:
-	movq $0xfefefefefefefeff,%r8
-	cmpq	$32, %rdx	/* Are there enough bytes in destination
-				   for the next unrolled round?  */
-	jb	60f		/* If not, avoid the unrolled loop.  */
-
-	/* Now the sources is aligned.  Unfortunatly we cannot force
-	   to have both source and destination aligned, so ignore the
-	   alignment of the destination.  */
-	.p2align 4
-1:
-	/* 1st unroll.  */
-	movq	(%rsi), %rax	/* Read double word (8 bytes).  */
-	addq	$8, %rsi	/* Adjust pointer for next word.  */
-	movq	%rax, %r9	/* Save a copy for NUL finding.  */
-	addq	%r8, %r9	/* add the magic value to the word.  We get
-				   carry bits reported for each byte which
-				   is *not* 0 */
-	jnc	3f		/* highest byte is NUL => return pointer */
-	xorq	%rax, %r9	/* (word+magic)^word */
-	orq	%r8, %r9	/* set all non-carry bits */
-	incq	%r9		/* add 1: if one carry bit was *not* set
-				   the addition will not result in 0.  */
-
-	jnz	3f		/* found NUL => return pointer */
-
-	movq	%rax, (%rdi)	/* Write value to destination.  */
-	addq	$8, %rdi	/* Adjust pointer.  */
-
-	/* 2nd unroll.  */
-	movq	(%rsi), %rax	/* Read double word (8 bytes).  */
-	addq	$8, %rsi	/* Adjust pointer for next word.  */
-	movq	%rax, %r9	/* Save a copy for NUL finding.  */
-	addq	%r8, %r9	/* add the magic value to the word.  We get
-				   carry bits reported for each byte which
-				   is *not* 0 */
-	jnc	3f		/* highest byte is NUL => return pointer */
-	xorq	%rax, %r9	/* (word+magic)^word */
-	orq	%r8, %r9	/* set all non-carry bits */
-	incq	%r9		/* add 1: if one carry bit was *not* set
-				   the addition will not result in 0.  */
-
-	jnz	3f		/* found NUL => return pointer */
-
-	movq	%rax, (%rdi)	/* Write value to destination.  */
-	addq	$8, %rdi	/* Adjust pointer.  */
-
-	/* 3rd unroll.  */
-	movq	(%rsi), %rax	/* Read double word (8 bytes).  */
-	addq	$8, %rsi	/* Adjust pointer for next word.  */
-	movq	%rax, %r9	/* Save a copy for NUL finding.  */
-	addq	%r8, %r9	/* add the magic value to the word.  We get
-				   carry bits reported for each byte which
-				   is *not* 0 */
-	jnc	3f		/* highest byte is NUL => return pointer */
-	xorq	%rax, %r9	/* (word+magic)^word */
-	orq	%r8, %r9	/* set all non-carry bits */
-	incq	%r9		/* add 1: if one carry bit was *not* set
-				   the addition will not result in 0.  */
-
-	jnz	3f		/* found NUL => return pointer */
-
-	movq	%rax, (%rdi)	/* Write value to destination.  */
-	addq	$8, %rdi	/* Adjust pointer.  */
-
-	/* 4th unroll.  */
-	movq	(%rsi), %rax	/* Read double word (8 bytes).  */
-	addq	$8, %rsi	/* Adjust pointer for next word.  */
-	movq	%rax, %r9	/* Save a copy for NUL finding.  */
-	addq	%r8, %r9	/* add the magic value to the word.  We get
-				   carry bits reported for each byte which
-				   is *not* 0 */
-	jnc	3f		/* highest byte is NUL => return pointer */
-	xorq	%rax, %r9	/* (word+magic)^word */
-	orq	%r8, %r9	/* set all non-carry bits */
-	incq	%r9		/* add 1: if one carry bit was *not* set
-				   the addition will not result in 0.  */
-
-	jnz	3f		/* found NUL => return pointer */
-
-	subq	$32, %rdx	/* Adjust destlen.  */
-	movq	%rax, (%rdi)	/* Write value to destination.  */
-	addq	$8, %rdi	/* Adjust pointer.  */
-	cmpq	$32, %rdx	/* Are there enough bytes in destination
-				   for the next unrolled round?  */
-	jae	1b		/* Next iteration.  */
-
-60:
-	cmpq	$8, %rdx	/* Are there enough bytes in destination
-				   for the next unrolled round?  */
-	jb	50f		/* Now, copy and check byte by byte.  */
-
-	movq	(%rsi), %rax	/* Read double word (8 bytes).  */
-	addq	$8, %rsi	/* Adjust pointer for next word.  */
-	movq	%rax, %r9	/* Save a copy for NUL finding.  */
-	addq	%r8, %r9	/* add the magic value to the word.  We get
-				   carry bits reported for each byte which
-				   is *not* 0 */
-	jnc	3f		/* highest byte is NUL => return pointer */
-	xorq	%rax, %r9	/* (word+magic)^word */
-	orq	%r8, %r9	/* set all non-carry bits */
-	incq	%r9		/* add 1: if one carry bit was *not* set
-				   the addition will not result in 0.  */
-
-	jnz	3f		/* found NUL => return pointer */
-
-	subq	$8, %rdx	/* Adjust destlen.  */
-	movq	%rax, (%rdi)	/* Write value to destination.  */
-	addq	$8, %rdi	/* Adjust pointer.  */
-	jmp	60b		/* Next iteration.  */
-
-	/* Do the last few bytes. %rax contains the value to write.
-	   The loop is unrolled twice.  */
-	.p2align 4
-3:
-	/* Note that stpcpy needs to return with the value of the NUL
-	   byte.  */
-	movb	%al, (%rdi)	/* 1st byte.  */
-	testb	%al, %al	/* Is it NUL.  */
-	jz	4f		/* yes, finish.  */
-	incq	%rdi		/* Increment destination.  */
-	movb	%ah, (%rdi)	/* 2nd byte.  */
-	testb	%ah, %ah	/* Is it NUL?.  */
-	jz	4f		/* yes, finish.  */
-	incq	%rdi		/* Increment destination.  */
-	shrq	$16, %rax	/* Shift...  */
-	jmp	3b		/* and look at next two bytes in %rax.  */
-
-51:
-	/* Search the bytes directly, checking for overflows.  */
-	incq	%rsi
-	incq	%rdi
-	decq	%rdx
-	jz	HIDDEN_JUMPTARGET (__chk_fail)
-52:
-	movb	(%rsi), %al	/* Fetch a byte */
-	testb	%al, %al	/* Is it NUL? */
-	movb	%al, (%rdi)	/* Store it */
-	jnz	51b		/* If it was NUL, done! */
-4:
+	cmpq	%rbp, %rbx
+	jbe	.L2
+	movq	%rax, %rdx
+	subq	%rbx, %rdx
+	addq	%rbp, %rdx
+	cmpq	%rdx, %rbx
+	jb	L(fail)
+.L2:
+	cmpq	%rax, %rbp
+	jb	.L11
+.L5:
+	cmpq	%r12, %rax
+	ja	L(fail)
+	movq	%rbx, %rax
+	popq	%rbx
+	.cfi_remember_state
+	.cfi_def_cfa_offset 24
+	popq	%rbp
+	.cfi_def_cfa_offset 16
+	popq	%r12
+	.cfi_def_cfa_offset 8
 #ifdef USE_AS_STPCPY_CHK
-	movq	%rdi, %rax	/* Destination is return value.  */
-#else
-	movq	%r10, %rax	/* Source is return value.  */
+	movq	%r8, %rax
 #endif
-	retq
-
-50:
-	testq	%rdx, %rdx
-	jnz	52b
+	ret
+
+	.p2align 3
+.L11:
+	.cfi_restore_state
+	cmpq	%rbp, %rbx
+	jae	.L5
+
+	.p2align 3
+L(fail):
+	popq	%rbx
+	.cfi_def_cfa_offset 24
+	popq	%rbp
+	.cfi_def_cfa_offset 16
+	popq	%r12
+	.cfi_def_cfa_offset 8
 	jmp	HIDDEN_JUMPTARGET (__chk_fail)
 
 END (STRCPY_CHK)
-- 
1.8.4.rc3


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]