diff options
Diffstat (limited to 'sysdeps')
27 files changed, 1280 insertions, 3 deletions
diff --git a/sysdeps/generic/memcpy_chk.c b/sysdeps/generic/memcpy_chk.c new file mode 100644 index 0000000000..638cd0e4fb --- /dev/null +++ b/sysdeps/generic/memcpy_chk.c @@ -0,0 +1,66 @@ +/* Copy memory to memory until the specified number of bytes + has been copied with error checking. Overlap is NOT handled correctly. + Copyright (C) 1991, 1997, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Torbjorn Granlund (tege@sics.se). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <string.h> +#include <memcopy.h> +#include <pagecopy.h> + +void * +__memcpy_chk (dstpp, srcpp, len, dstlen) + void *dstpp; + const void *srcpp; + size_t len; + size_t dstlen; +{ + if (__builtin_expect (dstlen < len, 0)) + __chk_fail (); + + unsigned long int dstp = (long int) dstpp; + unsigned long int srcp = (long int) srcpp; + + /* Copy from the beginning to the end. */ + + /* If there not too few bytes to copy, use word copy. */ + if (len >= OP_T_THRES) + { + /* Copy just a few bytes to make DSTP aligned. */ + len -= (-dstp) % OPSIZ; + BYTE_COPY_FWD (dstp, srcp, (-dstp) % OPSIZ); + + /* Copy whole pages from SRCP to DSTP by virtual address manipulation, + as much as possible. */ + + PAGE_COPY_FWD_MAYBE (dstp, srcp, len, len); + + /* Copy from SRCP to DSTP taking advantage of the known alignment of + DSTP. Number of bytes remaining is put in the third argument, + i.e. in LEN. This number may vary from machine to machine. */ + + WORD_COPY_FWD (dstp, srcp, len, len); + + /* Fall out and copy the tail. */ + } + + /* There are just a few bytes to copy. Use byte memory operations. */ + BYTE_COPY_FWD (dstp, srcp, len); + + return dstpp; +} diff --git a/sysdeps/generic/memmove_chk.c b/sysdeps/generic/memmove_chk.c new file mode 100644 index 0000000000..f3b74d23d9 --- /dev/null +++ b/sysdeps/generic/memmove_chk.c @@ -0,0 +1,98 @@ +/* Copy memory to memory until the specified number of bytes + has been copied with error checking. Overlap is handled correctly. + Copyright (C) 1991,1995,1996,1997,2003,2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Torbjorn Granlund (tege@sics.se). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <string.h> +#include <memcopy.h> +#include <pagecopy.h> + +void * +__memmove_chk (dest, src, len, destlen) + void *dest; + const void *src; + size_t len; + size_t destlen; +{ + if (__builtin_expect (destlen < len, 0)) + __chk_fail (); + + unsigned long int dstp = (long int) dest; + unsigned long int srcp = (long int) src; + + /* This test makes the forward copying code be used whenever possible. + Reduces the working set. */ + if (dstp - srcp >= len) /* *Unsigned* compare! */ + { + /* Copy from the beginning to the end. */ + + /* If there not too few bytes to copy, use word copy. */ + if (len >= OP_T_THRES) + { + /* Copy just a few bytes to make DSTP aligned. */ + len -= (-dstp) % OPSIZ; + BYTE_COPY_FWD (dstp, srcp, (-dstp) % OPSIZ); + + /* Copy whole pages from SRCP to DSTP by virtual address + manipulation, as much as possible. */ + + PAGE_COPY_FWD_MAYBE (dstp, srcp, len, len); + + /* Copy from SRCP to DSTP taking advantage of the known + alignment of DSTP. Number of bytes remaining is put + in the third argument, i.e. in LEN. This number may + vary from machine to machine. */ + + WORD_COPY_FWD (dstp, srcp, len, len); + + /* Fall out and copy the tail. */ + } + + /* There are just a few bytes to copy. Use byte memory operations. */ + BYTE_COPY_FWD (dstp, srcp, len); + } + else + { + /* Copy from the end to the beginning. */ + srcp += len; + dstp += len; + + /* If there not too few bytes to copy, use word copy. */ + if (len >= OP_T_THRES) + { + /* Copy just a few bytes to make DSTP aligned. */ + len -= dstp % OPSIZ; + BYTE_COPY_BWD (dstp, srcp, dstp % OPSIZ); + + /* Copy from SRCP to DSTP taking advantage of the known + alignment of DSTP. Number of bytes remaining is put + in the third argument, i.e. in LEN. This number may + vary from machine to machine. */ + + WORD_COPY_BWD (dstp, srcp, len, len); + + /* Fall out and copy the tail. */ + } + + /* There are just a few bytes to copy. Use byte memory operations. */ + BYTE_COPY_BWD (dstp, srcp, len); + } + + return dest; +} diff --git a/sysdeps/generic/mempcpy_chk.c b/sysdeps/generic/mempcpy_chk.c new file mode 100644 index 0000000000..5297bbab92 --- /dev/null +++ b/sysdeps/generic/mempcpy_chk.c @@ -0,0 +1,67 @@ +/* Copy memory to memory until the specified number of bytes + has been copied, return pointer to following byte, with error checking. + Overlap is NOT handled correctly. + Copyright (C) 1991, 1997, 1998, 2002, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Torbjorn Granlund (tege@sics.se). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <string.h> +#include <memcopy.h> +#include <pagecopy.h> + +void * +__mempcpy_chk (dstpp, srcpp, len, dstlen) + void *dstpp; + const void *srcpp; + size_t len; + size_t dstlen; +{ + if (__builtin_expect (dstlen < len, 0)) + __chk_fail (); + + unsigned long int dstp = (long int) dstpp; + unsigned long int srcp = (long int) srcpp; + + /* Copy from the beginning to the end. */ + + /* If there not too few bytes to copy, use word copy. */ + if (len >= OP_T_THRES) + { + /* Copy just a few bytes to make DSTP aligned. */ + len -= (-dstp) % OPSIZ; + BYTE_COPY_FWD (dstp, srcp, (-dstp) % OPSIZ); + + /* Copy whole pages from SRCP to DSTP by virtual address manipulation, + as much as possible. */ + + PAGE_COPY_FWD_MAYBE (dstp, srcp, len, len); + + /* Copy from SRCP to DSTP taking advantage of the known alignment of + DSTP. Number of bytes remaining is put in the third argument, + i.e. in LEN. This number may vary from machine to machine. */ + + WORD_COPY_FWD (dstp, srcp, len, len); + + /* Fall out and copy the tail. */ + } + + /* There are just a few bytes to copy. Use byte memory operations. */ + BYTE_COPY_FWD (dstp, srcp, len); + + return (void *) dstp; +} diff --git a/sysdeps/generic/memset_chk.c b/sysdeps/generic/memset_chk.c new file mode 100644 index 0000000000..c311914395 --- /dev/null +++ b/sysdeps/generic/memset_chk.c @@ -0,0 +1,92 @@ +/* Copyright (C) 1991, 1997, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <string.h> +#include <memcopy.h> + +void * +__memset_chk (dstpp, c, len, dstlen) + void *dstpp; + int c; + size_t len; + size_t dstlen; +{ + if (__builtin_expect (dstlen < len, 0)) + __chk_fail (); + + long int dstp = (long int) dstpp; + + if (len >= 8) + { + size_t xlen; + op_t cccc; + + cccc = (unsigned char) c; + cccc |= cccc << 8; + cccc |= cccc << 16; + if (OPSIZ > 4) + /* Do the shift in two steps to avoid warning if long has 32 bits. */ + cccc |= (cccc << 16) << 16; + + /* There are at least some bytes to set. + No need to test for LEN == 0 in this alignment loop. */ + while (dstp % OPSIZ != 0) + { + ((byte *) dstp)[0] = c; + dstp += 1; + len -= 1; + } + + /* Write 8 `op_t' per iteration until less than 8 `op_t' remain. */ + xlen = len / (OPSIZ * 8); + while (xlen > 0) + { + ((op_t *) dstp)[0] = cccc; + ((op_t *) dstp)[1] = cccc; + ((op_t *) dstp)[2] = cccc; + ((op_t *) dstp)[3] = cccc; + ((op_t *) dstp)[4] = cccc; + ((op_t *) dstp)[5] = cccc; + ((op_t *) dstp)[6] = cccc; + ((op_t *) dstp)[7] = cccc; + dstp += 8 * OPSIZ; + xlen -= 1; + } + len %= OPSIZ * 8; + + /* Write 1 `op_t' per iteration until less than OPSIZ bytes remain. */ + xlen = len / OPSIZ; + while (xlen > 0) + { + ((op_t *) dstp)[0] = cccc; + dstp += OPSIZ; + xlen -= 1; + } + len %= OPSIZ; + } + + /* Write the last few bytes. */ + while (len > 0) + { + ((byte *) dstp)[0] = c; + dstp += 1; + len -= 1; + } + + return dstpp; +} diff --git a/sysdeps/generic/readonly-area.c b/sysdeps/generic/readonly-area.c new file mode 100644 index 0000000000..df5b96015c --- /dev/null +++ b/sysdeps/generic/readonly-area.c @@ -0,0 +1,29 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Return 1 if the whole area PTR .. PTR+SIZE is not writable. + Return -1 if it is writable. */ + +#include <stdlib.h> + +int +__readonly_str (const void *ptr, size_t size) +{ + /* The conservative answer is that all strings are writable. */ + return -1; +} diff --git a/sysdeps/generic/stpcpy_chk.c b/sysdeps/generic/stpcpy_chk.c new file mode 100644 index 0000000000..dacda0115a --- /dev/null +++ b/sysdeps/generic/stpcpy_chk.c @@ -0,0 +1,45 @@ +/* Copyright (C) 1992, 1995, 1997, 2002, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <string.h> + + +/* Copy SRC to DEST, returning the address of the terminating '\0' in DEST. */ +char * +__stpcpy_chk (dest, src, destlen) + char *dest; + const char *src; + size_t destlen; +{ + register char *d = dest; + register const char *s = src; + + do + { + if (__builtin_expect (destlen-- == 0, 0)) + __chk_fail (); + *d++ = *s; + } + while (*s++ != '\0'); + + return d - 1; +} diff --git a/sysdeps/generic/strcat_chk.c b/sysdeps/generic/strcat_chk.c new file mode 100644 index 0000000000..b3fb3470b7 --- /dev/null +++ b/sysdeps/generic/strcat_chk.c @@ -0,0 +1,58 @@ +/* Copyright (C) 1991, 1997, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <string.h> +#include <memcopy.h> + + +/* Append SRC on the end of DEST. */ +char * +__strcat_chk (dest, src, destlen) + char *dest; + const char *src; + size_t destlen; +{ + char *s1 = dest; + const char *s2 = src; + reg_char c; + + /* Find the end of the string. */ + do + { + if (__builtin_expect (destlen-- == 0, 0)) + __chk_fail (); + c = *s1++; + } + while (c != '\0'); + + /* Make S1 point before the next character, so we can increment + it while memory is read (wins on pipelined cpus). */ + ++destlen; + s1 -= 2; + + do + { + if (__builtin_expect (destlen-- == 0, 0)) + __chk_fail (); + c = *s2++; + *++s1 = c; + } + while (c != '\0'); + + return dest; +} diff --git a/sysdeps/generic/strcpy_chk.c b/sysdeps/generic/strcpy_chk.c new file mode 100644 index 0000000000..5c1ae44cd0 --- /dev/null +++ b/sysdeps/generic/strcpy_chk.c @@ -0,0 +1,46 @@ +/* Copyright (C) 1991, 1997, 2000, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <stddef.h> +#include <string.h> +#include <memcopy.h> + +#undef strcpy + +/* Copy SRC to DEST with checking of destination buffer overflow. */ +char * +__strcpy_chk (dest, src, destlen) + char *dest; + const char *src; + size_t destlen; +{ + reg_char c; + char *s = (char *) src; + const ptrdiff_t off = dest - s - 1; + + do + { + if (__builtin_expect (destlen-- == 0, 0)) + __chk_fail (); + c = *s++; + s[off] = c; + } + while (c != '\0'); + + return dest; +} diff --git a/sysdeps/generic/strncat_chk.c b/sysdeps/generic/strncat_chk.c new file mode 100644 index 0000000000..953b435a4b --- /dev/null +++ b/sysdeps/generic/strncat_chk.c @@ -0,0 +1,100 @@ +/* Copyright (C) 1991, 1997, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <string.h> + +#include <memcopy.h> + + +char * +__strncat_chk (s1, s2, n, s1len) + char *s1; + const char *s2; + size_t n; + size_t s1len; +{ + reg_char c; + char *s = s1; + + /* Find the end of S1. */ + do + { + if (__builtin_expect (s1len-- == 0, 0)) + __chk_fail (); + c = *s1++; + } + while (c != '\0'); + + /* Make S1 point before next character, so we can increment + it while memory is read (wins on pipelined cpus). */ + ++s1len; + s1 -= 2; + + if (n >= 4) + { + size_t n4 = n >> 2; + do + { + if (__builtin_expect (s1len-- == 0, 0)) + __chk_fail (); + c = *s2++; + *++s1 = c; + if (c == '\0') + return s; + if (__builtin_expect (s1len-- == 0, 0)) + __chk_fail (); + c = *s2++; + *++s1 = c; + if (c == '\0') + return s; + if (__builtin_expect (s1len-- == 0, 0)) + __chk_fail (); + c = *s2++; + *++s1 = c; + if (c == '\0') + return s; + if (__builtin_expect (s1len-- == 0, 0)) + __chk_fail (); + c = *s2++; + *++s1 = c; + if (c == '\0') + return s; + } while (--n4 > 0); + n &= 3; + } + + while (n > 0) + { + if (__builtin_expect (s1len-- == 0, 0)) + __chk_fail (); + c = *s2++; + *++s1 = c; + if (c == '\0') + return s; + n--; + } + + if (c != '\0') + { + if (__builtin_expect (s1len-- == 0, 0)) + __chk_fail (); + *++s1 = '\0'; + } + + return s; +} diff --git a/sysdeps/generic/strncpy_chk.c b/sysdeps/generic/strncpy_chk.c new file mode 100644 index 0000000000..bdede7738b --- /dev/null +++ b/sysdeps/generic/strncpy_chk.c @@ -0,0 +1,89 @@ +/* Copyright (C) 1991, 1997, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <string.h> +#include <memcopy.h> + + +char * +__strncpy_chk (s1, s2, n, s1len) + char *s1; + const char *s2; + size_t n; + size_t s1len; +{ + reg_char c; + char *s = s1; + + if (__builtin_expect (s1len < n, 0)) + __chk_fail (); + + --s1; + + if (n >= 4) + { + size_t n4 = n >> 2; + + for (;;) + { + c = *s2++; + *++s1 = c; + if (c == '\0') + break; + c = *s2++; + *++s1 = c; + if (c == '\0') + break; + c = *s2++; + *++s1 = c; + if (c == '\0') + break; + c = *s2++; + *++s1 = c; + if (c == '\0') + break; + if (--n4 == 0) + goto last_chars; + } + n = n - (s1 - s) - 1; + if (n == 0) + return s; + goto zero_fill; + } + + last_chars: + n &= 3; + if (n == 0) + return s; + + do + { + c = *s2++; + *++s1 = c; + if (--n == 0) + return s; + } + while (c != '\0'); + + zero_fill: + do + *++s1 = '\0'; + while (--n > 0); + + return s; +} diff --git a/sysdeps/i386/i686/memcpy.S b/sysdeps/i386/i686/memcpy.S index 865967c5c8..00e84ec2e5 100644 --- a/sysdeps/i386/i686/memcpy.S +++ b/sysdeps/i386/i686/memcpy.S @@ -1,7 +1,7 @@ /* Copy memory block and return pointer to beginning of destination block For Intel 80x86, x>=6. This file is part of the GNU C Library. - Copyright (C) 1999, 2000, 2003 Free Software Foundation, Inc. + Copyright (C) 1999, 2000, 2003, 2004 Free Software Foundation, Inc. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1999. The GNU C Library is free software; you can redistribute it and/or @@ -31,6 +31,13 @@ #define LEN SRC+PTR_SIZE .text +#if defined PIC && !defined NOT_IN_libc +ENTRY (__memcpy_chk) + movl 12(%esp), %eax + cmpl %eax, 16(%esp) + jb HIDDEN_JUMPTARGET (__chk_fail) +END (__memcpy_chk) +#endif ENTRY (BP_SYM (memcpy)) ENTER diff --git a/sysdeps/i386/i686/memcpy_chk.S b/sysdeps/i386/i686/memcpy_chk.S new file mode 100644 index 0000000000..561263f9bf --- /dev/null +++ b/sysdeps/i386/i686/memcpy_chk.S @@ -0,0 +1,35 @@ +/* Checking memcpy for x86-64. + Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include "asm-syntax.h" + +#ifndef PIC + /* For libc.so this is defined in memcpy.S. + For libc.a, this is a separate source to avoid + memcpy bringing in __chk_fail and all routines + it calls. */ + .text +ENTRY (__memcpy_chk) + movl 12(%esp), %eax + cmpl %eax, 16(%esp) + jb __chk_fail + jmp memcpy +END (__memcpy_chk) +#endif diff --git a/sysdeps/i386/i686/memmove.S b/sysdeps/i386/i686/memmove.S index 421b4effda..951e139ad4 100644 --- a/sysdeps/i386/i686/memmove.S +++ b/sysdeps/i386/i686/memmove.S @@ -1,7 +1,7 @@ /* Copy memory block and return pointer to beginning of destination block For Intel 80x86, x>=6. This file is part of the GNU C Library. - Copyright (C) 2003 Free Software Foundation, Inc. + Copyright (C) 2003, 2004 Free Software Foundation, Inc. Contributed by Ulrich Drepper <drepper@cygnus.com>, 2003. The GNU C Library is free software; you can redistribute it and/or @@ -31,6 +31,13 @@ #define LEN SRC+PTR_SIZE .text +#if defined PIC && !defined NOT_IN_libc +ENTRY (__memmove_chk) + movl 12(%esp), %eax + cmpl %eax, 16(%esp) + jb HIDDEN_JUMPTARGET (__chk_fail) +END (__memmove_chk) +#endif ENTRY (BP_SYM (memmove)) ENTER diff --git a/sysdeps/i386/i686/memmove_chk.S b/sysdeps/i386/i686/memmove_chk.S new file mode 100644 index 0000000000..23382ea8bf --- /dev/null +++ b/sysdeps/i386/i686/memmove_chk.S @@ -0,0 +1,35 @@ +/* Checking memmove for x86-64. + Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include "asm-syntax.h" + +#ifndef PIC + /* For libc.so this is defined in memmove.S. + For libc.a, this is a separate source to avoid + memmove bringing in __chk_fail and all routines + it calls. */ + .text +ENTRY (__memmove_chk) + movl 12(%esp), %eax + cmpl %eax, 16(%esp) + jb __chk_fail + jmp memmove +END (__memmove_chk) +#endif diff --git a/sysdeps/i386/i686/mempcpy.S b/sysdeps/i386/i686/mempcpy.S index 3ea89d4a17..843a35823a 100644 --- a/sysdeps/i386/i686/mempcpy.S +++ b/sysdeps/i386/i686/mempcpy.S @@ -31,6 +31,13 @@ #define LEN SRC+PTR_SIZE .text +#if defined PIC && !defined NOT_IN_libc +ENTRY (__mempcpy_chk) + movl 12(%esp), %eax + cmpl %eax, 16(%esp) + jb HIDDEN_JUMPTARGET (__chk_fail) +END (__mempcpy_chk) +#endif ENTRY (BP_SYM (__mempcpy)) ENTER diff --git a/sysdeps/i386/i686/mempcpy_chk.S b/sysdeps/i386/i686/mempcpy_chk.S new file mode 100644 index 0000000000..dc9c6095f0 --- /dev/null +++ b/sysdeps/i386/i686/mempcpy_chk.S @@ -0,0 +1,35 @@ +/* Checking mempcpy for x86-64. + Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include "asm-syntax.h" + +#ifndef PIC + /* For libc.so this is defined in mempcpy.S. + For libc.a, this is a separate source to avoid + mempcpy bringing in __chk_fail and all routines + it calls. */ + .text +ENTRY (__mempcpy_chk) + movl 12(%esp), %eax + cmpl %eax, 16(%esp) + jb __chk_fail + jmp mempcpy +END (__mempcpy_chk) +#endif diff --git a/sysdeps/i386/i686/memset.S b/sysdeps/i386/i686/memset.S index 4ddcb39731..561188ffec 100644 --- a/sysdeps/i386/i686/memset.S +++ b/sysdeps/i386/i686/memset.S @@ -39,6 +39,13 @@ #endif .text +#if defined PIC && !defined NOT_IN_libc && !BZERO_P +ENTRY (__memset_chk) + movl 12(%esp), %eax + cmpl %eax, 16(%esp) + jb HIDDEN_JUMPTARGET (__chk_fail) +END (__memset_chk) +#endif ENTRY (BP_SYM (memset)) ENTER diff --git a/sysdeps/i386/i686/memset_chk.S b/sysdeps/i386/i686/memset_chk.S new file mode 100644 index 0000000000..d178654994 --- /dev/null +++ b/sysdeps/i386/i686/memset_chk.S @@ -0,0 +1,35 @@ +/* Checking memset for x86-64. + Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include "asm-syntax.h" + +#ifndef PIC + /* For libc.so this is defined in memset.S. + For libc.a, this is a separate source to avoid + memset bringing in __chk_fail and all routines + it calls. */ + .text +ENTRY (__memset_chk) + movl 12(%esp), %eax + cmpl %eax, 16(%esp) + jb __chk_fail + jmp memset +END (__memset_chk) +#endif diff --git a/sysdeps/unix/sysv/linux/readonly-area.c b/sysdeps/unix/sysv/linux/readonly-area.c new file mode 100644 index 0000000000..ce5321bcef --- /dev/null +++ b/sysdeps/unix/sysv/linux/readonly-area.c @@ -0,0 +1,90 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <stdint.h> +#include <stdio.h> +#include <stdio_ext.h> +#include <stdlib.h> +#include <string.h> +#include "libio/libioP.h" + +/* Return 1 if the whole area PTR .. PTR+SIZE is not writable. + Return -1 if it is writable. */ + +int +__readonly_area (const char *ptr, size_t size) +{ + const void *ptr_end = ptr + size; + + FILE *fp = fopen ("/proc/self/maps", "rc"); + if (fp == NULL) + return -1; + + /* We need no locking. */ + __fsetlocking (fp, FSETLOCKING_BYCALLER); + + char *line = NULL; + size_t linelen = 0; + + while (! feof_unlocked (fp)) + { + if (_IO_getdelim (&line, &linelen, '\n', fp) <= 0) + break; + + char *p; + uintptr_t from = strtoul (line, &p, 16); + + if (p == line || *p++ != '-') + break; + + char *q; + uintptr_t to = strtoul (p, &q, 16); + + if (q == p || *q++ != ' ') + break; + + if (from < (uintptr_t) ptr_end && to > (uintptr_t) ptr) + { + /* Found an entry that at least partially covers the area. */ + if (*q++ != 'r' || *q++ != '-') + break; + + if (from <= (uintptr_t) ptr && to >= (uintptr_t) ptr_end) + { + size = 0; + break; + } + else if (from <= (uintptr_t) ptr) + size -= to - (uintptr_t) ptr; + else if (to >= (uintptr_t) ptr_end) + size -= (uintptr_t) ptr_end - from; + else + size -= to - from; + + if (!size) + break; + } + } + + fclose (fp); + free (line); + + /* If the whole area between ptr and ptr_end is covered by read-only + VMAs, return 1. Otherwise return -1. */ + return size == 0 ? 1 : -1; +} diff --git a/sysdeps/x86_64/memcpy.S b/sysdeps/x86_64/memcpy.S index de47688241..5f06198b5d 100644 --- a/sysdeps/x86_64/memcpy.S +++ b/sysdeps/x86_64/memcpy.S @@ -29,6 +29,12 @@ #define MEMPCPY_P (defined memcpy) .text +#if defined PIC && !defined NOT_IN_libc +ENTRY (__memcpy_chk) + cmpq %rdx, %rcx + jb HIDDEN_JUMPTARGET (__chk_fail) +END (__memcpy_chk) +#endif ENTRY (BP_SYM (memcpy)) /* Cutoff for the big loop is a size of 32 bytes since otherwise the loop will never be entered. */ diff --git a/sysdeps/x86_64/memcpy_chk.S b/sysdeps/x86_64/memcpy_chk.S new file mode 100644 index 0000000000..c5251ea2d4 --- /dev/null +++ b/sysdeps/x86_64/memcpy_chk.S @@ -0,0 +1,34 @@ +/* Checking memcpy for x86-64. + Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include "asm-syntax.h" + +#ifndef PIC + /* For libc.so this is defined in memcpy.S. + For libc.a, this is a separate source to avoid + memcpy bringing in __chk_fail and all routines + it calls. */ + .text +ENTRY (__memcpy_chk) + cmpq %rdx, %rcx + jb __chk_fail + jmp memcpy +END (__memcpy_chk) +#endif diff --git a/sysdeps/x86_64/mempcpy.S b/sysdeps/x86_64/mempcpy.S index 03aa743fba..4558a1699a 100644 --- a/sysdeps/x86_64/mempcpy.S +++ b/sysdeps/x86_64/mempcpy.S @@ -1,4 +1,5 @@ #define memcpy __mempcpy +#define __memcpy_chk __mempcpy_chk #include <sysdeps/x86_64/memcpy.S> libc_hidden_def (BP_SYM (__mempcpy)) diff --git a/sysdeps/x86_64/mempcpy_chk.S b/sysdeps/x86_64/mempcpy_chk.S new file mode 100644 index 0000000000..c333a4adb3 --- /dev/null +++ b/sysdeps/x86_64/mempcpy_chk.S @@ -0,0 +1,34 @@ +/* Checking mempcpy for x86-64. + Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include "asm-syntax.h" + +#ifndef PIC + /* For libc.so this is defined in memcpy.S. + For libc.a, this is a separate source to avoid + mempcpy bringing in __chk_fail and all routines + it calls. */ + .text +ENTRY (__mempcpy_chk) + cmpq %rdx, %rcx + jb __chk_fail + jmp mempcpy +END (__mempcpy_chk) +#endif diff --git a/sysdeps/x86_64/memset.S b/sysdeps/x86_64/memset.S index 29afa63e7e..6c47f4c863 100644 --- a/sysdeps/x86_64/memset.S +++ b/sysdeps/x86_64/memset.S @@ -1,6 +1,6 @@ /* memset/bzero -- set memory area to CH/0 Optimized version for x86-64. - Copyright (C) 2002, 2003 Free Software Foundation, Inc. + Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Andreas Jaeger <aj@suse.de>. @@ -32,6 +32,12 @@ #define LARGE $120000 .text +#if !BZERO_P && defined PIC && !defined NOT_IN_libc +ENTRY (__memset_chk) + cmpq %rdx, %rcx + jb HIDDEN_JUMPTARGET (__chk_fail) +END (__memset_chk) +#endif ENTRY (memset) #if BZERO_P mov %rsi,%rdx /* Adjust parameter. */ diff --git a/sysdeps/x86_64/memset_chk.S b/sysdeps/x86_64/memset_chk.S new file mode 100644 index 0000000000..e62cb58cc0 --- /dev/null +++ b/sysdeps/x86_64/memset_chk.S @@ -0,0 +1,34 @@ +/* Checking memset for x86-64. + Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include "asm-syntax.h" + +#ifndef PIC + /* For libc.so this is defined in memset.S. + For libc.a, this is a separate source to avoid + memset bringing in __chk_fail and all routines + it calls. */ + .text +ENTRY (__memset_chk) + cmpq %rdx, %rcx + jb __chk_fail + jmp memset +END (__memset_chk) +#endif diff --git a/sysdeps/x86_64/stpcpy_chk.S b/sysdeps/x86_64/stpcpy_chk.S new file mode 100644 index 0000000000..905e8d7ee3 --- /dev/null +++ b/sysdeps/x86_64/stpcpy_chk.S @@ -0,0 +1,3 @@ +#define USE_AS_STPCPY_CHK +#define STRCPY_CHK __stpcpy_chk +#include <sysdeps/x86_64/strcpy_chk.S> diff --git a/sysdeps/x86_64/strcpy_chk.S b/sysdeps/x86_64/strcpy_chk.S new file mode 100644 index 0000000000..364331553a --- /dev/null +++ b/sysdeps/x86_64/strcpy_chk.S @@ -0,0 +1,211 @@ +/* strcpy/stpcpy checking implementation for x86-64. + Copyright (C) 2002, 2004 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>. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include "asm-syntax.h" +#include "bp-sym.h" +#include "bp-asm.h" + +#ifndef USE_AS_STPCPY_CHK +# define STRCPY_CHK __strcpy_chk +#endif + + .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. */ +#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: +#ifdef USE_AS_STPCPY_CHK + movq %rdi, %rax /* Destination is return value. */ +#else + movq %r10, %rax /* Source is return value. */ +#endif + retq + +50: + testq %rdx, %rdx + jnz 52b + jmp HIDDEN_JUMPTARGET (__chk_fail) + +END (STRCPY_CHK) |