This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
[PATCH][BZ #16004] Check overlaps in strcpy.
- From: OndÅej BÃlka <neleai at seznam dot cz>
- To: libc-alpha at sourceware dot org
- Date: Sat, 5 Oct 2013 15:51:04 +0200
- Subject: [PATCH][BZ #16004] Check overlaps in strcpy.
- Authentication-results: sourceware.org; auth=none
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