diff options
109 files changed, 3731 insertions, 131 deletions
diff --git a/ChangeLog b/ChangeLog index fc66050f1e..1e5ff7d981 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,242 @@ +2004-10-06 Maciej W. Rozycki <macro@mips.com> + + * sysdeps/unix/sysv/linux/mips/mips32/sysdep.h + (__SYSCALL_CLOBBERS): Add "memory". + * sysdeps/unix/sysv/linux/mips/mips64/n32/sysdep.h + (__SYSCALL_CLOBBERS): Likewise. + * sysdeps/unix/sysv/linux/mips/mips64/n64/sysdep.h + (__SYSCALL_CLOBBERS): Likewise. + +2004-10-17 Ulrich Drepper <drepper@redhat.com> + + * include/libc-symbols.h: Define libresolv_hidden_proto and friends. + * include/resolv.h: Add libresolv_hidden_proto for symbols defined, + used, and exported in libresolv. + * resolv/base64.c: Add libresolv_hidden_def. + * resolv/gethnamaddr.c: Likewise. + * resolv/ns_name.c: Likewise. + * resolv/ns_netint.c: Likewise. + * resolv/res_comp.c: Likewise. + * resolv/res_data.c: Likewise. + * resolv/res_debug.c: Likewise. + * resolv/res_mkquery.c: Likewise. + * resolv/res_query.c: Likewise. + * resolv/res_send.c: Likewise. + +2004-10-15 Jakub Jelinek <jakub@redhat.com> + + * elf/dl-minimal.c (__chk_fail): New. Add rtld_hidden_def. + * sysdeps/unix/sysv/linux/readonly-area.c: New file. + * sysdeps/i386/i686/memmove.S (__memmove_chk): Add checking + routine. + * sysdeps/i386/i686/memcpy.S (__memcpy_chk): Likewise. + * sysdeps/i386/i686/mempcpy.S (__mempcpy_chk): Likewise. + * sysdeps/i386/i686/memset.S (__memset_chk): Likewise. + * sysdeps/i386/i686/memmove-chk.S: New file. + * sysdeps/i386/i686/memcpy-chk.S: Likewise. + * sysdeps/i386/i686/mempcpy-chk.S: Likewise. + * sysdeps/i386/i686/memset-chk.S: Likewise. + * sysdeps/generic/strcat-chk.c (__strcat_chk): Don't __chk_fail + if exactly fitting into buffer. + * sysdeps/generic/strncat-chk.c (__strncat_chk): Likewise. + * sysdeps/generic/readonly-area.c: New file. + * sysdeps/generic/strncpy-chk.c (__strncpy_chk): Only test + destlen once. + * sysdeps/x86_64/memset.S (__memset_chk): Add checking routine. + * sysdeps/x86_64/memcpy.S (__memcpy_chk): Likewise. + * sysdeps/x86_64/mempcpy.S (__memcpy_chk): Define to __mempcpy_chk. + * sysdeps/x86_64/memcpy-chk.S: New file. + * sysdeps/x86_64/mempcpy-chk.S: Likewise. + * sysdeps/x86_64/memset-chk.S: Likewise. + * sysdeps/x86_64/strcpy-chk.S: Likewise. + * sysdeps/x86_64/stpcpy-chk.S: Likewise. + * argp/argp-xinl.c (__OPTIMIZE__): Define to 1 instead of nothing. + * argp/argp-fs-xinl.c (__OPTIMIZE__): Likewise. + * debug/tst-chk1.c: New test. + * debug/tst-chk2.c: Likewise. + * debug/tst-chk3.c: Likewise. + * debug/test-strcpy_chk.c: Likewise. + * debug/test-stpcpy_chk.c: Likewise. + * debug/vsprintf_chk.c (__vsprintf_chk): If flags > 0, request + _IO_FLAGS2_CHECK_PERCENT_N. Add libc_hidden_def. + * debug/Makefile (routines): Add printf_chk, fprintf_chk, vprintf_chk, + vfprintf_chk, gets_chk and readonly-area. + (CFLAGS-*_chk.c): Set. + (tests): Add tst-chk1, tst-chk2, tst-chk3, test-strcpy_chk and + test-stpcpy_chk. + * debug/vprintf_chk.c: New file. + * debug/printf_chk.c: Likewise. + * debug/vfprintf_chk.c: Likewise. + * debug/fprintf_chk.c: Likewise. + * debug/gets_chk.c: Likewise. + * debug/chk_fail.c (__chk_fail): Add libc_hidden_def. + * debug/snprintf_chk.c (__snprintf_chk): Fix order of arguments + passed to __vsnprintf_chk. + * debug/Versions (libc): Export __printf_chk, __fprintf_chk, + __vprintf_chk, __vfprintf_chk and __gets_chk @GLIBC_2.3.4. + * debug/vsnprintf_chk.c (__vsnprintf_chk): Don't call + __vsnprintf, instead create a temporary file with + _IO_strn_jumps jumptable. If flags > 0, request + _IO_FLAGS2_CHECK_PERCENT_N. Add libc_hidden_def. + * libio/Makefile (headers): Add bits/stdio2.h. + * libio/stdio.h: Include <bits/stdio2.h> if __USE_FORTIFY_LEVEL. + (sprintf, snprintf, vsprintf, vsnprintf): Remove defines. + * libio/strfile.h (_IO_strnfile): New type. + (_IO_strn_jumps): New extern. + * libio/vsnprintf.c (_IO_strnfile): Remove. + (_IO_strn_jumps): Remove static. + * libio/bits/stdio2.h: New file. + * libio/vswprintf.c (_IO_strnfile): Rename type to... + (_IO_wstrnfile): ...this. Adjust all uses. + * libio/libio.h (_IO_FLAGS2_CHECK_PERCENT_N): Define. + * stdio-common/vfprintf.c (STR_LEN): Define. + (vfprintf): Add readonly_format variable. + Handle _IO_FLAGS2_CHECK_PERCENT_N. + (buffered_vfprintf): Copy _flags2. + * include/stdio.h (__sprintf_chk, __snprintf_chk, __vsprintf_chk, + __vsnprintf_chk, __printf_chk, __fprintf_chk, __vprintf_chk, + __vfprintf_chk): New prototypes. + (__vsprintf_chk, __vsnprintf_chk): Add libc_hidden_proto. + * include/string.h (__memcpy_chk, __memmove_chk, __mempcpy_chk, + __memset_chk, __strcpy_chk, __stpcpy_chk, __strncpy_chk, __strcat_chk, + __strncat_chk): New prototypes. + * include/bits/string3.h: New file. + * include/sys/cdefs.h (__chk_fail): Add libc_hidden_proto + and rtld_hidden_proto. + * string/Makefile (headers): Add bits/string3.h. + * string/bits/string3.h (bcopy, bzero): New defines. + (memset, memcpy, memmove, strcpy, strncpy, strcat, strncat): Change + macros so that inlines are used only if unknown destination size + or side-effects in destination argument. + (mempcpy, stpcpy): Likewise. Protect with #ifdef __USE_GNU. + +2004-09-16 Ulrich Drepper <drepper@redhat.com> + + * debug/Makefile (routines): Add *_chk. + * debug/Versions (libc): Export __chk_fail, __memcpy_chk, + __memmove_chk, __mempcpy_chk, __memset_chk, __stpcpy_chk, + __strcat_chk, __strcpy_chk, __strncat_chk, __strncpy_chk, + __sprintf_chk, __vsprintf_chk, __snprintf_chk, __vsnprintf_chk + @GLIBC_2.3.4. + * debug/chk_fail.c: New file. + * debug/snprintf_chk.c: Likewise. + * debug/sprintf_chk.c: Likewise. + * debug/vsnprintf_chk.c: Likewise. + * debug/vsprintf_chk.c: Likewise. + * include/features.h (_FORTIFY_SOURCE): Document, handle. + (__USE_FORTIFY_LEVEL): Define. + (__GNUC_PREREQ): Move to earlier location. + * include/sys/cdefs.h (__chk_fail): New prototype. + * libio/bits/stdio.h (sprintf, vsprintf, snprintf, vsnprintf): + Define if __USE_FORTIFY_LEVEL. + * misc/sys/cdefs.h (__bos, __bos0): Define. + * string/string.h: Include <bits/string3.h> if __USE_FORTIFY_LEVEL. + * bits/string/string3.h: New header. + * sysdeps/generic/memcpy_chk.c: New file. + * sysdeps/generic/memmove_chk.c: Likewise. + * sysdeps/generic/mempcpy_chk.c: Likewise. + * sysdeps/generic/memset_chk.c: Likewise. + * sysdeps/generic/stpcpy_chk.c: Likewise. + * sysdeps/generic/strcat_chk.c: Likewise. + * sysdeps/generic/strcpy_chk.c: Likewise. + * sysdeps/generic/strncat_chk.c: Likewise. + * sysdeps/generic/strncpy_chk.c: Likewise. + +2004-10-17 Roland McGrath <roland@frob.com> + + * manual/memory.texi (Page Lock Functions): Typo fix. + Reported by Carlos Maziero <maziero@ppgia.pucpr.br> + +2004-10-16 Alfred M. Szmidt <ams@kemisten.nu> + + * sysdeps/mach/hurd/Makefile (link-libc-static): Use + `$(static-gnulib') instead of `$(gnulib)'. + +2004-10-17 Ulrich Drepper <drepper@redhat.com> + + * sunrpc/rpc_clntout.c: Avoid including rcsid into binary. + * sunrpc/rpc_cout.c: Likewise. + * sunrpc/rpc_hout.c: Likewise. + * sunrpc/rpc_main.c: Likewise. + * sunrpc/rpc_parse.c: Likewise. + * sunrpc/rpc_sample.c: Likewise. + * sunrpc/rpc_scan.c: Likewise. + * sunrpc/rpc_svcout.c: Likewise. + * sunrpc/rpc_tblout.c: Likewise. + * sunrpc/rpc_util.c: Likewise. + +2004-10-15 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/i386/sysdep.h (PUSHARGS_6, DOARGS_6, + POPARGS_6, _PUSHARGS_6, _DOARGS_6, _POPARGS_6): Define. + * sysdeps/unix/sysv/linux/i386/syscall.S (syscall): Handle 6 argument + syscalls. + +2004-10-15 Ulrich Drepper <drepper@redhat.com> + + * nscd/nscd.h (_PATH_NSCD_PASSWD_DB): Move to /var/db. + (_PATH_NSCD_GROUP_DB): Likewise. + (_PATH_NSCD_HOSTS_DB): Likewise. + (_PATH_NSCD_XYZ_DB_TMP): New #define, point to /var/run. + * nscd/connections.c (nscd_init): Non-persistent database files + are created with the _PATH_NSCD_XYZ_DB_TMP path. + * nscd/nscd.init: Create /var/db/nscd if necessary. + +2004-10-15 Richard Henderson <rth@redhat.com> + + * sysdeps/unix/sysv/linux/alpha/register-dump.h: New file. + * sysdeps/unix/sysv/linux/alpha/sigcontextinfo.h (SIGCONTEXT): Add + _code argument, pass sigcontext by pointer. + (SIGCONTEXT_EXTRA_ARGS): Likewise. + (GET_PC, GET_FRAME, GET_STACK): Expect ctx as pointer. + +2004-10-14 Richard Henderson <rth@redhat.com> + + * sysdeps/alpha/dl-machine.h (elf_machine_rela, + elf_machine_rela_relative, elf_machine_lazy_rel): Mark auto + instead of static. + + * sysdeps/unix/sysv/linux/adjtime.c (ADJTIME): Use prototype + style definition. + * sysdeps/unix/sysv/linux/alpha/adjtime.c (ADJTIME): If + __ASSUME_TIMEVAL64, define __adjtime directly rather than + via strong_alias. + +2004-10-14 Ulrich Drepper <drepper@redhat.com> + + * nscd/Makefile: When using compilers without -fpie support, also + link with -lselinux if necessary. + Patch by Arkadiusz Miskiewicz <arekm@pld-linux.org>. + + * nscd/connections.c (nscd_init): Remove file if not persistent + and not shared. Patch by Jerome Borsboom <j.borsboom@erasmusmc.nl>. + +2004-10-14 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/i386/setresuid.c: Handle + defined __NR_setresuid32 && !defined __NR_setresuid. + * sysdeps/unix/sysv/linux/i386/setresgid.c: Handle + defined __NR_setresgid32 && !defined __NR_setresgid. + + * sysdeps/sparc/fpu/bits/mathinline.h (__signbitf, __signbit, + __signbitl, sqrtf, sqrt, sqrtl, fdim, fdimf): Use __NTH macro. + + * sysdeps/generic/errno-loc.c: Don't undef #errno + if RTLD_PRIVATE_ERRNO. + * include/errno.h (__errno_location): If RTLD_PRIVATE_ERRNO, + add attribute_hidden. + + * dlfcn/dlinfo.c (dlinfo_doit): Replace iteration over GL(dl_loaded) + chain with iteration over all namespaces' _ns_loaded chains. + * sysdeps/powerpc/powerpc32/dl-machine.c (__elf_preferred_address): + Likewise. + * sysdeps/mips/dl-machine.h (elf_machine_runtime_link_map): Likewise. + + * elf/rtld.c (_dl_start): Fix one last dl_loaded. + * elf/dl-load.c (_dl_map_object_from_fd): Avoid definition of + label when it is not needed. + * elf/dl-close.c (_dl_close): Typo: & -> &&. + 2004-10-12 Jakub Jelinek <jakub@redhat.com> * sysdeps/generic/segfault.c: Include alloca.h and stdint.h. diff --git a/argp/argp-fs-xinl.c b/argp/argp-fs-xinl.c index 21f9bd9f71..3cf1f9827d 100644 --- a/argp/argp-fs-xinl.c +++ b/argp/argp-fs-xinl.c @@ -1,5 +1,5 @@ /* Real definitions for extern inline functions in argp-fmtstream.h - Copyright (C) 1997, 2003 Free Software Foundation, Inc. + Copyright (C) 1997, 2003, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Miles Bader <miles@gnu.ai.mit.edu>. @@ -24,7 +24,7 @@ #define ARGP_FS_EI #undef __OPTIMIZE__ -#define __OPTIMIZE__ +#define __OPTIMIZE__ 1 #include "argp-fmtstream.h" #if 0 diff --git a/argp/argp-xinl.c b/argp/argp-xinl.c index 2431093ea3..73177585e8 100644 --- a/argp/argp-xinl.c +++ b/argp/argp-xinl.c @@ -1,5 +1,5 @@ /* Real definitions for extern inline functions in argp.h - Copyright (C) 1997, 1998 Free Software Foundation, Inc. + Copyright (C) 1997, 1998, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Miles Bader <miles@gnu.ai.mit.edu>. @@ -31,7 +31,7 @@ #endif #define ARGP_EI #undef __OPTIMIZE__ -#define __OPTIMIZE__ +#define __OPTIMIZE__ 1 #include "argp.h" /* Add weak aliases. */ diff --git a/debug/Makefile b/debug/Makefile index aba98926da..fed60d78b5 100644 --- a/debug/Makefile +++ b/debug/Makefile @@ -1,4 +1,4 @@ -# Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. +# Copyright (C) 1998, 1999, 2000, 2001, 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 @@ -24,11 +24,26 @@ subdir := debug headers := execinfo.h distribute = sigcontextinfo.h register-dump.h frame.h -routines := backtrace backtracesyms backtracesymsfd noophooks +routines := backtrace backtracesyms backtracesymsfd noophooks \ + memcpy_chk memmove_chk mempcpy_chk memset_chk stpcpy_chk \ + strcat_chk strcpy_chk strncat_chk strncpy_chk \ + sprintf_chk vsprintf_chk snprintf_chk vsnprintf_chk \ + printf_chk fprintf_chk vprintf_chk vfprintf_chk \ + gets_chk chk_fail readonly-area CFLAGS-backtrace.c = -fno-omit-frame-pointer - -tests = backtrace-tst +CFLAGS-sprintf_chk.c = -D_IO_MTSAFE_IO +CFLAGS-snprintf_chk.c = -D_IO_MTSAFE_IO +CFLAGS-vsprintf_chk.c = -D_IO_MTSAFE_IO +CFLAGS-vsnprintf_chk.c = -D_IO_MTSAFE_IO +CFLAGS-printf_chk.c = -D_IO_MTSAFE_IO $(exceptions) +CFLAGS-fprintf_chk.c = -D_IO_MTSAFE_IO $(exceptions) +CFLAGS-vprintf_chk.c = -D_IO_MTSAFE_IO $(exceptions) +CFLAGS-vfprintf_chk.c = -D_IO_MTSAFE_IO $(exceptions) +CFLAGS-gets_chk.c = -D_IO_MTSAFE_IO $(exceptions) + +tests = backtrace-tst tst-chk1 tst-chk2 tst-chk3 \ + test-strcpy_chk test-stpcpy_chk extra-libs = libSegFault libpcprofile extra-libs-others = $(extra-libs) diff --git a/debug/Versions b/debug/Versions index c2b6396d82..07d6fbb830 100644 --- a/debug/Versions +++ b/debug/Versions @@ -10,4 +10,12 @@ libc { # These are to support some gcc features. __cyg_profile_func_enter; __cyg_profile_func_exit; } + GLIBC_2.3.4 { + __chk_fail; + __memcpy_chk; __memmove_chk; __mempcpy_chk; __memset_chk; __stpcpy_chk; + __strcat_chk; __strcpy_chk; __strncat_chk; __strncpy_chk; + __sprintf_chk; __vsprintf_chk; __snprintf_chk; __vsnprintf_chk; + __printf_chk; __fprintf_chk; __vprintf_chk; __vfprintf_chk; + __gets_chk; + } } diff --git a/debug/chk_fail.c b/debug/chk_fail.c new file mode 100644 index 0000000000..48848fbe35 --- /dev/null +++ b/debug/chk_fail.c @@ -0,0 +1,38 @@ +/* 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 <stdlib.h> +#include <unistd.h> +#include <abort-instr.h> + + +void +__attribute__ ((noreturn)) +__chk_fail (void) +{ + while (1) + { + /* This will leave a nice backtrace. */ + abort (); +#ifdef ABORT_INSTRUCTION + ABORT_INSTRUCTION; +#endif + _exit (127); + } +} +libc_hidden_def (__chk_fail) diff --git a/debug/fprintf_chk.c b/debug/fprintf_chk.c new file mode 100644 index 0000000000..77508b902e --- /dev/null +++ b/debug/fprintf_chk.c @@ -0,0 +1,45 @@ +/* Copyright (C) 1991, 1995, 1996, 1997, 2001, 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 <stdarg.h> +#include <stdio.h> +#include "../libio/libioP.h" + + +/* Write formatted output to FP from the format string FORMAT. */ +int +__fprintf_chk (FILE *fp, int flag, const char *format, ...) +{ + va_list ap; + int done; + + _IO_acquire_lock (fp); + if (flag > 0) + fp->_flags2 |= _IO_FLAGS2_CHECK_PERCENT_N; + + va_start (ap, format); + done = vfprintf (fp, format, ap); + va_end (ap); + + if (flag > 0) + fp->_flags2 &= ~_IO_FLAGS2_CHECK_PERCENT_N; + _IO_release_lock (fp); + + return done; +} diff --git a/debug/gets_chk.c b/debug/gets_chk.c new file mode 100644 index 0000000000..3715a39672 --- /dev/null +++ b/debug/gets_chk.c @@ -0,0 +1,77 @@ +/* Copyright (C) 1993, 1996, 1997, 1998, 2002, 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. + + As a special exception, if you link the code in this file with + files compiled with a GNU compiler to produce an executable, + that does not cause the resulting executable to be covered by + the GNU Lesser General Public License. This exception does not + however invalidate any other reasons why the executable file + might be covered by the GNU Lesser General Public License. + This exception applies to code released by its copyright holders + in files containing the exception. */ + +#include "../libio/libioP.h" +#include <limits.h> + +char * +__gets_chk (char *buf, size_t size) +{ + _IO_size_t count; + int ch; + char *retval; + + if (size == 0) + __chk_fail (); + + _IO_acquire_lock (_IO_stdin); + ch = _IO_getc_unlocked (_IO_stdin); + if (ch == EOF) + { + retval = NULL; + goto unlock_return; + } + if (ch == '\n') + count = 0; + else + { + /* This is very tricky since a file descriptor may be in the + non-blocking mode. The error flag doesn't mean much in this + case. We return an error only when there is a new error. */ + int old_error = _IO_stdin->_IO_file_flags & _IO_ERR_SEEN; + _IO_stdin->_IO_file_flags &= ~_IO_ERR_SEEN; + buf[0] = (char) ch; + count = INTUSE(_IO_getline) (_IO_stdin, buf + 1, size - 1, '\n', 0) + 1; + if (_IO_stdin->_IO_file_flags & _IO_ERR_SEEN) + { + retval = NULL; + goto unlock_return; + } + else + _IO_stdin->_IO_file_flags |= old_error; + } + if (count >= size) + __chk_fail (); + buf[count] = 0; + retval = buf; +unlock_return: + _IO_release_lock (_IO_stdin); + return retval; +} + +link_warning (__gets_chk, "the `gets' function is dangerous and should not be used.") diff --git a/debug/printf_chk.c b/debug/printf_chk.c new file mode 100644 index 0000000000..d2b387323d --- /dev/null +++ b/debug/printf_chk.c @@ -0,0 +1,45 @@ +/* Copyright (C) 1991, 1995, 1996, 1997, 2001, 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 <stdarg.h> +#include <stdio.h> +#include "../libio/libioP.h" + + +/* Write formatted output to stdout from the format string FORMAT. */ +int +__printf_chk (int flag, const char *format, ...) +{ + va_list ap; + int done; + + _IO_acquire_lock (stdout); + if (flag > 0) + stdout->_flags2 |= _IO_FLAGS2_CHECK_PERCENT_N; + + va_start (ap, format); + done = vfprintf (stdout, format, ap); + va_end (ap); + + if (flag > 0) + stdout->_flags2 &= ~_IO_FLAGS2_CHECK_PERCENT_N; + _IO_release_lock (stdout); + + return done; +} diff --git a/debug/snprintf_chk.c b/debug/snprintf_chk.c new file mode 100644 index 0000000000..5a77afef29 --- /dev/null +++ b/debug/snprintf_chk.c @@ -0,0 +1,38 @@ +/* Copyright (C) 1991, 1995, 1997, 1998, 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 <stdarg.h> +#include <stdio.h> + + +/* Write formatted output into S, according to the format + string FORMAT, writing no more than MAXLEN characters. */ +/* VARARGS5 */ +int +__snprintf_chk (char *s, size_t maxlen, int flags, size_t slen, + const char *format, ...) +{ + va_list arg; + int done; + + va_start (arg, format); + done = __vsnprintf_chk (s, maxlen, flags, slen, format, arg); + va_end (arg); + + return done; +} diff --git a/debug/sprintf_chk.c b/debug/sprintf_chk.c new file mode 100644 index 0000000000..d141633b9f --- /dev/null +++ b/debug/sprintf_chk.c @@ -0,0 +1,35 @@ +/* Copyright (C) 1991,1995,1997,1998,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. */ + +#include <stdarg.h> +#include <stdio.h> + +/* Write formatted output into S, according to the format string FORMAT. */ +/* VARARGS4 */ +int +__sprintf_chk (char *s, int flags, size_t slen, const char *format, ...) +{ + va_list arg; + int done; + + va_start (arg, format); + done = __vsprintf_chk (s, flags, slen, format, arg); + va_end (arg); + + return done; +} diff --git a/debug/test-stpcpy_chk.c b/debug/test-stpcpy_chk.c new file mode 100644 index 0000000000..d717ca7363 --- /dev/null +++ b/debug/test-stpcpy_chk.c @@ -0,0 +1,46 @@ +/* Test and measure stpcpy checking functions. + Copyright (C) 1999, 2002, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Written by Jakub Jelinek <jakub@redhat.com>, 1999. + + 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. */ + +#define STRCPY_RESULT(dst, len) ((dst) + (len)) +#define TEST_MAIN +#include "../string/test-string.h" + +extern void __attribute__ ((noreturn)) __chk_fail (void); +char *simple_stpcpy_chk (char *, const char *, size_t); +extern char *normal_stpcpy (char *, const char *, size_t) + __asm ("stpcpy"); +extern char *__stpcpy_chk (char *, const char *, size_t); + +IMPL (simple_stpcpy_chk, 0) +IMPL (normal_stpcpy, 1) +IMPL (__stpcpy_chk, 2) + +char * +simple_stpcpy_chk (char *dst, const char *src, size_t len) +{ + if (! len) + __chk_fail (); + while ((*dst++ = *src++) != '\0') + if (--len == 0) + __chk_fail (); + return dst - 1; +} + +#include "test-strcpy_chk.c" diff --git a/debug/test-strcpy_chk.c b/debug/test-strcpy_chk.c new file mode 100644 index 0000000000..4c61f4fb43 --- /dev/null +++ b/debug/test-strcpy_chk.c @@ -0,0 +1,370 @@ +/* Test and measure __strcpy_chk functions. + Copyright (C) 1999, 2002, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Written by Jakub Jelinek <jakub@redhat.com>, 1999. + + 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. */ + +#ifndef STRCPY_RESULT +# define STRCPY_RESULT(dst, len) dst +# define TEST_MAIN +# include "../string/test-string.h" + +extern void __attribute__ ((noreturn)) __chk_fail (void); +char *simple_strcpy_chk (char *, const char *, size_t); +extern char *normal_strcpy (char *, const char *, size_t) + __asm ("strcpy"); +extern char *__strcpy_chk (char *, const char *, size_t); + +IMPL (simple_strcpy_chk, 0) +IMPL (normal_strcpy, 1) +IMPL (__strcpy_chk, 2) + +char * +simple_strcpy_chk (char *dst, const char *src, size_t len) +{ + char *ret = dst; + if (! len) + __chk_fail (); + while ((*dst++ = *src++) != '\0') + if (--len == 0) + __chk_fail (); + return ret; +} +#endif + +#include <setjmp.h> +#include <signal.h> + +volatile int chk_fail_ok; +jmp_buf chk_fail_buf; + +static void +handler (int sig) +{ + if (chk_fail_ok) + { + chk_fail_ok = 0; + longjmp (chk_fail_buf, 1); + } + else + _exit (127); +} + +typedef char *(*proto_t) (char *, const char *, size_t); + +static void +do_one_test (impl_t *impl, char *dst, const char *src, + size_t len, size_t dlen) +{ + char *res; + if (dlen <= len) + { + if (impl->test == 1) + return; + + chk_fail_ok = 1; + if (setjmp (chk_fail_buf) == 0) + { + res = CALL (impl, dst, src, dlen); + error (0, 0, "Function %s (%zd; %zd) did not __chk_fail", + impl->name, len, dlen); + chk_fail_ok = 0; + ret = 1; + } + return; + } + else + res = CALL (impl, dst, src, dlen); + + if (res != STRCPY_RESULT (dst, len)) + { + error (0, 0, "Wrong result in function %s %p %p", impl->name, + res, STRCPY_RESULT (dst, len)); + ret = 1; + return; + } + + if (strcmp (dst, src) != 0) + { + error (0, 0, "Wrong result in function %s dst \"%s\" src \"%s\"", + impl->name, dst, src); + ret = 1; + return; + } + + if (HP_TIMING_AVAIL) + { + hp_timing_t start __attribute ((unused)); + hp_timing_t stop __attribute ((unused));; + hp_timing_t best_time = ~ (hp_timing_t) 0; + size_t i; + + for (i = 0; i < 32; ++i) + { + HP_TIMING_NOW (start); + CALL (impl, dst, src, dlen); + HP_TIMING_NOW (stop); + HP_TIMING_BEST (best_time, start, stop); + } + + printf ("\t%zd", (size_t) best_time); + } +} + +static void +do_test (size_t align1, size_t align2, size_t len, size_t dlen, int max_char) +{ + size_t i; + char *s1, *s2; + + align1 &= 7; + if (align1 + len >= page_size) + return; + + align2 &= 7; + if (align2 + len >= page_size) + return; + + s1 = buf1 + align1; + s2 = buf2 + align2; + + for (i = 0; i < len; i++) + s1[i] = 32 + 23 * i % (max_char - 32); + s1[len] = 0; + + if (HP_TIMING_AVAIL && dlen > len) + printf ("Length %4zd, alignment %2zd/%2zd:", len, align1, align2); + + FOR_EACH_IMPL (impl, 0) + do_one_test (impl, s2, s1, len, dlen); + + if (HP_TIMING_AVAIL && dlen > len) + putchar ('\n'); +} + +static void +do_random_tests (void) +{ + size_t i, j, n, align1, align2, len, dlen; + unsigned char *p1 = buf1 + page_size - 512; + unsigned char *p2 = buf2 + page_size - 512; + unsigned char *res; + + for (n = 0; n < ITERATIONS; n++) + { + align1 = random () & 31; + if (random () & 1) + align2 = random () & 31; + else + align2 = align1 + (random () & 24); + len = random () & 511; + j = align1; + if (align2 > j) + j = align2; + if (len + j >= 511) + len = 510 - j - (random () & 7); + j = len + align1 + 64; + if (j > 512) + j = 512; + for (i = 0; i < j; i++) + { + if (i == len + align1) + p1[i] = 0; + else + { + p1[i] = random () & 255; + if (i >= align1 && i < len + align1 && !p1[i]) + p1[i] = (random () & 127) + 3; + } + } + + switch (random () & 7) + { + case 0: + dlen = len - (random () & 31); + if (dlen > len) + dlen = len; + break; + case 1: + dlen = (size_t) -1; + break; + case 2: + dlen = len + 1 + (random () & 65535); + break; + case 3: + dlen = len + 1 + (random () & 255); + break; + case 4: + dlen = len + 1 + (random () & 31); + break; + case 5: + dlen = len + 1 + (random () & 7); + break; + case 6: + dlen = len + 1 + (random () & 3); + break; + default: + dlen = len + 1; + break; + } + + FOR_EACH_IMPL (impl, 1) + { + if (dlen <= len) + { + if (impl->test != 1) + { + chk_fail_ok = 1; + if (setjmp (chk_fail_buf) == 0) + { + res = CALL (impl, p2 + align2, p1 + align1, dlen); + error (0, 0, "Iteration %zd - did not __chk_fail", n); + chk_fail_ok = 0; + ret = 1; + } + } + continue; + } + memset (p2 - 64, '\1', 512 + 64); + res = CALL (impl, p2 + align2, p1 + align1, dlen); + if (res != STRCPY_RESULT (p2 + align2, len)) + { + error (0, 0, "Iteration %zd - wrong result in function %s (%zd, %zd, %zd) %p != %p", + n, impl->name, align1, align2, len, res, + STRCPY_RESULT (p2 + align2, len)); + ret = 1; + } + for (j = 0; j < align2 + 64; ++j) + { + if (p2[j - 64] != '\1') + { + error (0, 0, "Iteration %zd - garbage before, %s (%zd, %zd, %zd)", + n, impl->name, align1, align2, len); + ret = 1; + break; + } + } + for (j = align2 + len + 1; j < 512; ++j) + { + if (p2[j] != '\1') + { + error (0, 0, "Iteration %zd - garbage after, %s (%zd, %zd, %zd)", + n, impl->name, align1, align2, len); + ret = 1; + break; + } + } + if (memcmp (p1 + align1, p2 + align2, len + 1)) + { + error (0, 0, "Iteration %zd - different strings, %s (%zd, %zd, %zd)", + n, impl->name, align1, align2, len); + ret = 1; + } + } + } +} + +int +test_main (void) +{ + size_t i; + + struct sigaction sa; + sa.sa_handler = handler; + sa.sa_flags = 0; + sigemptyset (&sa.sa_mask); + + sigaction (SIGABRT, &sa, NULL); + + test_init (); + + printf ("%23s", ""); + FOR_EACH_IMPL (impl, 0) + printf ("\t%s", impl->name); + putchar ('\n'); + + for (i = 0; i < 16; ++i) + { + do_test (0, 0, i, i + 1, 127); + do_test (0, 0, i, i + 1, 255); + do_test (0, i, i, i + 1, 127); + do_test (i, 0, i, i + 1, 255); + } + + for (i = 1; i < 8; ++i) + { + do_test (0, 0, 8 << i, (8 << i) + 1, 127); + do_test (8 - i, 2 * i, (8 << i), (8 << i) + 1, 127); + } + + for (i = 1; i < 8; ++i) + { + do_test (i, 2 * i, (8 << i), (8 << i) + 1, 127); + do_test (2 * i, i, (8 << i), (8 << i) + 1, 255); + do_test (i, i, (8 << i), (8 << i) + 1, 127); + do_test (i, i, (8 << i), (8 << i) + 1, 255); + } + + for (i = 0; i < 16; ++i) + { + do_test (0, 0, i, i + 256, 127); + do_test (0, 0, i, i + 256, 255); + do_test (0, i, i, i + 256, 127); + do_test (i, 0, i, i + 256, 255); + } + + for (i = 1; i < 8; ++i) + { + do_test (0, 0, 8 << i, (8 << i) + 256, 127); + do_test (8 - i, 2 * i, (8 << i), (8 << i) + 256, 127); + } + + for (i = 1; i < 8; ++i) + { + do_test (i, 2 * i, (8 << i), (8 << i) + 256, 127); + do_test (2 * i, i, (8 << i), (8 << i) + 256, 255); + do_test (i, i, (8 << i), (8 << i) + 256, 127); + do_test (i, i, (8 << i), (8 << i) + 256, 255); + } + + for (i = 0; i < 16; ++i) + { + do_test (0, 0, i, i, 127); + do_test (0, 0, i, i + 2, 255); + do_test (0, i, i, i + 3, 127); + do_test (i, 0, i, i + 4, 255); + } + + for (i = 1; i < 8; ++i) + { + do_test (0, 0, 8 << i, (8 << i) - 15, 127); + do_test (8 - i, 2 * i, (8 << i), (8 << i) + 5, 127); + } + + for (i = 1; i < 8; ++i) + { + do_test (i, 2 * i, (8 << i), (8 << i) + i, 127); + do_test (2 * i, i, (8 << i), (8 << i) + (i - 1), 255); + do_test (i, i, (8 << i), (8 << i) + i + 2, 127); + do_test (i, i, (8 << i), (8 << i) + i + 3, 255); + } + + do_random_tests (); + return ret; +} + +#include "../test-skeleton.c" diff --git a/debug/tst-chk1.c b/debug/tst-chk1.c new file mode 100644 index 0000000000..639da3847c --- /dev/null +++ b/debug/tst-chk1.c @@ -0,0 +1,466 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>, 2004. + + 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 <setjmp.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +char *temp_filename; +static void do_prepare (void); +static int do_test (void); +#define PREPARE(argc, argv) do_prepare () +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" + +static void +do_prepare (void) +{ + int temp_fd = create_temp_file ("tst-chk1.", &temp_filename); + if (temp_fd == -1) + { + printf ("cannot create temporary file: %m\n"); + exit (1); + } + + const char *strs = "abcdefgh\nABCDEFGHI\nabcdefghij\nABCDEFGHIJ"; + if (write (temp_fd, strs, strlen (strs)) != strlen (strs)) + { + puts ("could not write test strings into file"); + unlink (temp_filename); + exit (1); + } +} + +volatile int chk_fail_ok; +jmp_buf chk_fail_buf; + +static void +handler (int sig) +{ + if (chk_fail_ok) + { + chk_fail_ok = 0; + longjmp (chk_fail_buf, 1); + } + else + _exit (127); +} + +char buf[10]; +volatile size_t l0; +volatile char *p; +const char *str1 = "JIHGFEDCBA"; +const char *str2 = "F"; +const char *str3 = "%s%n%s%n"; +const char *str4 = "Hello, "; +const char *str5 = "World!\n"; +char buf2[10] = "%s"; +int num1 = 67; +int num2 = 987654; + +#define FAIL() \ + do { printf ("Failure on line %d\n", __LINE__); ret = 1; } while (0) +#define CHK_FAIL_START \ + chk_fail_ok = 1; \ + if (! setjmp (chk_fail_buf)) \ + { +#define CHK_FAIL_END \ + chk_fail_ok = 0; \ + FAIL (); \ + ret = 1; \ + } +#if __USE_FORTIFY_LEVEL >= 2 +#define CHK_FAIL2_START CHK_FAIL_START +#define CHK_FAIL2_END CHK_FAIL_END +#else +#define CHK_FAIL2_START +#define CHK_FAIL2_END +#endif + +static int +do_test (void) +{ + int ret = 0; + struct sigaction sa; + sa.sa_handler = handler; + sa.sa_flags = 0; + sigemptyset (&sa.sa_mask); + + sigaction (SIGABRT, &sa, NULL); + + struct A { char buf1[9]; char buf2[1]; } a; + + printf ("Test checking routines at fortify level %d\n", +#ifdef __USE_FORTIFY_LEVEL + (int) __USE_FORTIFY_LEVEL +#else + 0 +#endif + ); + + /* These ops can be done without runtime checking of object size. */ + memcpy (buf, "abcdefghij", 10); + memmove (buf + 1, buf, 9); + if (memcmp (buf, "aabcdefghi", 10)) + FAIL (); + + if (mempcpy (buf + 5, "abcde", 5) != buf + 10 || memcmp (buf, "aabcdabcde", 10)) + FAIL (); + + memset (buf + 8, 'j', 2); + if (memcmp (buf, "aabcdabcjj", 10)) + FAIL (); + + strcpy (buf + 4, "EDCBA"); + if (memcmp (buf, "aabcEDCBA", 10)) + FAIL (); + + if (stpcpy (buf + 8, "F") != buf + 9 || memcmp (buf, "aabcEDCBF", 10)) + FAIL (); + + strncpy (buf + 6, "X", 4); + if (memcmp (buf, "aabcEDX\0\0", 10)) + FAIL (); + + if (sprintf (buf + 7, "%s", "67") != 2 || memcmp (buf, "aabcEDX67", 10)) + FAIL (); + + if (snprintf (buf + 7, 3, "%s", "987654") != 6 + || memcmp (buf, "aabcEDX98", 10)) + FAIL (); + + /* These ops need runtime checking, but shouldn't __chk_fail. */ + memcpy (buf, "abcdefghij", l0 + 10); + memmove (buf + 1, buf, l0 + 9); + if (memcmp (buf, "aabcdefghi", 10)) + FAIL (); + + if (mempcpy (buf + 5, "abcde", l0 + 5) != buf + 10 || memcmp (buf, "aabcdabcde", 10)) + FAIL (); + + memset (buf + 8, 'j', l0 + 2); + if (memcmp (buf, "aabcdabcjj", 10)) + FAIL (); + + strcpy (buf + 4, str1 + 5); + if (memcmp (buf, "aabcEDCBA", 10)) + FAIL (); + + if (stpcpy (buf + 8, str2) != buf + 9 || memcmp (buf, "aabcEDCBF", 10)) + FAIL (); + + strncpy (buf + 6, "X", l0 + 4); + if (memcmp (buf, "aabcEDX\0\0", 10)) + FAIL (); + + if (sprintf (buf + 7, "%d", num1) != 2 || memcmp (buf, "aabcEDX67", 10)) + FAIL (); + + if (snprintf (buf + 7, 3, "%d", num2) != 6 || memcmp (buf, "aabcEDX98", 10)) + FAIL (); + + buf[l0 + 8] = '\0'; + strcat (buf, "A"); + if (memcmp (buf, "aabcEDX9A", 10)) + FAIL (); + + buf[l0 + 7] = '\0'; + strncat (buf, "ZYXWV", l0 + 2); + if (memcmp (buf, "aabcEDXZY", 10)) + FAIL (); + + memcpy (a.buf1, "abcdefghij", l0 + 10); + memmove (a.buf1 + 1, a.buf1, l0 + 9); + if (memcmp (a.buf1, "aabcdefghi", 10)) + FAIL (); + + if (mempcpy (a.buf1 + 5, "abcde", l0 + 5) != a.buf1 + 10 + || memcmp (a.buf1, "aabcdabcde", 10)) + FAIL (); + + memset (a.buf1 + 8, 'j', l0 + 2); + if (memcmp (a.buf1, "aabcdabcjj", 10)) + FAIL (); + +#if __USE_FORTIFY_LEVEL < 2 + /* The following tests are supposed to crash with -D_FORTIFY_SOURCE=2 + and sufficient GCC support, as the string operations overflow + from a.buf1 into a.buf2. */ + strcpy (a.buf1 + 4, str1 + 5); + if (memcmp (a.buf1, "aabcEDCBA", 10)) + FAIL (); + + if (stpcpy (a.buf1 + 8, str2) != a.buf1 + 9 || memcmp (a.buf1, "aabcEDCBF", 10)) + FAIL (); + + strncpy (a.buf1 + 6, "X", l0 + 4); + if (memcmp (a.buf1, "aabcEDX\0\0", 10)) + FAIL (); + + if (sprintf (a.buf1 + 7, "%d", num1) != 2 || memcmp (a.buf1, "aabcEDX67", 10)) + FAIL (); + + if (snprintf (a.buf1 + 7, 3, "%d", num2) != 6 + || memcmp (a.buf1, "aabcEDX98", 10)) + FAIL (); + + a.buf1[l0 + 8] = '\0'; + strcat (a.buf1, "A"); + if (memcmp (a.buf1, "aabcEDX9A", 10)) + FAIL (); + + a.buf1[l0 + 7] = '\0'; + strncat (a.buf1, "ZYXWV", l0 + 2); + if (memcmp (a.buf1, "aabcEDXZY", 10)) + FAIL (); + +#endif + +#if __USE_FORTIFY_LEVEL >= 1 + /* Now check if all buffer overflows are caught at runtime. */ + + CHK_FAIL_START + memcpy (buf + 1, "abcdefghij", l0 + 10); + CHK_FAIL_END + + CHK_FAIL_START + memmove (buf + 2, buf + 1, l0 + 9); + CHK_FAIL_END + + CHK_FAIL_START + p = mempcpy (buf + 6, "abcde", l0 + 5); + CHK_FAIL_END + + CHK_FAIL_START + memset (buf + 9, 'j', l0 + 2); + CHK_FAIL_END + + CHK_FAIL_START + strcpy (buf + 5, str1 + 5); + CHK_FAIL_END + + CHK_FAIL_START + p = stpcpy (buf + 9, str2); + CHK_FAIL_END + + CHK_FAIL_START + strncpy (buf + 7, "X", l0 + 4); + CHK_FAIL_END + + CHK_FAIL_START + sprintf (buf + 8, "%d", num1); + CHK_FAIL_END + + CHK_FAIL_START + snprintf (buf + 8, l0 + 3, "%d", num2); + CHK_FAIL_END + + memcpy (buf, str1 + 2, l0 + 9); + CHK_FAIL_START + strcat (buf, "AB"); + CHK_FAIL_END + + memcpy (buf, str1 + 3, l0 + 8); + CHK_FAIL_START + strncat (buf, "ZYXWV", l0 + 3); + CHK_FAIL_END + + CHK_FAIL_START + memcpy (a.buf1 + 1, "abcdefghij", l0 + 10); + CHK_FAIL_END + + CHK_FAIL_START + memmove (a.buf1 + 2, a.buf1 + 1, l0 + 9); + CHK_FAIL_END + + CHK_FAIL_START + p = mempcpy (a.buf1 + 6, "abcde", l0 + 5); + CHK_FAIL_END + + CHK_FAIL_START + memset (a.buf1 + 9, 'j', l0 + 2); + CHK_FAIL_END + +#if __USE_FORTIFY_LEVEL >= 2 +# define O 0 +#else +# define O 1 +#endif + + CHK_FAIL_START + strcpy (a.buf1 + (O + 4), str1 + 5); + CHK_FAIL_END + + CHK_FAIL_START + p = stpcpy (a.buf1 + (O + 8), str2); + CHK_FAIL_END + + CHK_FAIL_START + strncpy (a.buf1 + (O + 6), "X", l0 + 4); + CHK_FAIL_END + + CHK_FAIL_START + sprintf (a.buf1 + (O + 7), "%d", num1); + CHK_FAIL_END + + CHK_FAIL_START + snprintf (a.buf1 + (O + 7), l0 + 3, "%d", num2); + CHK_FAIL_END + + memcpy (a.buf1, str1 + (3 - O), l0 + 8 + O); + CHK_FAIL_START + strcat (a.buf1, "AB"); + CHK_FAIL_END + + memcpy (a.buf1, str1 + (4 - O), l0 + 7 + O); + CHK_FAIL_START + strncat (a.buf1, "ZYXWV", l0 + 3); + CHK_FAIL_END +#endif + + /* Now checks for %n protection. */ + + /* Constant literals passed directly are always ok + (even with warnings about possible bugs from GCC). */ + int n1, n2; + if (sprintf (buf, "%s%n%s%n", str2, &n1, str2, &n2) != 2 + || n1 != 1 || n2 != 2) + FAIL (); + + /* In this case the format string is not known at compile time, + but resides in read-only memory, so is ok. */ + if (snprintf (buf, 4, str3, str2, &n1, str2, &n2) != 2 + || n1 != 1 || n2 != 2) + FAIL (); + + strcpy (buf2 + 2, "%n%s%n"); + /* When the format string is writable and contains %n, + with -D_FORTIFY_SOURCE=2 it causes __chk_fail. */ + CHK_FAIL2_START + if (sprintf (buf, buf2, str2, &n1, str2, &n1) != 2) + FAIL (); + CHK_FAIL2_END + + CHK_FAIL2_START + if (snprintf (buf, 3, buf2, str2, &n1, str2, &n1) != 2) + FAIL (); + CHK_FAIL2_END + + /* But if there is no %n, even writable format string + should work. */ + buf2[6] = '\0'; + if (sprintf (buf, buf2 + 4, str2) != 1) + FAIL (); + + /* Constant literals passed directly are always ok + (even with warnings about possible bugs from GCC). */ + if (printf ("%s%n%s%n", str4, &n1, str5, &n2) != 14 + || n1 != 7 || n2 != 14) + FAIL (); + + /* In this case the format string is not known at compile time, + but resides in read-only memory, so is ok. */ + if (printf (str3, str4, &n1, str5, &n2) != 14 + || n1 != 7 || n2 != 14) + FAIL (); + + strcpy (buf2 + 2, "%n%s%n"); + /* When the format string is writable and contains %n, + with -D_FORTIFY_SOURCE=2 it causes __chk_fail. */ + CHK_FAIL2_START + if (printf (buf2, str4, &n1, str5, &n1) != 14) + FAIL (); + CHK_FAIL2_END + + /* But if there is no %n, even writable format string + should work. */ + buf2[6] = '\0'; + if (printf (buf2 + 4, str5) != 7) + FAIL (); + + FILE *fp = stdout; + + /* Constant literals passed directly are always ok + (even with warnings about possible bugs from GCC). */ + if (fprintf (fp, "%s%n%s%n", str4, &n1, str5, &n2) != 14 + || n1 != 7 || n2 != 14) + FAIL (); + + /* In this case the format string is not known at compile time, + but resides in read-only memory, so is ok. */ + if (fprintf (fp, str3, str4, &n1, str5, &n2) != 14 + || n1 != 7 || n2 != 14) + FAIL (); + + strcpy (buf2 + 2, "%n%s%n"); + /* When the format string is writable and contains %n, + with -D_FORTIFY_SOURCE=2 it causes __chk_fail. */ + CHK_FAIL2_START + if (fprintf (fp, buf2, str4, &n1, str5, &n1) != 14) + FAIL (); + CHK_FAIL2_END + + /* But if there is no %n, even writable format string + should work. */ + buf2[6] = '\0'; + if (fprintf (fp, buf2 + 4, str5) != 7) + FAIL (); + + if (freopen (temp_filename, "r", stdin) == NULL) + { + puts ("could not open temporary file"); + exit (1); + } + + if (gets (buf) != buf || memcmp (buf, "abcdefgh", 9)) + FAIL (); + if (gets (buf) != buf || memcmp (buf, "ABCDEFGHI", 10)) + FAIL (); + +#if __USE_FORTIFY_LEVEL >= 1 + CHK_FAIL_START + if (gets (buf) != buf) + FAIL (); + CHK_FAIL_END +#endif + + if (freopen (temp_filename, "r", stdin) == NULL) + { + puts ("could not open temporary file"); + exit (1); + } + + if (fseek (stdin, 9 + 10 + 11, SEEK_SET)) + { + puts ("could not seek in test file"); + exit (1); + } + +#if __USE_FORTIFY_LEVEL >= 1 + CHK_FAIL_START + if (gets (buf) != buf) + FAIL (); + CHK_FAIL_END +#endif + + return ret; +} diff --git a/debug/tst-chk2.c b/debug/tst-chk2.c new file mode 100644 index 0000000000..be37ce2d22 --- /dev/null +++ b/debug/tst-chk2.c @@ -0,0 +1,2 @@ +#define _FORTIFY_SOURCE 1 +#include "tst-chk1.c" diff --git a/debug/tst-chk3.c b/debug/tst-chk3.c new file mode 100644 index 0000000000..38b8e4fb36 --- /dev/null +++ b/debug/tst-chk3.c @@ -0,0 +1,2 @@ +#define _FORTIFY_SOURCE 2 +#include "tst-chk1.c" diff --git a/debug/vfprintf_chk.c b/debug/vfprintf_chk.c new file mode 100644 index 0000000000..a9e107d8e5 --- /dev/null +++ b/debug/vfprintf_chk.c @@ -0,0 +1,42 @@ +/* Copyright (C) 1991, 1995, 1996, 1997, 2001, 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 <stdarg.h> +#include <stdio.h> +#include "../libio/libioP.h" + + +/* Write formatted output to FP from the format string FORMAT. */ +int +__vfprintf_chk (FILE *fp, int flag, const char *format, va_list ap) +{ + int done; + + _IO_acquire_lock (fp); + if (flag > 0) + fp->_flags2 |= _IO_FLAGS2_CHECK_PERCENT_N; + + done = vfprintf (fp, format, ap); + + if (flag > 0) + fp->_flags2 &= ~_IO_FLAGS2_CHECK_PERCENT_N; + _IO_release_lock (fp); + + return done; +} diff --git a/debug/vprintf_chk.c b/debug/vprintf_chk.c new file mode 100644 index 0000000000..f477f15411 --- /dev/null +++ b/debug/vprintf_chk.c @@ -0,0 +1,42 @@ +/* Copyright (C) 1991, 1995, 1996, 1997, 2001, 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 <stdarg.h> +#include <stdio.h> +#include "../libio/libioP.h" + + +/* Write formatted output to stdout from the format string FORMAT. */ +int +__vprintf_chk (int flag, const char *format, va_list ap) +{ + int done; + + _IO_acquire_lock (stdout); + if (flag > 0) + stdout->_flags2 |= _IO_FLAGS2_CHECK_PERCENT_N; + + done = vfprintf (stdout, format, ap); + + if (flag > 0) + stdout->_flags2 &= ~_IO_FLAGS2_CHECK_PERCENT_N; + _IO_release_lock (stdout); + + return done; +} diff --git a/debug/vsnprintf_chk.c b/debug/vsnprintf_chk.c new file mode 100644 index 0000000000..850cd5af5a --- /dev/null +++ b/debug/vsnprintf_chk.c @@ -0,0 +1,70 @@ +/* Copyright (C) 1991, 1995, 1997, 1998, 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 <stdarg.h> +#include <stdio.h> +#include "../libio/libioP.h" +#include "../libio/strfile.h" + +extern const struct _IO_jump_t _IO_strn_jumps attribute_hidden; + +/* Write formatted output into S, according to the format + string FORMAT, writing no more than MAXLEN characters. */ +/* VARARGS5 */ +int +__vsnprintf_chk (char *s, size_t maxlen, int flags, size_t slen, + const char *format, va_list args) +{ + /* XXX Maybe for less strict version do not fail immediately. + Though, maxlen is supposed to be the size of buffer pointed + to by s, so a conforming program can't pass such maxlen + to *snprintf. */ + if (__builtin_expect (slen < maxlen, 0)) + __chk_fail (); + + _IO_strnfile sf; + int ret; +#ifdef _IO_MTSAFE_IO + sf.f._sbf._f._lock = NULL; +#endif + + /* We need to handle the special case where MAXLEN is 0. Use the + overflow buffer right from the start. */ + if (maxlen == 0) + { + s = sf.overflow_buf; + maxlen = sizeof (sf.overflow_buf); + } + + _IO_no_init (&sf.f._sbf._f, _IO_USER_LOCK, -1, NULL, NULL); + _IO_JUMPS ((struct _IO_FILE_plus *) &sf.f._sbf) = &_IO_strn_jumps; + s[0] = '\0'; + + /* For flags > 0 (i.e. __USE_FORTIFY_LEVEL > 1) request that %n + can only come from read-only format strings. */ + if (flags > 0) + sf.f._sbf._f._flags2 |= _IO_FLAGS2_CHECK_PERCENT_N; + + _IO_str_init_static_internal (&sf.f, s, maxlen - 1, s); + ret = INTUSE(_IO_vfprintf) ((_IO_FILE *) &sf.f._sbf, format, args); + + if (sf.f._sbf._f._IO_buf_base != sf.overflow_buf) + *sf.f._sbf._f._IO_write_ptr = '\0'; + return ret; +} +libc_hidden_def (__vsnprintf_chk) diff --git a/debug/vsprintf_chk.c b/debug/vsprintf_chk.c new file mode 100644 index 0000000000..83383286da --- /dev/null +++ b/debug/vsprintf_chk.c @@ -0,0 +1,91 @@ +/* Copyright (C) 1994, 1997, 1999-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 <stdarg.h> +#include <stdio.h> +#include "../libio/libioP.h" +#include "../libio/strfile.h" + + +static int _IO_str_chk_overflow (_IO_FILE *fp, int c) __THROW; + +static int +_IO_str_chk_overflow (fp, c) + _IO_FILE *fp; + int c; +{ + /* When we come to here this means the user supplied buffer is + filled. */ + __chk_fail (); +} + + +static const struct _IO_jump_t _IO_str_chk_jumps = +{ + JUMP_INIT_DUMMY, + JUMP_INIT(finish, _IO_str_finish), + JUMP_INIT(overflow, _IO_str_chk_overflow), + JUMP_INIT(underflow, INTUSE(_IO_str_underflow)), + JUMP_INIT(uflow, INTUSE(_IO_default_uflow)), + JUMP_INIT(pbackfail, INTUSE(_IO_str_pbackfail)), + JUMP_INIT(xsputn, INTUSE(_IO_default_xsputn)), + JUMP_INIT(xsgetn, INTUSE(_IO_default_xsgetn)), + JUMP_INIT(seekoff, INTUSE(_IO_str_seekoff)), + JUMP_INIT(seekpos, _IO_default_seekpos), + JUMP_INIT(setbuf, _IO_default_setbuf), + JUMP_INIT(sync, _IO_default_sync), + JUMP_INIT(doallocate, INTUSE(_IO_default_doallocate)), + JUMP_INIT(read, _IO_default_read), + JUMP_INIT(write, _IO_default_write), + JUMP_INIT(seek, _IO_default_seek), + JUMP_INIT(close, _IO_default_close), + JUMP_INIT(stat, _IO_default_stat), + JUMP_INIT(showmanyc, _IO_default_showmanyc), + JUMP_INIT(imbue, _IO_default_imbue) +}; + + +int +__vsprintf_chk (char *s, int flags, size_t slen, const char *format, + va_list args) +{ + _IO_strfile f; + int ret; +#ifdef _IO_MTSAFE_IO + f._sbf._f._lock = NULL; +#endif + + if (slen == 0) + __chk_fail (); + + _IO_no_init (&f._sbf._f, _IO_USER_LOCK, -1, NULL, NULL); + _IO_JUMPS ((struct _IO_FILE_plus *) &f._sbf) = &_IO_str_chk_jumps; + s[0] = '\0'; + _IO_str_init_static_internal (&f, s, slen - 1, s); + + /* For flags > 0 (i.e. __USE_FORTIFY_LEVEL > 1) request that %n + can only come from read-only format strings. */ + if (flags > 0) + f._sbf._f._flags2 |= _IO_FLAGS2_CHECK_PERCENT_N; + + ret = INTUSE(_IO_vfprintf) ((_IO_FILE *) &f._sbf, format, args); + + *f._sbf._f._IO_write_ptr = '\0'; + return ret; +} +libc_hidden_def (__vsprintf_chk) diff --git a/elf/dl-minimal.c b/elf/dl-minimal.c index 4ec2ebcbb4..adb85e6753 100644 --- a/elf/dl-minimal.c +++ b/elf/dl-minimal.c @@ -354,6 +354,13 @@ __strsep (char **stringp, const char *delim) weak_alias (__strsep, strsep) strong_alias (__strsep, __strsep_g) +void +__attribute__ ((noreturn)) +__chk_fail (void) +{ + _exit (127); +} +rtld_hidden_def (__chk_fail) /* The '_itoa_lower_digits' variable in libc.so is able to handle bases up to 36. We don't need this here. */ diff --git a/fedora/branch.mk b/fedora/branch.mk index 939c3e1144..d97f635a5d 100644 --- a/fedora/branch.mk +++ b/fedora/branch.mk @@ -1,5 +1,5 @@ # This file is updated automatically by Makefile. glibc-branch := fedora glibc-base := HEAD -fedora-sync-date := 2004-10-14 05:48 UTC -fedora-sync-tag := fedora-glibc-20041014T0548 +fedora-sync-date := 2004-10-18 09:40 UTC +fedora-sync-tag := fedora-glibc-20041018T0940 diff --git a/fedora/glibc.spec.in b/fedora/glibc.spec.in index b32811dd1f..7b263153e0 100644 --- a/fedora/glibc.spec.in +++ b/fedora/glibc.spec.in @@ -1,4 +1,4 @@ -%define glibcrelease 68 +%define glibcrelease 69 %define auxarches i586 i686 athlon sparcv9 alphaev6 %define prelinkarches noarch %define nptlarches i386 i686 athlon x86_64 ia64 s390 s390x sparcv9 ppc ppc64 @@ -1239,6 +1239,10 @@ rm -f *.filelist* %endif %changelog +* Mon Oct 18 2004 Jakub Jelinek <jakub@redhat.com> 2.3.3-69 +- update from CVS + - object size checking support (-D_FORTIFY_SOURCE={1,2}) + * Thu Oct 14 2004 Jakub Jelinek <jakub@redhat.com> 2.3.3-68 - update from CVS - support for namespaces in the dynamic linker diff --git a/include/bits/string3.h b/include/bits/string3.h new file mode 100644 index 0000000000..1ddd981a90 --- /dev/null +++ b/include/bits/string3.h @@ -0,0 +1 @@ +#include <string/bits/string3.h> diff --git a/include/features.h b/include/features.h index 221b25ffe2..9940304ccb 100644 --- a/include/features.h +++ b/include/features.h @@ -41,6 +41,8 @@ _GNU_SOURCE All of the above, plus GNU extensions. _REENTRANT Select additionally reentrant object. _THREAD_SAFE Same as _REENTRANT, often used by other systems. + _FORTIFY_SOURCE If set to numeric value > 0 additional security + measures are defined, according to level. The `-ansi' switch to the GNU C compiler defines __STRICT_ANSI__. If none of these are defined, the default is to have _SVID_SOURCE, @@ -69,6 +71,7 @@ __USE_MISC Define things common to BSD and System V Unix. __USE_GNU Define GNU extensions. __USE_REENTRANT Define reentrant/thread-safe *_r functions. + __USE_FORTIFY_LEVEL Additional security measures used, according to level. __FAVOR_BSD Favor 4.3BSD things in cases of conflict. The macros `__GNU_LIBRARY__', `__GLIBC__', and `__GLIBC_MINOR__' are @@ -101,6 +104,7 @@ #undef __USE_MISC #undef __USE_GNU #undef __USE_REENTRANT +#undef __USE_FORTIFY_LEVEL #undef __FAVOR_BSD #undef __KERNEL_STRICT_NAMES @@ -113,6 +117,20 @@ /* Always use ISO C things. */ #define __USE_ANSI 1 +/* Convenience macros to test the versions of glibc and gcc. + Use them like this: + #if __GNUC_PREREQ (2,8) + ... code requiring gcc 2.8 or later ... + #endif + Note - they won't work for gcc1 or glibc1, since the _MINOR macros + were not defined then. */ +#if defined __GNUC__ && defined __GNUC_MINOR__ +# define __GNUC_PREREQ(maj, min) \ + ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) +#else +# define __GNUC_PREREQ(maj, min) 0 +#endif + /* If _BSD_SOURCE was defined by the user, favor BSD over POSIX. */ #if defined _BSD_SOURCE && \ @@ -244,6 +262,14 @@ # define __USE_REENTRANT 1 #endif +#if _FORTIFY_SOURCE > 0 && __GNUC_PREREQ (4, 1) && __OPTIMIZE__ > 0 +# if _FORTIFY_SOURCE == 1 +# define __USE_FORTIFY_LEVEL 1 +# elif _FORTIFY_SOURCE > 1 +# define __USE_FORTIFY_LEVEL 2 +# endif +#endif + /* We do support the IEC 559 math functionality, real and complex. */ #define __STDC_IEC_559__ 1 #define __STDC_IEC_559_COMPLEX__ 1 @@ -265,20 +291,6 @@ #define __GLIBC__ 2 #define __GLIBC_MINOR__ 3 -/* Convenience macros to test the versions of glibc and gcc. - Use them like this: - #if __GNUC_PREREQ (2,8) - ... code requiring gcc 2.8 or later ... - #endif - Note - they won't work for gcc1 or glibc1, since the _MINOR macros - were not defined then. */ -#if defined __GNUC__ && defined __GNUC_MINOR__ -# define __GNUC_PREREQ(maj, min) \ - ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) -#else -# define __GNUC_PREREQ(maj, min) 0 -#endif - #define __GLIBC_PREREQ(maj, min) \ ((__GLIBC__ << 16) + __GLIBC_MINOR__ >= ((maj) << 16) + (min)) diff --git a/include/libc-symbols.h b/include/libc-symbols.h index 9cc72b261a..e7880b6c46 100644 --- a/include/libc-symbols.h +++ b/include/libc-symbols.h @@ -744,6 +744,24 @@ for linking") # define libm_hidden_data_ver(local, name) #endif +#if defined NOT_IN_libc && defined IS_IN_libresolv +# define libresolv_hidden_proto(name, attrs...) hidden_proto (name, ##attrs) +# define libresolv_hidden_def(name) hidden_def (name) +# define libresolv_hidden_weak(name) hidden_weak (name) +# define libresolv_hidden_ver(local, name) hidden_ver (local, name) +# define libresolv_hidden_data_def(name) hidden_data_def (name) +# define libresolv_hidden_data_weak(name) hidden_data_weak (name) +# define libresolv_hidden_data_ver(local, name) hidden_data_ver (local, name) +#else +# define libresolv_hidden_proto(name, attrs...) +# define libresolv_hidden_def(name) +# define libresolv_hidden_weak(name) +# define libresolv_hidden_ver(local, name) +# define libresolv_hidden_data_def(name) +# define libresolv_hidden_data_weak(name) +# define libresolv_hidden_data_ver(local, name) +#endif + #ifdef HAVE_BUILTIN_REDIRECTION # define libc_hidden_builtin_proto(name, attrs...) libc_hidden_proto (name, ##attrs) # define libc_hidden_builtin_def(name) libc_hidden_def (name) diff --git a/include/resolv.h b/include/resolv.h index d62a8ff1e5..6f1c343b4a 100644 --- a/include/resolv.h +++ b/include/resolv.h @@ -60,6 +60,44 @@ int __libc_res_nsend (res_state, const u_char *, int, u_char *, int, u_char **) attribute_hidden; +libresolv_hidden_proto (_sethtent) +libresolv_hidden_proto (_gethtent) +libresolv_hidden_proto (_gethtbyaddr) +libresolv_hidden_proto (_gethtbyname2) +libresolv_hidden_proto (__dn_expand) +libresolv_hidden_proto (__dn_comp) +libresolv_hidden_proto (__dn_skipname) +libresolv_hidden_proto (__res_hnok) +libresolv_hidden_proto (__res_dnok) +libresolv_hidden_proto (__putlong) +libresolv_hidden_proto (__putshort) +libresolv_hidden_proto (__p_cdnname) +libresolv_hidden_proto (__p_fqnname) +libresolv_hidden_proto (__p_option) +libresolv_hidden_proto (__sym_ntos) +libresolv_hidden_proto (__p_rcode) +libresolv_hidden_proto (__p_class) +libresolv_hidden_proto (__p_type) +libresolv_hidden_proto (__loc_ntoa) +libresolv_hidden_proto (__fp_nquery) +libresolv_hidden_proto (__fp_query) +libresolv_hidden_proto (__hostalias) +libresolv_hidden_proto (__res_nmkquery) +libresolv_hidden_proto (__libc_res_nquery) +libresolv_hidden_proto (__res_nquery) +libresolv_hidden_proto (__res_nquerydomain) +libresolv_hidden_proto (__res_hostalias) +libresolv_hidden_proto (__libc_res_nsearch) +libresolv_hidden_proto (__res_nsearch) +libresolv_hidden_proto (__res_nameinquery) +libresolv_hidden_proto (__res_queriesmatch) +libresolv_hidden_proto (__res_nsend) +libresolv_hidden_proto (__b64_ntop) +libresolv_hidden_proto (__ns_name_ntop) +libresolv_hidden_proto (__ns_name_unpack) +libresolv_hidden_proto (__ns_get16) +libresolv_hidden_proto (__ns_get32) + #endif #endif diff --git a/include/stdio.h b/include/stdio.h index b871abc15e..05a91b4cb3 100644 --- a/include/stdio.h +++ b/include/stdio.h @@ -27,6 +27,18 @@ extern int __vsscanf (__const char *__restrict __s, _G_va_list __arg) __attribute__ ((__format__ (__scanf__, 2, 0))); +extern int __sprintf_chk (char *, int, size_t, const char *, ...) __THROW; +extern int __snprintf_chk (char *, size_t, int, size_t, const char *, ...) + __THROW; +extern int __vsprintf_chk (char *, int, size_t, const char *, + _G_va_list) __THROW; +extern int __vsnprintf_chk (char *, size_t, int, size_t, const char *, + _G_va_list) __THROW; +extern int __printf_chk (int, const char *, ...); +extern int __fprintf_chk (FILE *, int, const char *, ...); +extern int __vprintf_chk (int, const char *, _G_va_list); +extern int __vfprintf_chk (FILE *, int, const char *, _G_va_list); + /* Prototypes for compatibility functions. */ extern FILE *__new_tmpfile (void); extern FILE *__old_tmpfile (void); @@ -109,6 +121,8 @@ libc_hidden_proto (fgets_unlocked) libc_hidden_proto (fputs_unlocked) libc_hidden_proto (open_memstream) libc_hidden_proto (__libc_fatal) +libc_hidden_proto (__vsprintf_chk) +libc_hidden_proto (__vsnprintf_chk) # if !defined NOT_IN_libc && defined SHARED && defined DO_VERSIONING \ && defined HAVE_VISIBILITY_ATTRIBUTE && !defined HAVE_BROKEN_ALIAS_ATTRIBUTE\ diff --git a/include/string.h b/include/string.h index afc6adfbda..738dd8e27c 100644 --- a/include/string.h +++ b/include/string.h @@ -3,7 +3,7 @@ #include <sys/types.h> extern void *__memccpy (void *__dest, __const void *__src, - int __c, size_t __n); + int __c, size_t __n); extern size_t __strnlen (__const char *__string, size_t __maxlen) __attribute_pure__; @@ -114,4 +114,30 @@ libc_hidden_builtin_proto (ffs) # endif # endif +extern void *__memcpy_chk (void *__restrict __dest, + const void *__restrict __src, size_t __len, + size_t __destlen) __THROW; +extern void *__memmove_chk (void *__dest, const void *__src, size_t __len, + size_t __destlen) __THROW; +extern void *__mempcpy_chk (void *__restrict __dest, + const void *__restrict __src, size_t __len, + size_t __destlen) __THROW; +extern void *__memset_chk (void *__dest, int __ch, size_t __len, + size_t __destlen) __THROW; +extern char *__strcpy_chk (char *__restrict __dest, + const char *__restrict __src, + size_t __destlen) __THROW; +extern char *__stpcpy_chk (char *__restrict __dest, + const char *__restrict __src, + size_t __destlen) __THROW; +extern char *__strncpy_chk (char *__restrict __dest, + const char *__restrict __src, + size_t __len, size_t __destlen) __THROW; +extern char *__strcat_chk (char *__restrict __dest, + const char *__restrict __src, + size_t __destlen) __THROW; +extern char *__strncat_chk (char *__restrict __dest, + const char *__restrict __src, + size_t __len, size_t __destlen) __THROW; + #endif diff --git a/include/sys/cdefs.h b/include/sys/cdefs.h index 200abb4f02..8ba980477d 100644 --- a/include/sys/cdefs.h +++ b/include/sys/cdefs.h @@ -1 +1,9 @@ +#ifndef _SYS_CDEFS_H + #include <misc/sys/cdefs.h> + +extern void __chk_fail (void) __attribute__ ((__noreturn__)); +libc_hidden_proto (__chk_fail) +rtld_hidden_proto (__chk_fail) + +#endif diff --git a/libio/Makefile b/libio/Makefile index c7253ff571..a9384b55a9 100644 --- a/libio/Makefile +++ b/libio/Makefile @@ -1,4 +1,4 @@ -# Copyright (C) 1995-2002, 2003 Free Software Foundation, Inc. +# Copyright (C) 1995-2002, 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 @@ -22,7 +22,7 @@ subdir := libio headers := stdio.h libio.h _G_config.h bits/stdio.h bits/stdio-lock.h \ - bits/sys_errlist.h + bits/sys_errlist.h bits/stdio2.h routines := \ filedoalloc iofclose iofdopen iofflush iofgetpos iofgets iofopen \ diff --git a/libio/bits/stdio2.h b/libio/bits/stdio2.h new file mode 100644 index 0000000000..acf07ea91b --- /dev/null +++ b/libio/bits/stdio2.h @@ -0,0 +1,78 @@ +/* Checking macros for stdio functions. + 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. */ + +#ifndef _STDIO_H +# error "Never include <bits/stdio2.h> directly; use <stdio.h> instead." +#endif + +extern int __sprintf_chk (char *__restrict __s, int __flag, size_t __slen, + __const char *__restrict __format, ...) __THROW; +extern int __vsprintf_chk (char *__restrict __s, int __flag, size_t __slen, + __const char *__restrict __format, + _G_va_list __ap) __THROW; + +#define sprintf(str, ...) \ + __builtin___sprintf_chk (str, __USE_FORTIFY_LEVEL - 1, __bos (str), \ + __VA_ARGS__) +#define vsprintf(str, fmt, ap) \ + __builtin___vsprintf_chk (str, __USE_FORTIFY_LEVEL - 1, __bos (str), fmt, ap) + +#if defined __USE_BSD || defined __USE_ISOC99 || defined __USE_UNIX98 + +extern int __snprintf_chk (char *__restrict __s, size_t __n, int __flag, + size_t __slen, __const char *__restrict __format, + ...) __THROW; +extern int __vsnprintf_chk (char *__restrict __s, size_t __n, int __flag, + size_t __slen, __const char *__restrict __format, + _G_va_list __ap) __THROW; + +# define snprintf(str, len, ...) \ + __builtin___snprintf_chk (str, len, __USE_FORTIFY_LEVEL - 1, __bos (str), \ + __VA_ARGS__) +# define vsnprintf(str, len, fmt, ap) \ + __builtin___vsnprintf_chk (str, len, __USE_FORTIFY_LEVEL - 1, __bos (str), \ + fmt, ap) + +#endif + +#if __USE_FORTIFY_LEVEL > 1 + +extern int __fprintf_chk (FILE *__restrict __stream, int __flag, + __const char *__restrict __format, ...); +extern int __printf_chk (int __flag, __const char *__restrict __format, ...); +extern int __vfprintf_chk (FILE *__restrict __stream, int __flag, + __const char *__restrict __format, _G_va_list __ap); +extern int __vprintf_chk (int __flag, __const char *__restrict __format, + _G_va_list __ap); + +# define printf(...) \ + __printf_chk (__USE_FORTIFY_LEVEL - 1, __VA_ARGS__) +# define fprintf(stream, ...) \ + __fprintf_chk (stream, __USE_FORTIFY_LEVEL - 1, __VA_ARGS__) +# define vprintf(format, ap) \ + __vprintf_chk (__USE_FORTIFY_LEVEL - 1, format, ap) +# define vfprintf(stream, format, ap) \ + __vfprintf_chk (stream, __USE_FORTIFY_LEVEL - 1, format, ap) + +#endif + +extern char *__gets_chk (char *__str, size_t); +#define gets(__str) \ + ((__bos (__str) == (size_t) -1) \ + ? (gets) (__str) : __gets_chk (__str, __bos (__str))) diff --git a/libio/libio.h b/libio/libio.h index 1672f7b54f..645f9fb83c 100644 --- a/libio/libio.h +++ b/libio/libio.h @@ -139,6 +139,9 @@ #define _IO_FLAGS2_MMAP 1 #define _IO_FLAGS2_NOTCANCEL 2 +#ifdef _LIBC +# define _IO_FLAGS2_CHECK_PERCENT_N 4 +#endif /* These are "formatting flags" matching the iostream fmtflags enum values. */ #define _IO_SKIPWS 01 diff --git a/libio/stdio.h b/libio/stdio.h index 385bc64618..941a2afc74 100644 --- a/libio/stdio.h +++ b/libio/stdio.h @@ -829,6 +829,9 @@ extern void funlockfile (FILE *__stream) __THROW; #ifdef __USE_EXTERN_INLINES # include <bits/stdio.h> #endif +#if __USE_FORTIFY_LEVEL > 0 && !defined __cplusplus +# include <bits/stdio2.h> +#endif __END_DECLS diff --git a/libio/strfile.h b/libio/strfile.h index bcac784717..b91111a9d6 100644 --- a/libio/strfile.h +++ b/libio/strfile.h @@ -63,3 +63,13 @@ typedef struct _IO_strfile_ /* frozen: set when the program has requested that the array object not be altered, reallocated, or freed. */ #define _IO_STR_FROZEN(FP) ((FP)->_f._IO_file_flags & _IO_USER_BUF) + +typedef struct +{ + _IO_strfile f; + /* This is used for the characters which do not fit in the buffer + provided by the user. */ + char overflow_buf[64]; +} _IO_strnfile; + +extern const struct _IO_jump_t _IO_strn_jumps attribute_hidden; diff --git a/libio/vsnprintf.c b/libio/vsnprintf.c index e2cfb16d8a..4250c2d2de 100644 --- a/libio/vsnprintf.c +++ b/libio/vsnprintf.c @@ -28,16 +28,6 @@ #include "libioP.h" #include "strfile.h" - -typedef struct -{ - _IO_strfile f; - /* This is used for the characters which do not fit in the buffer - provided by the user. */ - char overflow_buf[64]; -} _IO_strnfile; - - static int _IO_strn_overflow (_IO_FILE *fp, int c) __THROW; static int @@ -77,7 +67,7 @@ _IO_strn_overflow (fp, c) } -static const struct _IO_jump_t _IO_strn_jumps = +const struct _IO_jump_t _IO_strn_jumps attribute_hidden = { JUMP_INIT_DUMMY, JUMP_INIT(finish, _IO_str_finish), diff --git a/libio/vswprintf.c b/libio/vswprintf.c index 3cf01e2c84..42168aade4 100644 --- a/libio/vswprintf.c +++ b/libio/vswprintf.c @@ -35,7 +35,7 @@ typedef struct /* This is used for the characters which do not fit in the buffer provided by the user. */ wchar_t overflow_buf[64]; -} _IO_strnfile; +} _IO_wstrnfile; static wint_t _IO_wstrn_overflow (_IO_FILE *fp, wint_t c) __THROW; @@ -49,8 +49,8 @@ _IO_wstrn_overflow (fp, c) filled. But since we must return the number of characters which would have been written in total we must provide a buffer for further use. We can do this by writing on and on in the overflow - buffer in the _IO_strnfile structure. */ - _IO_strnfile *snf = (_IO_strnfile *) fp; + buffer in the _IO_wstrnfile structure. */ + _IO_wstrnfile *snf = (_IO_wstrnfile *) fp; if (fp->_wide_data->_IO_buf_base != snf->overflow_buf) { @@ -107,7 +107,7 @@ _IO_vswprintf (string, maxlen, format, args) const wchar_t *format; _IO_va_list args; { - _IO_strnfile sf; + _IO_wstrnfile sf; int ret; struct _IO_wide_data wd; #ifdef _IO_MTSAFE_IO diff --git a/linuxthreads/ChangeLog b/linuxthreads/ChangeLog index c704685250..bfccc57eb7 100644 --- a/linuxthreads/ChangeLog +++ b/linuxthreads/ChangeLog @@ -1,3 +1,8 @@ +2004-10-14 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/pthread/errno-loc.c: Don't undef #errno + if RTLD_PRIVATE_ERRNO. + 2004-10-05 Dwayne Grant McConnell <dgm69@us.ibm.com> * pthread.c: Mask restart signal during cancel signal handler. diff --git a/manual/memory.texi b/manual/memory.texi index 10ae4dee10..91abb7f5d4 100644 --- a/manual/memory.texi +++ b/manual/memory.texi @@ -2578,7 +2578,7 @@ wouldn't know what address to tell @code{mlock}. @comment POSIX.1b @deftypefun int munlock (const void *@var{addr}, size_t @var{len}) -@code{mlock} unlocks a range of the calling process' virtual pages. +@code{munlock} unlocks a range of the calling process' virtual pages. @code{munlock} is the inverse of @code{mlock} and functions completely analogously to @code{mlock}, except that there is no @code{EPERM} diff --git a/misc/sys/cdefs.h b/misc/sys/cdefs.h index 8894d0d5fc..475cf62961 100644 --- a/misc/sys/cdefs.h +++ b/misc/sys/cdefs.h @@ -127,6 +127,11 @@ #endif +/* Fortify support. */ +#define __bos(ptr) __builtin_object_size (ptr, __USE_FORTIFY_LEVEL > 1) +#define __bos0(ptr) __builtin_object_size (ptr, 0) + + /* Support for flexible arrays. */ #if __GNUC_PREREQ (2,97) /* GCC 2.97 supports C99 flexible array members. */ diff --git a/nptl/ChangeLog b/nptl/ChangeLog index e842302cb8..2385b9cd37 100644 --- a/nptl/ChangeLog +++ b/nptl/ChangeLog @@ -1,3 +1,8 @@ +2004-10-14 Richard Henderson <rth@redhat.com> + + * sysdeps/alpha/tcb-offsets.sym (thread_offsetof): Redefine to + make gcc4 happy. + 2004-10-06 Jakub Jelinek <jakub@redhat.com> * sysdeps/unix/sysv/linux/jmp-unwind.c: Include pthreadP.h instead @@ -28,8 +33,6 @@ * tst-clock2.c: Likewise. * tst-cond11.c: Likewise. -2004-10-05 Jakub Jelinek <jakub@redhat.com> - * sysdeps/pthread/timer_create.c (timer_create): Use defined _POSIX_CPUTIME && _POSIX_CPUTIME >= 0 instead of defined CLOCK_PROCESS_CPUTIME_ID #ifs and similarly for diff --git a/nptl/sysdeps/alpha/tcb-offsets.sym b/nptl/sysdeps/alpha/tcb-offsets.sym index 14494ee2cd..ebd84f35e5 100644 --- a/nptl/sysdeps/alpha/tcb-offsets.sym +++ b/nptl/sysdeps/alpha/tcb-offsets.sym @@ -4,8 +4,10 @@ -- -- Abuse tls.h macros to derive offsets relative to the thread register. -# define __builtin_thread_pointer() ((void *) 0) -# define thread_offsetof(mem) ((void *) &THREAD_SELF->mem - (void *) 0) +-- # define __builtin_thread_pointer() ((void *) 0) +-- # define thread_offsetof(mem) ((void *) &THREAD_SELF->mem - (void *) 0) +-- Ho hum, this doesn't work in gcc4, so Know Things about THREAD_SELF +#define thread_offsetof(mem) (long)(offsetof(struct pthread, mem) - sizeof(struct pthread)) MULTIPLE_THREADS_OFFSET thread_offsetof (header.multiple_threads) PID_OFFSET thread_offsetof (pid) diff --git a/nscd/Makefile b/nscd/Makefile index 70a35198c2..b21edc2b79 100644 --- a/nscd/Makefile +++ b/nscd/Makefile @@ -123,10 +123,10 @@ $(objpfx)nscd_nischeck: $(objpfx)nscd_nischeck.o ifeq ($(build-shared),yes) $(objpfx)nscd: $(common-objpfx)rt/librt.so $(shared-thread-library) \ - $(common-objpfx)nis/libnsl.so + $(common-objpfx)nis/libnsl.so $(selinux-LIBS) $(objpfx)nscd_nischeck: $(common-objpfx)nis/libnsl.so else $(objpfx)nscd: $(common-objpfx)rt/librt.a $(static-thread-library) \ - $(common-objpfx)nis/libnsl.a + $(common-objpfx)nis/libnsl.a $(selinux-LIBS) $(objpfx)nscd_nischeck: $(common-objpfx)nis/libnsl.a endif diff --git a/nscd/connections.c b/nscd/connections.c index d9c11f5425..aa760e0252 100644 --- a/nscd/connections.c +++ b/nscd/connections.c @@ -321,17 +321,15 @@ cannot create read-only descriptor for \"%s\"; no mmap"), } else { - size_t slen = strlen (dbs[cnt].db_filename); - char fname[slen + 8]; - strcpy (mempcpy (fname, dbs[cnt].db_filename, slen), - ".XXXXXX"); + char fname[] = _PATH_NSCD_XYZ_DB_TMP; fd = mkstemp (fname); /* We do not need the file name anymore after we opened another file descriptor in read-only mode. */ - if (fd != -1 && dbs[cnt].shared) + if (fd != -1) { - ro_fd = open (fname, O_RDONLY); + if (dbs[cnt].shared) + ro_fd = open (fname, O_RDONLY); unlink (fname); } diff --git a/nscd/nscd.h b/nscd/nscd.h index 4e00f69fb9..d5dc613d22 100644 --- a/nscd/nscd.h +++ b/nscd/nscd.h @@ -87,9 +87,12 @@ struct database_dyn /* Paths of the file for the persistent storage. */ -#define _PATH_NSCD_PASSWD_DB "/var/run/nscd/passwd" -#define _PATH_NSCD_GROUP_DB "/var/run/nscd/group" -#define _PATH_NSCD_HOSTS_DB "/var/run/nscd/hosts" +#define _PATH_NSCD_PASSWD_DB "/var/db/nscd/passwd" +#define _PATH_NSCD_GROUP_DB "/var/db/nscd/group" +#define _PATH_NSCD_HOSTS_DB "/var/db/nscd/hosts" + +/* Path used when not using persistent storage. */ +#define _PATH_NSCD_XYZ_DB_TMP "/var/run/nscd/dbXXXXXX" /* Global variables. */ diff --git a/nscd/nscd.init b/nscd/nscd.init index 568fe3e1e2..d5c1cb9ae3 100644 --- a/nscd/nscd.init +++ b/nscd/nscd.init @@ -38,6 +38,7 @@ prog=nscd start () { [ -d /var/run/nscd ] || mkdir /var/run/nscd + [ -d /var/db/nscd ] || mkdir /var/db/nscd secure="" # for table in passwd group hosts # do diff --git a/resolv/base64.c b/resolv/base64.c index b7c7d1c1b8..ea584ed357 100644 --- a/resolv/base64.c +++ b/resolv/base64.c @@ -112,9 +112,9 @@ static const char Pad64 = '='; end of the data is performed using the '=' character. Since all base64 input is an integral number of octets, only the - ------------------------------------------------- + ------------------------------------------------- following cases can arise: - + (1) the final quantum of encoding input is an integral multiple of 24 bits; here, the final unit of encoded output will be an integral multiple of 4 characters @@ -156,14 +156,14 @@ b64_ntop(u_char const *src, size_t srclength, char *target, size_t targsize) { target[datalength++] = Base64[output[2]]; target[datalength++] = Base64[output[3]]; } - + /* Now we worry about padding. */ if (0 != srclength) { /* Get what's left. */ input[0] = input[1] = input[2] = '\0'; for (i = 0; i < srclength; i++) input[i] = *src++; - + output[0] = input[0] >> 2; output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); @@ -186,6 +186,7 @@ b64_ntop(u_char const *src, size_t srclength, char *target, size_t targsize) { target[datalength] = '\0'; /* Returned value doesn't count \0. */ return (datalength); } +libresolv_hidden_def (b64_ntop) /* skips all whitespace anywhere. converts characters, four at a time, starting at (or after) diff --git a/resolv/gethnamaddr.c b/resolv/gethnamaddr.c index 1a4b08ecdc..3698e4b841 100644 --- a/resolv/gethnamaddr.c +++ b/resolv/gethnamaddr.c @@ -487,6 +487,9 @@ getanswer(answer, anslen, qname, qtype) return (NULL); } +extern struct hostent *gethostbyname2(const char *name, int af); +libresolv_hidden_proto (gethostbyname2) + struct hostent * gethostbyname(name) const char *name; @@ -637,6 +640,7 @@ gethostbyname2(name, af) free (buf.buf); return ret; } +libresolv_hidden_def (gethostbyname2) struct hostent * gethostbyaddr(addr, len, af) @@ -795,6 +799,7 @@ _sethtent(f) rewind(hostf); stayopen = f; } +libresolv_hidden_def (_sethtent) void _endhtent() @@ -869,6 +874,7 @@ _gethtent() __set_h_errno (NETDB_SUCCESS); return (&host); } +libresolv_hidden_def (_gethtent) struct hostent * _gethtbyname(name) @@ -907,6 +913,7 @@ _gethtbyname2(name, af) _endhtent(); return (p); } +libresolv_hidden_def (_gethtbyname2) struct hostent * _gethtbyaddr(addr, len, af) @@ -923,6 +930,7 @@ _gethtbyaddr(addr, len, af) _endhtent(); return (p); } +libresolv_hidden_def (_gethtbyaddr) static void map_v4v6_address(src, dst) diff --git a/resolv/ns_name.c b/resolv/ns_name.c index b96a1fe8ab..ed361915d8 100644 --- a/resolv/ns_name.c +++ b/resolv/ns_name.c @@ -145,6 +145,7 @@ ns_name_ntop(const u_char *src, char *dst, size_t dstsiz) { *dn++ = '\0'; return (dn - dst); } +libresolv_hidden_def (ns_name_ntop) /* * ns_name_pton(src, dst, dstsiz) @@ -421,6 +422,7 @@ ns_name_unpack(const u_char *msg, const u_char *eom, const u_char *src, len = srcp - src; return (len); } +libresolv_hidden_def (ns_name_unpack) /* * ns_name_pack(src, dst, dstsiz, dnptrs, lastdnptr) diff --git a/resolv/ns_netint.c b/resolv/ns_netint.c index ff24128cd6..20ecf626d8 100644 --- a/resolv/ns_netint.c +++ b/resolv/ns_netint.c @@ -22,6 +22,7 @@ static const char rcsid[] = "$BINDId: ns_netint.c,v 8.4 1999/10/13 16:39:35 vixi /* Import. */ #include <arpa/nameser.h> +#include <resolv.h> /* Public. */ @@ -32,6 +33,7 @@ ns_get16(const u_char *src) { NS_GET16(dst, src); return (dst); } +libresolv_hidden_def (ns_get16) u_long ns_get32(const u_char *src) { @@ -40,6 +42,7 @@ ns_get32(const u_char *src) { NS_GET32(dst, src); return (dst); } +libresolv_hidden_def (ns_get32) void ns_put16(u_int src, u_char *dst) { diff --git a/resolv/res_comp.c b/resolv/res_comp.c index f227c4d163..8157b97566 100644 --- a/resolv/res_comp.c +++ b/resolv/res_comp.c @@ -1,7 +1,7 @@ /* * Copyright (c) 1985, 1993 * The Regents of the University of California. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -13,7 +13,7 @@ * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -29,14 +29,14 @@ /* * Portions Copyright (c) 1993 by Digital Equipment Corporation. - * + * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies, and that * the name of Digital Equipment Corporation not be used in advertising or * publicity pertaining to distribution of the document or software without * specific, written prior permission. - * + * * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT @@ -96,6 +96,7 @@ dn_expand(const u_char *msg, const u_char *eom, const u_char *src, dst[0] = '\0'; return (n); } +libresolv_hidden_def (dn_expand) /* * Pack domain name 'exp_dn' in presentation form into 'comp_dn'. @@ -110,6 +111,7 @@ dn_comp(const char *src, u_char *dst, int dstsiz, (const u_char **)dnptrs, (const u_char **)lastdnptr)); } +libresolv_hidden_def (dn_comp) /* * Skip over a compressed domain name. Return the size or -1. @@ -122,6 +124,7 @@ dn_skipname(const u_char *ptr, const u_char *eom) { return (-1); return (ptr - saveptr); } +libresolv_hidden_def (dn_skipname) /* * Verify that a domain name uses an acceptable character set. @@ -170,6 +173,7 @@ res_hnok(const char *dn) { } return (1); } +libresolv_hidden_def (res_hnok) /* * hostname-like (A, MX, WKS) owners can have "*" as their first label @@ -227,6 +231,7 @@ res_dnok(const char *dn) { return (0); return (1); } +libresolv_hidden_def (res_dnok) #ifdef BIND_4_COMPAT /* @@ -238,7 +243,9 @@ res_dnok(const char *dn) { * Note that one _ comes from C and the others come from us. */ void __putlong(u_int32_t src, u_char *dst) { ns_put32(src, dst); } +libresolv_hidden_def (__putlong) void __putshort(u_int16_t src, u_char *dst) { ns_put16(src, dst); } +libresolv_hidden_def (__putshort) #ifndef __ultrix__ u_int32_t _getlong(const u_char *src) { return (ns_get32(src)); } u_int16_t _getshort(const u_char *src) { return (ns_get16(src)); } diff --git a/resolv/res_data.c b/resolv/res_data.c index 2183e022c8..438f815605 100644 --- a/resolv/res_data.c +++ b/resolv/res_data.c @@ -39,7 +39,7 @@ static const char rcsid[] = "$BINDId: res_data.c,v 8.17 1999/10/13 17:11:31 vixi #include <string.h> #include <unistd.h> -const char *_res_opcodes[] = { +const char *_res_opcodes[] attribute_hidden = { "QUERY", "IQUERY", "CQUERYM", @@ -59,7 +59,7 @@ const char *_res_opcodes[] = { }; #ifdef BIND_UPDATE -const char *_res_sectioncodes[] = { +const char *_res_sectioncodes[] attribute_hidden = { "ZONE", "PREREQUISITES", "UPDATE", @@ -138,6 +138,7 @@ void fp_query(const u_char *msg, FILE *file) { fp_nquery(msg, PACKETSZ, file); } +libresolv_hidden_def (fp_query) void fp_nquery(const u_char *msg, int len, FILE *file) { @@ -146,6 +147,7 @@ fp_nquery(const u_char *msg, int len, FILE *file) { res_pquery(&_res, msg, len, file); } +libresolv_hidden_def (fp_nquery) int res_mkquery(int op, /* opcode of query */ @@ -295,6 +297,7 @@ hostalias(const char *name) { return (res_hostalias(&_res, name, abuf, sizeof abuf)); } +libresolv_hidden_def (hostalias) #ifdef ultrix int diff --git a/resolv/res_debug.c b/resolv/res_debug.c index bd1fd3388f..6b719d1f2d 100644 --- a/resolv/res_debug.c +++ b/resolv/res_debug.c @@ -118,8 +118,8 @@ static const char rcsid[] = "$BINDId: res_debug.c,v 8.34 2000/02/29 05:30:55 vix # define SPRINTF(x) sprintf x #endif -extern const char *_res_opcodes[]; -extern const char *_res_sectioncodes[]; +extern const char *_res_opcodes[] attribute_hidden; +extern const char *_res_sectioncodes[] attribute_hidden; /* * Print the current options. @@ -298,6 +298,7 @@ p_cdnname(const u_char *cp, const u_char *msg, int len, FILE *file) { fputs(name, file); return (cp + n); } +libresolv_hidden_def (p_cdnname) const u_char * p_cdname(const u_char *cp, const u_char *msg, FILE *file) { @@ -327,6 +328,7 @@ p_fqnname(cp, msg, msglen, name, namelen) } return (cp + n); } +libresolv_hidden_def (p_fqnname) /* XXX: the rest of these functions need to become length-limited, too. */ @@ -347,7 +349,7 @@ p_fqname(const u_char *cp, const u_char *msg, FILE *file) { * that C_ANY is a qclass but not a class. (You can ask for records of class * C_ANY, but you can't have any records of that class in the database.) */ -const struct res_sym __p_class_syms[] = { +const struct res_sym __p_class_syms[] attribute_hidden = { {C_IN, "IN"}, {C_CHAOS, "CHAOS"}, {C_HS, "HS"}, @@ -360,7 +362,7 @@ const struct res_sym __p_class_syms[] = { /* * Names of message sections. */ -const struct res_sym __p_default_section_syms[] = { +const struct res_sym __p_default_section_syms[] attribute_hidden = { {ns_s_qd, "QUERY"}, {ns_s_an, "ANSWER"}, {ns_s_ns, "AUTHORITY"}, @@ -368,7 +370,7 @@ const struct res_sym __p_default_section_syms[] = { {0, (char *)0} }; -const struct res_sym __p_update_section_syms[] = { +const struct res_sym __p_update_section_syms[] attribute_hidden = { {S_ZONE, "ZONE"}, {S_PREREQ, "PREREQUISITE"}, {S_UPDATE, "UPDATE"}, @@ -376,7 +378,7 @@ const struct res_sym __p_update_section_syms[] = { {0, (char *)0} }; -const struct res_sym __p_key_syms[] = { +const struct res_sym __p_key_syms[] attribute_hidden = { {NS_ALG_MD5RSA, "RSA", "RSA KEY with MD5 hash"}, {NS_ALG_DH, "DH", "Diffie Hellman"}, {NS_ALG_DSA, "DSA", "Digital Signature Algorithm"}, @@ -385,7 +387,7 @@ const struct res_sym __p_key_syms[] = { {0, NULL, NULL} }; -const struct res_sym __p_cert_syms[] = { +const struct res_sym __p_cert_syms[] attribute_hidden = { {cert_t_pkix, "PKIX", "PKIX (X.509v3) Certificate"}, {cert_t_spki, "SPKI", "SPKI certificate"}, {cert_t_pgp, "PGP", "PGP certificate"}, @@ -399,7 +401,7 @@ const struct res_sym __p_cert_syms[] = { * that T_ANY is a qtype but not a type. (You can ask for records of type * T_ANY, but you can't have any records of that type in the database.) */ -const struct res_sym __p_type_syms[] = { +const struct res_sym __p_type_syms[] attribute_hidden = { {ns_t_a, "A", "address"}, {ns_t_ns, "NS", "name server"}, {ns_t_md, "MD", "mail destination (deprecated)"}, @@ -450,7 +452,7 @@ const struct res_sym __p_type_syms[] = { /* * Names of DNS rcodes. */ -const struct res_sym __p_rcode_syms[] = { +const struct res_sym __p_rcode_syms[] attribute_hidden = { {ns_r_noerror, "NOERROR", "no error"}, {ns_r_formerr, "FORMERR", "format error"}, {ns_r_servfail, "SERVFAIL", "server failed"}, @@ -500,6 +502,7 @@ sym_ntos(const struct res_sym *syms, int number, int *success) { *success = 0; return (unname); } +libresolv_hidden_def (sym_ntos) const char * sym_ntop(const struct res_sym *syms, int number, int *success) { @@ -525,6 +528,7 @@ const char * p_type(int type) { return (sym_ntos(__p_type_syms, type, (int *)0)); } +libresolv_hidden_def (p_type) /* * Return a string for the type. @@ -551,6 +555,7 @@ const char * p_class(int class) { return (sym_ntos(__p_class_syms, class, (int *)0)); } +libresolv_hidden_def (p_class) /* * Return a mnemonic for an option @@ -581,6 +586,7 @@ p_option(u_long option) { return (nbuf); } } +libresolv_hidden_def (p_option) /* * Return a mnemonic for a time to live. @@ -601,6 +607,7 @@ const char * p_rcode(int rcode) { return (sym_ntos(__p_rcode_syms, rcode, (int *)0)); } +libresolv_hidden_def (p_rcode) /* * routines to convert between on-the-wire RR format and zone file format. @@ -608,8 +615,9 @@ p_rcode(int rcode) { * by 60*60*1000 for that. */ -static unsigned int poweroften[10] = {1, 10, 100, 1000, 10000, 100000, - 1000000,10000000,100000000,1000000000}; +static const unsigned int poweroften[10]= + { 1, 10, 100, 1000, 10000, 100000, + 1000000,10000000,100000000,1000000000}; /* takes an XeY precision/size value, returns a string representation. */ static const char * @@ -988,6 +996,7 @@ loc_ntoa(binary, ascii) return (ascii); } +libresolv_hidden_def (loc_ntoa) /* Return the number of DNS hierarchy levels in the name. */ diff --git a/resolv/res_mkquery.c b/resolv/res_mkquery.c index 9825ae0fa3..875d495b72 100644 --- a/resolv/res_mkquery.c +++ b/resolv/res_mkquery.c @@ -219,3 +219,4 @@ res_nmkquery(res_state statp, } return (cp - buf); } +libresolv_hidden_def (res_nmkquery) diff --git a/resolv/res_query.c b/resolv/res_query.c index d2ef3b5e93..0feba6687a 100644 --- a/resolv/res_query.c +++ b/resolv/res_query.c @@ -190,6 +190,7 @@ __libc_res_nquery(res_state statp, } return (n); } +libresolv_hidden_def (__libc_res_nquery) int res_nquery(res_state statp, @@ -201,6 +202,7 @@ res_nquery(res_state statp, return __libc_res_nquery(statp, name, class, type, answer, anslen, NULL); } +libresolv_hidden_def (res_nquery) /* * Formulate a normal query, send, and retrieve answer in supplied buffer. @@ -365,6 +367,7 @@ __libc_res_nsearch(res_state statp, RES_SET_H_ERRNO(statp, TRY_AGAIN); return (-1); } +libresolv_hidden_def (__libc_res_nsearch) int res_nsearch(res_state statp, @@ -376,6 +379,7 @@ res_nsearch(res_state statp, return __libc_res_nsearch(statp, name, class, type, answer, anslen, NULL); } +libresolv_hidden_def (res_nsearch) /* * Perform a call on res_query on the concatenation of name and domain, @@ -439,6 +443,7 @@ res_nquerydomain(res_state statp, return __libc_res_nquerydomain(statp, name, domain, class, type, answer, anslen, NULL); } +libresolv_hidden_def (res_nquerydomain) const char * res_hostalias(const res_state statp, const char *name, char *dst, size_t siz) { @@ -476,3 +481,4 @@ res_hostalias(const res_state statp, const char *name, char *dst, size_t siz) { fclose(fp); return (NULL); } +libresolv_hidden_def (res_hostalias) diff --git a/resolv/res_send.c b/resolv/res_send.c index 44d8cb0fee..7773a2f522 100644 --- a/resolv/res_send.c +++ b/resolv/res_send.c @@ -312,6 +312,7 @@ res_nameinquery(const char *name, int type, int class, } return (0); } +libresolv_hidden_def (res_nameinquery) /* int * res_queriesmatch(buf1, eom1, buf2, eom2) @@ -361,6 +362,7 @@ res_queriesmatch(const u_char *buf1, const u_char *eom1, } return (1); } +libresolv_hidden_def (res_queriesmatch) int __libc_res_nsend(res_state statp, const u_char *buf, int buflen, @@ -689,6 +691,7 @@ res_nsend(res_state statp, { return __libc_res_nsend(statp, buf, buflen, ans, anssiz, NULL); } +libresolv_hidden_def (res_nsend) /* Private */ diff --git a/stdio-common/vfprintf.c b/stdio-common/vfprintf.c index 38da382efa..5e480ad52b 100644 --- a/stdio-common/vfprintf.c +++ b/stdio-common/vfprintf.c @@ -70,6 +70,7 @@ # define INT_T int # define L_(Str) Str # define ISDIGIT(Ch) ((unsigned int) ((Ch) - '0') < 10) +# define STR_LEN(Str) strlen (Str) # define PUT(F, S, N) _IO_sputn ((F), (S), (N)) # define PAD(Padchar) \ @@ -86,6 +87,7 @@ # define INT_T wint_t # define L_(Str) L##Str # define ISDIGIT(Ch) ((unsigned int) ((Ch) - L'0') < 10) +# define STR_LEN(Str) __wcslen (Str) # include "_itowa.h" @@ -219,6 +221,9 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap) /* For the %m format we may need the current `errno' value. */ int save_errno = errno; + /* 1 if format is in read-only memory, -1 if it is in writable memory, + 0 if unknown. */ + int readonly_format = 0; /* This table maps a character into a number representing a class. In each step there is a destination label for each @@ -877,6 +882,19 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap) /* NOTREACHED */ \ \ LABEL (form_number): \ + if (s->_flags2 & _IO_FLAGS2_CHECK_PERCENT_N) \ + { \ + if (! readonly_format) \ + { \ + extern int __readonly_area (const void *, size_t) \ + attribute_hidden; \ + readonly_format \ + = __readonly_area (format, (STR_LEN (format) + 1) \ + * sizeof (CHAR_T)); \ + } \ + if (readonly_format < 0) \ + __chk_fail (); \ + } \ /* Answer the count of characters written. */ \ if (fspec == NULL) \ { \ @@ -2091,6 +2109,7 @@ buffered_vfprintf (register _IO_FILE *s, const CHAR_T *format, #ifdef _IO_MTSAFE_IO hp->_lock = NULL; #endif + hp->_flags2 = s->_flags2; _IO_JUMPS (&helper._f) = (struct _IO_jump_t *) &_IO_helper_jumps; /* Now print to helper instead. */ diff --git a/string/Makefile b/string/Makefile index 5ab487f5ba..66469f586e 100644 --- a/string/Makefile +++ b/string/Makefile @@ -23,7 +23,7 @@ subdir := string headers := string.h strings.h memory.h endian.h bits/endian.h \ argz.h envz.h byteswap.h bits/byteswap.h bits/string.h \ - bits/string2.h + bits/string2.h bits/string3.h routines := strcat strchr strcmp strcoll strcpy strcspn \ strverscmp strdup strndup \ diff --git a/string/bits/string3.h b/string/bits/string3.h new file mode 100644 index 0000000000..87cbe35bb1 --- /dev/null +++ b/string/bits/string3.h @@ -0,0 +1,167 @@ +/* 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. */ + +#ifndef _STRING_H +# error "Never use <bits/string3.h> directly; include <string.h> instead." +#endif + +/* XXX This is temporarily. We should not redefine any of the symbols + and instead integrate the error checking into the original + definitions. */ +#undef memcpy +#undef memmove +#undef memset +#undef strcat +#undef strcpy +#undef strncat +#undef strncpy +#ifdef __USE_GNU +# undef mempcpy +# undef stpcpy +#endif +#ifdef __USE_BSD +# undef bcopy +# undef bzero +#endif + + +#define memcpy(dest, src, len) \ + ((__bos0 (dest) != (size_t) -1) \ + ? __builtin___memcpy_chk (dest, src, len, __bos0 (dest)) \ + : __memcpy_ichk (dest, src, len)) +static __inline__ void * +__attribute__ ((__always_inline__)) +__memcpy_ichk (void *__restrict __dest, const void *__restrict __src, + size_t __len) +{ + return __builtin___memcpy_chk (__dest, __src, __len, __bos0 (__dest)); +} + + +#define memmove(dest, src, len) \ + ((__bos0 (dest) != (size_t) -1) \ + ? __builtin___memmove_chk (dest, src, len, __bos0 (dest)) \ + : __memmove_ichk (dest, src, len)) +static __inline__ void * +__attribute__ ((__always_inline__)) +__memmove_ichk (void *__dest, const void *__src, size_t __len) +{ + return __builtin___memmove_chk (__dest, __src, __len, __bos0 (__dest)); +} + + +#ifdef __USE_GNU +# define mempcpy(dest, src, len) \ + ((__bos0 (dest) != (size_t) -1) \ + ? __builtin___mempcpy_chk (dest, src, len, __bos0 (dest)) \ + : __mempcpy_ichk (dest, src, len)) +static __inline__ void * +__attribute__ ((__always_inline__)) +__mempcpy_ichk (void *__restrict __dest, const void *__restrict __src, + size_t __len) +{ + return __builtin___mempcpy_chk (__dest, __src, __len, __bos0 (__dest)); +} +#endif + + +#define memset(dest, ch, len) \ + ((__bos0 (dest) != (size_t) -1) \ + ? __builtin___memset_chk (dest, ch, len, __bos0 (dest)) \ + : __memset_ichk (dest, ch, len)) +static __inline__ void * +__attribute__ ((__always_inline__)) +__memset_ichk (void *__dest, int __ch, size_t __len) +{ + return __builtin___memset_chk (__dest, __ch, __len, __bos0 (__dest)); +} + +#ifdef __USE_BSD +# define bcopy(src, dest, len) ((void) \ + ((__bos0 (dest) != (size_t) -1) \ + ? __builtin___memmove_chk (dest, src, len, __bos0 (dest)) \ + : __memmove_ichk (dest, src, len))) +# define bzero(dest, len) ((void) \ + ((__bos0 (dest) != (size_t) -1) \ + ? __builtin___memset_chk (dest, '\0', len, __bos0 (dest)) \ + : __memset_ichk (dest, '\0', len))) +#endif + + +#define strcpy(dest, src) \ + ((__bos (dest) != (size_t) -1) \ + ? __builtin___strcpy_chk (dest, src, __bos (dest)) \ + : __strcpy_ichk (dest, src)) +static __inline__ char * +__attribute__ ((__always_inline__)) +__strcpy_ichk (char *__restrict __dest, const char *__restrict __src) +{ + return __builtin___strcpy_chk (__dest, __src, __bos (__dest)); +} + + +#ifdef __USE_GNU +# define stpcpy(dest, src) \ + ((__bos (dest) != (size_t) -1) \ + ? __builtin___stpcpy_chk (dest, src, __bos (dest)) \ + : __stpcpy_ichk (dest, src)) +static __inline__ char * +__attribute__ ((__always_inline__)) +__stpcpy_ichk (char *__restrict __dest, const char *__restrict __src) +{ + return __builtin___stpcpy_chk (__dest, __src, __bos (__dest)); +} +#endif + + +#define strncpy(dest, src, len) \ + ((__bos (dest) != (size_t) -1) \ + ? __builtin___strncpy_chk (dest, src, len, __bos (dest)) \ + : __strncpy_ichk (dest, src, len)) +static __inline__ char * +__attribute__ ((__always_inline__)) +__strncpy_ichk (char *__restrict __dest, const char *__restrict __src, + size_t __len) +{ + return __builtin___strncpy_chk (__dest, __src, __len, __bos (__dest)); +} + + +#define strcat(dest, src) \ + ((__bos (dest) != (size_t) -1) \ + ? __builtin___strcat_chk (dest, src, __bos (dest)) \ + : __strcat_ichk (dest, src)) +static __inline__ char * +__attribute__ ((__always_inline__)) +__strcat_ichk (char *__restrict __dest, const char *__restrict __src) +{ + return __builtin___strcat_chk (__dest, __src, __bos (__dest)); +} + + +#define strncat(dest, src, len) \ + ((__bos (dest) != (size_t) -1) \ + ? __builtin___strncat_chk (dest, src, len, __bos (dest)) \ + : __strncat_ichk (dest, src, len)) +static __inline__ char * +__attribute__ ((__always_inline__)) +__strncat_ichk (char *__restrict __dest, const char *__restrict __src, + size_t __len) +{ + return __builtin___strncat_chk (__dest, __src, __len, __bos (__dest)); +} diff --git a/string/string.h b/string/string.h index 4ea3a74ca7..1adf925bb0 100644 --- a/string/string.h +++ b/string/string.h @@ -416,6 +416,11 @@ extern char *basename (__const char *__filename) __THROW __nonnull ((1)); /* These are generic optimizations which do not add too much inline code. */ # include <bits/string2.h> # endif + +# if __USE_FORTIFY_LEVEL > 0 && !defined __cplusplus +/* Functions with security checks. */ +# include <bits/string3.h> +# endif #endif __END_DECLS diff --git a/sunrpc/rpc_clntout.c b/sunrpc/rpc_clntout.c index 1e6bb56728..4e2832ff56 100644 --- a/sunrpc/rpc_clntout.c +++ b/sunrpc/rpc_clntout.c @@ -31,8 +31,10 @@ /* * From: @(#)rpc_clntout.c 1.11 89/02/22 (C) 1987 SMI */ -char clntout_rcsid[] = +#if defined(LIBC_SCCS) && !defined(lint) +static const char clntout_rcsid[] = "$Id$"; +#endif /* * rpc_clntout.c, Client-stub outputter for the RPC protocol compiler diff --git a/sunrpc/rpc_cout.c b/sunrpc/rpc_cout.c index a6471ab335..a803feb65a 100644 --- a/sunrpc/rpc_cout.c +++ b/sunrpc/rpc_cout.c @@ -31,8 +31,10 @@ /* * From: @(#)rpc_cout.c 1.13 89/02/22 (C) 1987 SMI */ -char cout_rcsid[] = +#if defined(LIBC_SCCS) && !defined(lint) +static const char cout_rcsid[] = "$Id$"; +#endif /* * rpc_cout.c, XDR routine outputter for the RPC protocol compiler diff --git a/sunrpc/rpc_hout.c b/sunrpc/rpc_hout.c index 076d63cb12..38cb419527 100644 --- a/sunrpc/rpc_hout.c +++ b/sunrpc/rpc_hout.c @@ -31,8 +31,10 @@ /* * From: @(#)rpc_hout.c 1.12 89/02/22 (C) 1987 SMI */ -char hout_rcsid[] = +#if defined(LIBC_SCCS) && !defined(lint) +static const char hout_rcsid[] = "$Id$"; +#endif /* * rpc_hout.c, Header file outputter for the RPC protocol compiler diff --git a/sunrpc/rpc_main.c b/sunrpc/rpc_main.c index 656f8ae502..fee83514d1 100644 --- a/sunrpc/rpc_main.c +++ b/sunrpc/rpc_main.c @@ -31,8 +31,10 @@ /* * From @(#)rpc_main.c 1.30 89/03/30 (C) 1987 SMI; */ -const char main_rcsid[] = +#if defined(LIBC_SCCS) && !defined(lint) +static const char main_rcsid[] = "$Id$"; +#endif /* * rpc_main.c, Top level of the RPC protocol compiler. diff --git a/sunrpc/rpc_parse.c b/sunrpc/rpc_parse.c index d6eda42309..7115cbdd08 100644 --- a/sunrpc/rpc_parse.c +++ b/sunrpc/rpc_parse.c @@ -31,8 +31,10 @@ /* * From: @(#)rpc_parse.c 1.8 89/02/22 (C) 1987 SMI */ -const char parse_rcsid[] = +#if defined(LIBC_SCCS) && !defined(lint) +static const char parse_rcsid[] = "$Id$"; +#endif /* * rpc_parse.c, Parser for the RPC protocol compiler diff --git a/sunrpc/rpc_sample.c b/sunrpc/rpc_sample.c index 79214a6a83..50c3d5554b 100644 --- a/sunrpc/rpc_sample.c +++ b/sunrpc/rpc_sample.c @@ -31,8 +31,10 @@ /* * From: @(#)rpc_sample.c 1.1 90/08/30 (C) 1987 SMI */ -char sample_rcsid[] = +#if defined(LIBC_SCCS) && !defined(lint) +static const char sample_rcsid[] = "$Id$"; +#endif /* * rpc_sample.c, Sample client-server code outputter for the RPC protocol compiler diff --git a/sunrpc/rpc_scan.c b/sunrpc/rpc_scan.c index 15c8e01178..d6211e9105 100644 --- a/sunrpc/rpc_scan.c +++ b/sunrpc/rpc_scan.c @@ -31,8 +31,10 @@ /* * From: @(#)rpc_scan.c 1.11 89/02/22 (C) 1987 SMI */ -char scan_rcsid[] = +#if defined(LIBC_SCCS) && !defined(lint) +static const char scan_rcsid[] = "$Id$"; +#endif /* * rpc_scan.c, Scanner for the RPC protocol compiler diff --git a/sunrpc/rpc_svcout.c b/sunrpc/rpc_svcout.c index a1eb792097..9a807c4096 100644 --- a/sunrpc/rpc_svcout.c +++ b/sunrpc/rpc_svcout.c @@ -31,8 +31,10 @@ /* * From: @(#)rpc_svcout.c 1.29 89/03/30 (C) 1987 SMI */ -char svcout_rcsid[] = +#if defined(LIBC_SCCS) && !defined(lint) +static const char svcout_rcsid[] = "$Id$"; +#endif /* * rpc_svcout.c, Server-skeleton outputter for the RPC protocol compiler diff --git a/sunrpc/rpc_tblout.c b/sunrpc/rpc_tblout.c index 4f62e2e7fd..bf4037fc37 100644 --- a/sunrpc/rpc_tblout.c +++ b/sunrpc/rpc_tblout.c @@ -31,8 +31,10 @@ /* * From: @(#)rpc_tblout.c 1.4 89/02/22 (C) 1988 SMI */ -char tblout_rcsid[] = +#if defined(LIBC_SCCS) && !defined(lint) +static const char tblout_rcsid[] = "$Id$"; +#endif /* * rpc_tblout.c, Dispatch table outputter for the RPC protocol compiler diff --git a/sunrpc/rpc_util.c b/sunrpc/rpc_util.c index 4c986040ce..31e1d3143c 100644 --- a/sunrpc/rpc_util.c +++ b/sunrpc/rpc_util.c @@ -31,8 +31,10 @@ /* * From: @(#)rpc_util.c 1.11 89/02/22 (C) 1987 SMI */ -char util_rcsid[] = +#if defined(LIBC_SCCS) && !defined(lint) +static const char util_rcsid[] = "$Id$"; +#endif /* * rpc_util.c, Utility routines for the RPC protocol compiler diff --git a/sysdeps/alpha/dl-machine.h b/sysdeps/alpha/dl-machine.h index 7c5f3c1518..780a3a57fd 100644 --- a/sysdeps/alpha/dl-machine.h +++ b/sysdeps/alpha/dl-machine.h @@ -507,7 +507,7 @@ elf_machine_plt_value (struct link_map *map, const Elf64_Rela *reloc, /* Perform the relocation specified by RELOC and SYM (which is fully resolved). MAP is the object containing the reloc. */ -static inline void +auto inline void elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc, const Elf64_Sym *sym, @@ -645,7 +645,7 @@ elf_machine_rela (struct link_map *map, can be skipped. */ #define ELF_MACHINE_REL_RELATIVE 1 -static inline void +auto inline void elf_machine_rela_relative (Elf64_Addr l_addr, const Elf64_Rela *reloc, void *const reloc_addr_arg) { @@ -661,7 +661,7 @@ elf_machine_rela_relative (Elf64_Addr l_addr, const Elf64_Rela *reloc, memcpy (reloc_addr_arg, &reloc_addr_val, 8); } -static inline void +auto inline void elf_machine_lazy_rel (struct link_map *map, Elf64_Addr l_addr, const Elf64_Rela *reloc) { 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/mach/hurd/Makefile b/sysdeps/mach/hurd/Makefile index 5f3da04b47..8677515cd9 100644 --- a/sysdeps/mach/hurd/Makefile +++ b/sysdeps/mach/hurd/Makefile @@ -1,4 +1,4 @@ -# Copyright (C) 1993,94,95,96,97,98,99,2000,2001,2002, 2003 +# Copyright (C) 1993,94,95,96,97,98,99,2000,2001,2002, 2003, 2004 # Free Software Foundation, Inc. # This file is part of the GNU C Library. @@ -177,14 +177,14 @@ ifeq (yes,$(build-static)) link-libc-static := -Wl,-\( \ $(patsubst %,$(common-objpfx)%.a,\ libc mach/libmachuser hurd/libhurduser) \ - $(gnulib) -Wl,-\) + $(static-gnulib) -Wl,-\) else ifeq (yes,$(build-shared)) # We can try to link the programs with lib*_pic.a... link-libc-static := $(link-libc) -Wl,-\( \ $(patsubst %,$(common-objpfx)%_pic.a,\ libc mach/libmachuser hurd/libhurduser) \ - $(gnulib) -Wl,-\) + $(static-gnulib) -Wl,-\) endif endif diff --git a/sysdeps/powerpc/powerpc32/dl-machine.c b/sysdeps/powerpc/powerpc32/dl-machine.c index 606a1dd043..06960716b9 100644 --- a/sysdeps/powerpc/powerpc32/dl-machine.c +++ b/sysdeps/powerpc/powerpc32/dl-machine.c @@ -101,8 +101,8 @@ weak_extern (__cache_line_size) mapped somewhere else. */ ElfW(Addr) -__elf_preferred_address(struct link_map *loader, size_t maplength, - ElfW(Addr) mapstartpref) +__elf_preferred_address (struct link_map *loader, size_t maplength, + ElfW(Addr) mapstartpref) { ElfW(Addr) low, high; struct link_map *l; @@ -343,8 +343,8 @@ __elf_machine_runtime_setup (struct link_map *map, int lazy, int profile) } Elf32_Addr -__elf_machine_fixup_plt(struct link_map *map, const Elf32_Rela *reloc, - Elf32_Addr *reloc_addr, Elf32_Addr finaladdr) +__elf_machine_fixup_plt (struct link_map *map, const Elf32_Rela *reloc, + Elf32_Addr *reloc_addr, Elf32_Addr finaladdr) { Elf32_Sword delta = finaladdr - (Elf32_Word) reloc_addr; if (delta << 6 >> 6 == delta) diff --git a/sysdeps/unix/sysv/linux/adjtime.c b/sysdeps/unix/sysv/linux/adjtime.c index 62008f63ca..38ef805cd5 100644 --- a/sysdeps/unix/sysv/linux/adjtime.c +++ b/sysdeps/unix/sysv/linux/adjtime.c @@ -1,4 +1,5 @@ -/* Copyright (C) 1995, 1996, 1997, 1998, 2002 Free Software Foundation, Inc. +/* Copyright (C) 1995, 1996, 1997, 1998, 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 @@ -51,9 +52,7 @@ extern int INTUSE(__adjtimex) (struct timex *__ntx); #endif LINKAGE int -ADJTIME (itv, otv) - const struct TIMEVAL *itv; - struct TIMEVAL *otv; +ADJTIME (const struct TIMEVAL *itv, struct TIMEVAL *otv) { struct TIMEX tntx; diff --git a/sysdeps/unix/sysv/linux/alpha/adjtime.c b/sysdeps/unix/sysv/linux/alpha/adjtime.c index f8b272e9ce..e206cb4727 100644 --- a/sysdeps/unix/sysv/linux/alpha/adjtime.c +++ b/sysdeps/unix/sysv/linux/alpha/adjtime.c @@ -87,14 +87,15 @@ compat_symbol (libc, __adjtime_tv32, adjtime, GLIBC_2_0); #define TIMEVAL timeval #undef TIMEX #define TIMEX timex -#undef ADJTIME -#define ADJTIME __adjtime_tv64 #undef ADJTIMEX #define ADJTIMEX(x) INLINE_SYSCALL (adjtimex, 1, x) + #undef LINKAGE +#undef ADJTIME +#if !defined __ASSUME_TIMEVAL64 #define LINKAGE static - -LINKAGE int ADJTIME (const struct TIMEVAL *itv, struct TIMEVAL *otv); +#define ADJTIME __adjtime_tv64 +#endif #include <sysdeps/unix/sysv/linux/adjtime.c> #include <stdbool.h> @@ -135,8 +136,6 @@ __adjtime (itv, otv) return ret; } -#else -strong_alias (__adjtime_tv64, __adjtime); #endif versioned_symbol (libc, __adjtime, adjtime, GLIBC_2_1); diff --git a/sysdeps/unix/sysv/linux/alpha/register-dump.h b/sysdeps/unix/sysv/linux/alpha/register-dump.h new file mode 100644 index 0000000000..d55899a2c1 --- /dev/null +++ b/sysdeps/unix/sysv/linux/alpha/register-dump.h @@ -0,0 +1,161 @@ +/* Dump registers. + 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 <stddef.h> +#include <sys/uio.h> + +/* We will print the register dump in this format: + + V0: XXXXXXXXXXXXXXXX T0: XXXXXXXXXXXXXXXX T1: XXXXXXXXXXXXXXXX + T2: XXXXXXXXXXXXXXXX T3: XXXXXXXXXXXXXXXX T4: XXXXXXXXXXXXXXXX + T5: XXXXXXXXXXXXXXXX T6: XXXXXXXXXXXXXXXX T7: XXXXXXXXXXXXXXXX + S0: XXXXXXXXXXXXXXXX S1: XXXXXXXXXXXXXXXX S2: XXXXXXXXXXXXXXXX + S3: XXXXXXXXXXXXXXXX S4: XXXXXXXXXXXXXXXX S5: XXXXXXXXXXXXXXXX + S6: XXXXXXXXXXXXXXXX A0: XXXXXXXXXXXXXXXX A1: XXXXXXXXXXXXXXXX + A2: XXXXXXXXXXXXXXXX A3: XXXXXXXXXXXXXXXX A4: XXXXXXXXXXXXXXXX + A5: XXXXXXXXXXXXXXXX T8: XXXXXXXXXXXXXXXX T9: XXXXXXXXXXXXXXXX + T10: XXXXXXXXXXXXXXXX T11: XXXXXXXXXXXXXXXX RA: XXXXXXXXXXXXXXXX + T12: XXXXXXXXXXXXXXXX AT: XXXXXXXXXXXXXXXX GP: XXXXXXXXXXXXXXXX + SP: XXXXXXXXXXXXXXXX PC: XXXXXXXXXXXXXXXX + + FP0: XXXXXXXXXXXXXXXX FP1: XXXXXXXXXXXXXXXX FP2: XXXXXXXXXXXXXXXX + FP3: XXXXXXXXXXXXXXXX FP4: XXXXXXXXXXXXXXXX FP5: XXXXXXXXXXXXXXXX + FP6: XXXXXXXXXXXXXXXX FP7: XXXXXXXXXXXXXXXX FP8: XXXXXXXXXXXXXXXX + FP9: XXXXXXXXXXXXXXXX FP10: XXXXXXXXXXXXXXXX FP11: XXXXXXXXXXXXXXXX + FP12: XXXXXXXXXXXXXXXX FP13: XXXXXXXXXXXXXXXX FP14: XXXXXXXXXXXXXXXX + FP15: XXXXXXXXXXXXXXXX FP16: XXXXXXXXXXXXXXXX FP17: XXXXXXXXXXXXXXXX + FP18: XXXXXXXXXXXXXXXX FP19: XXXXXXXXXXXXXXXX FP20: XXXXXXXXXXXXXXXX + FP21: XXXXXXXXXXXXXXXX FP22: XXXXXXXXXXXXXXXX FP23: XXXXXXXXXXXXXXXX + FP24: XXXXXXXXXXXXXXXX FP25: XXXXXXXXXXXXXXXX FP26: XXXXXXXXXXXXXXXX + FP27: XXXXXXXXXXXXXXXX FP28: XXXXXXXXXXXXXXXX FP29: XXXXXXXXXXXXXXXX + FP30: XXXXXXXXXXXXXXXX FPCR: XXXXXXXXXXXXXXXX + + TA0: XXXXXXXXXXXXXXXX TA1: XXXXXXXXXXXXXXXX TA2: XXXXXXXXXXXXXXXX +*/ + +#define NREGS (32+32+3) + +static const char regnames[NREGS][8] = +{ + " V0: ", " T0: ", " T1: ", + " T2: ", " T3: ", " T4: ", + " T5: ", " T6: ", " T7: ", + " S0: ", " S1: ", " S2: ", + " S3: ", " S4: ", " S5: ", + " S6: ", " A0: ", " A1: ", + " A2: ", " A3: ", " A4: ", + " A5: ", " T8: ", " T9: ", + " T10: ", " T11: ", " RA: ", + " T12: ", " AT: ", " GP: ", + " SP: ", " PC: ", + + " FP0: ", " FP1: ", " FP2: ", + " FP3: ", " FP4: ", " FP5: ", + " FP6: ", " FP7: ", " FP8: ", + " FP9: ", " FP10: ", " FP11: ", + " FP12: ", " FP13: ", " FP14: ", + " FP15: ", " FP16: ", " FP17: ", + " FP18: ", " FP19: ", " FP20: ", + " FP21: ", " FP22: ", " FP23: ", + " FP24: ", " FP25: ", " FP26: ", + " FP27: ", " FP28: ", " FP29: ", + " FP30: ", " FPCR: ", + + " TA0: ", " TA1: ", " TA2: " +}; + +#define O(FIELD, LF) offsetof(struct sigcontext, FIELD) + LF + +static const int offsets[NREGS] = +{ + O(sc_regs[0], 0), O(sc_regs[1], 0), O(sc_regs[2], 1), + O(sc_regs[3], 0), O(sc_regs[4], 0), O(sc_regs[5], 1), + O(sc_regs[6], 0), O(sc_regs[7], 0), O(sc_regs[8], 1), + O(sc_regs[9], 0), O(sc_regs[10], 0), O(sc_regs[11], 1), + O(sc_regs[12], 0), O(sc_regs[13], 0), O(sc_regs[14], 1), + O(sc_regs[15], 0), O(sc_regs[16], 0), O(sc_regs[17], 1), + O(sc_regs[18], 0), O(sc_regs[19], 0), O(sc_regs[20], 1), + O(sc_regs[21], 0), O(sc_regs[22], 0), O(sc_regs[23], 1), + O(sc_regs[24], 0), O(sc_regs[25], 0), O(sc_regs[26], 1), + O(sc_regs[27], 0), O(sc_regs[28], 0), O(sc_regs[29], 1), + O(sc_regs[30], 0), O(sc_pc, 2), + + O(sc_fpregs[0], 0), O(sc_fpregs[1], 0), O(sc_fpregs[2], 1), + O(sc_fpregs[3], 0), O(sc_fpregs[4], 0), O(sc_fpregs[5], 1), + O(sc_fpregs[6], 0), O(sc_fpregs[7], 0), O(sc_fpregs[8], 1), + O(sc_fpregs[9], 0), O(sc_fpregs[10], 0), O(sc_fpregs[11], 1), + O(sc_fpregs[12], 0), O(sc_fpregs[13], 0), O(sc_fpregs[14], 1), + O(sc_fpregs[15], 0), O(sc_fpregs[16], 0), O(sc_fpregs[17], 1), + O(sc_fpregs[18], 0), O(sc_fpregs[19], 0), O(sc_fpregs[20], 1), + O(sc_fpregs[21], 0), O(sc_fpregs[22], 0), O(sc_fpregs[23], 1), + O(sc_fpregs[24], 0), O(sc_fpregs[25], 0), O(sc_fpregs[26], 1), + O(sc_fpregs[27], 0), O(sc_fpregs[28], 0), O(sc_fpregs[29], 1), + O(sc_fpregs[30], 0), O(sc_fpcr, 2), + + O(sc_traparg_a0, 0), O(sc_traparg_a1, 0), O(sc_traparg_a2, 1) +}; + +#undef O + +static const char linefeed[2] = "\n\n"; + +static void +register_dump (int fd, struct sigcontext *ctx) +{ + char regs[NREGS][16]; + struct iovec iov[2*NREGS+24]; + size_t iov_i = 0, i, j; + +#define ADD_MEM(str, len) \ + (iov[iov_i].iov_base = (void *)(str), \ + iov[iov_i].iov_len = len, \ + ++iov_i) + +#define ADD_STRING(str) ADD_MEM(str, strlen(str)) + + ADD_STRING ("Register dump:\n\n"); + + for (i = 0; i < NREGS; ++i) + { + int this_offset, this_lf; + unsigned long val; + + this_offset = offsets[i]; + this_lf = this_offset & 7; + this_offset &= -8; + + val = *(unsigned long *)((char *)ctx + this_offset); + + for (j = 0; j < 16; ++j) + { + unsigned long x = (val >> (64 - (j + 1) * 4)) & 15; + x += x < 10 ? '0' : 'a' - 10; + regs[i][j] = x; + } + + ADD_MEM (regnames[i], 8); + ADD_MEM (regs[i], 16); + if (this_lf) + ADD_MEM (linefeed, this_lf); + } + + writev (fd, iov, iov_i); +} + +#define REGISTER_DUMP register_dump (fd, ctx) diff --git a/sysdeps/unix/sysv/linux/alpha/sigcontextinfo.h b/sysdeps/unix/sysv/linux/alpha/sigcontextinfo.h index eb6f4f0758..16c5dcbc5b 100644 --- a/sysdeps/unix/sysv/linux/alpha/sigcontextinfo.h +++ b/sysdeps/unix/sysv/linux/alpha/sigcontextinfo.h @@ -1,4 +1,4 @@ -/* Copyright (C) 1999 Free Software Foundation, Inc. +/* Copyright (C) 1999, 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 @@ -16,10 +16,10 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#define SIGCONTEXT struct sigcontext -#define SIGCONTEXT_EXTRA_ARGS -#define GET_PC(ctx) ((void *) (ctx).sc_pc) -#define GET_FRAME(ctx) ((void *) (ctx).sc_regs[15]) -#define GET_STACK(ctx) ((void *) (ctx).sc_regs[30]) +#define SIGCONTEXT int _code, struct sigcontext * +#define SIGCONTEXT_EXTRA_ARGS _code, +#define GET_PC(ctx) ((void *) (ctx)->sc_pc) +#define GET_FRAME(ctx) ((void *) (ctx)->sc_regs[15]) +#define GET_STACK(ctx) ((void *) (ctx)->sc_regs[30]) #define CALL_SIGHANDLER(handler, signo, ctx) \ (handler)((signo), SIGCONTEXT_EXTRA_ARGS (ctx)) diff --git a/sysdeps/unix/sysv/linux/i386/syscall.S b/sysdeps/unix/sysv/linux/i386/syscall.S index cd7dc65a5f..b569650b24 100644 --- a/sysdeps/unix/sysv/linux/i386/syscall.S +++ b/sysdeps/unix/sysv/linux/i386/syscall.S @@ -1,4 +1,4 @@ -/* Copyright (C) 1995, 1996, 1998, 2002 Free Software Foundation, Inc. +/* Copyright (C) 1995, 1996, 1998, 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 @@ -24,11 +24,11 @@ .text ENTRY (syscall) - PUSHARGS_5 /* Save register contents. */ - _DOARGS_5(36) /* Load arguments. */ - movl 16(%esp), %eax /* Load syscall number into %eax. */ + PUSHARGS_6 /* Save register contents. */ + _DOARGS_6(44) /* Load arguments. */ + movl 20(%esp), %eax /* Load syscall number into %eax. */ ENTER_KERNEL /* Do the system call. */ - POPARGS_5 /* Restore register contents. */ + POPARGS_6 /* Restore register contents. */ cmpl $-4095, %eax /* Check %eax for error. */ jae SYSCALL_ERROR_LABEL /* Jump to error handler if error. */ L(pseudo_end): diff --git a/sysdeps/unix/sysv/linux/i386/sysdep.h b/sysdeps/unix/sysv/linux/i386/sysdep.h index 37e7459a9c..af75d4c51a 100644 --- a/sysdeps/unix/sysv/linux/i386/sysdep.h +++ b/sysdeps/unix/sysv/linux/i386/sysdep.h @@ -297,6 +297,13 @@ __i686.get_pc_thunk.reg: \ #define _DOARGS_5(n) movl n(%esp), %edi; _DOARGS_4 (n-4) #define _POPARGS_5 _POPARGS_4; popl %edi; L(POPDI1): +#define PUSHARGS_6 _PUSHARGS_6 +#define DOARGS_6 _DOARGS_6 (36) +#define POPARGS_6 _POPARGS_6 +#define _PUSHARGS_6 pushl %ebp; L(PUSHBP1): _PUSHARGS_5 +#define _DOARGS_6(n) movl n(%esp), %ebp; _DOARGS_5 (n-4) +#define _POPARGS_6 _POPARGS_5; popl %ebp; L(POPBP1): + #else /* !__ASSEMBLER__ */ /* We need some help from the assembler to generate optimal code. We diff --git a/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h b/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h index 1f56671ba0..5eaf7a276b 100644 --- a/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h +++ b/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2000, 2002, 2003 Free Software Foundation, Inc. +/* Copyright (C) 2000, 2002, 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 @@ -275,7 +275,8 @@ _sys_result; \ }) -#define __SYSCALL_CLOBBERS "$1", "$3", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", "$25" +#define __SYSCALL_CLOBBERS "$1", "$3", "$8", "$9", "$10", "$11", "$12", "$13", \ + "$14", "$15", "$24", "$25", "memory" #endif /* __ASSEMBLER__ */ diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/sysdep.h b/sysdeps/unix/sysv/linux/mips/mips64/n32/sysdep.h index 2b2aefa15d..be343aabca 100644 --- a/sysdeps/unix/sysv/linux/mips/mips64/n32/sysdep.h +++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/sysdep.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2000, 2002, 2003 Free Software Foundation, Inc. +/* Copyright (C) 2000, 2002, 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 @@ -235,7 +235,8 @@ _sys_result; \ }) -#define __SYSCALL_CLOBBERS "$1", "$3", "$10", "$11", "$12", "$13", "$14", "$15", "$24", "$25" +#define __SYSCALL_CLOBBERS "$1", "$3", "$10", "$11", "$12", "$13", \ + "$14", "$15", "$24", "$25", "memory" #endif /* __ASSEMBLER__ */ #endif /* linux/mips/sysdep.h */ diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/sysdep.h b/sysdeps/unix/sysv/linux/mips/mips64/n64/sysdep.h index e2d8707d25..f30a465081 100644 --- a/sysdeps/unix/sysv/linux/mips/mips64/n64/sysdep.h +++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/sysdep.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2000, 2002, 2003 Free Software Foundation, Inc. +/* Copyright (C) 2000, 2002, 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 @@ -235,7 +235,8 @@ _sys_result; \ }) -#define __SYSCALL_CLOBBERS "$1", "$3", "$10", "$11", "$12", "$13", "$14", "$15", "$24", "$25" +#define __SYSCALL_CLOBBERS "$1", "$3", "$10", "$11", "$12", "$13", \ + "$14", "$15", "$24", "$25", "memory" #endif /* __ASSEMBLER__ */ #endif /* linux/mips/sysdep.h */ 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) |