diff options
Diffstat (limited to 'debug')
82 files changed, 4122 insertions, 60 deletions
diff --git a/debug/Depend b/debug/Depend new file mode 100644 index 0000000000..f3e1156a4e --- /dev/null +++ b/debug/Depend @@ -0,0 +1 @@ +localedata diff --git a/debug/Makefile b/debug/Makefile index 6df06116b7..9d9b6ac96a 100644 --- a/debug/Makefile +++ b/debug/Makefile @@ -1,4 +1,4 @@ -# Copyright (C) 1998, 1999, 2000, 2001, 2004 Free Software Foundation, Inc. +# Copyright (C) 1998-2001,2004,2005,2006 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,12 +24,27 @@ 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 \ + strcat_chk strcpy_chk strncat_chk strncpy_chk stpncpy_chk \ sprintf_chk vsprintf_chk snprintf_chk vsnprintf_chk \ printf_chk fprintf_chk vprintf_chk vfprintf_chk \ - gets_chk chk_fail readonly-area + gets_chk chk_fail readonly-area fgets_chk fgets_u_chk \ + read_chk pread_chk pread64_chk recv_chk recvfrom_chk \ + readlink_chk readlinkat_chk getwd_chk getcwd_chk \ + realpath_chk ptsname_r_chk \ + wctomb_chk wcscpy_chk wmemcpy_chk wmemmove_chk wmempcpy_chk \ + wcpcpy_chk wcsncpy_chk wcscat_chk wcsncat_chk wmemset_chk \ + wcpncpy_chk \ + swprintf_chk vswprintf_chk wprintf_chk fwprintf_chk \ + vwprintf_chk vfwprintf_chk fgetws_chk fgetws_u_chk \ + confstr_chk getgroups_chk ttyname_r_chk getlogin_r_chk \ + gethostname_chk getdomainname_chk wcrtomb_chk mbsnrtowcs_chk \ + wcsnrtombs_chk mbsrtowcs_chk wcsrtombs_chk mbstowcs_chk \ + wcstombs_chk \ + stack_chk_fail \ + $(static-only-routines) +static-only-routines := warning-nop stack_chk_fail_local CFLAGS-backtrace.c = -fno-omit-frame-pointer CFLAGS-sprintf_chk.c = -D_IO_MTSAFE_IO @@ -41,9 +56,31 @@ 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) +CFLAGS-fgets_chk.c = -D_IO_MTSAFE_IO $(exceptions) +CFLAGS-fgets_u_chk.c = -D_IO_MTSAFE_IO $(exceptions) +CFLAGS-swprintf_chk.c = -D_IO_MTSAFE_IO +CFLAGS-vswprintf_chk.c = -D_IO_MTSAFE_IO +CFLAGS-wprintf_chk.c = -D_IO_MTSAFE_IO $(exceptions) +CFLAGS-fwprintf_chk.c = -D_IO_MTSAFE_IO $(exceptions) +CFLAGS-vwprintf_chk.c = -D_IO_MTSAFE_IO $(exceptions) +CFLAGS-vfwprintf_chk.c = -D_IO_MTSAFE_IO $(exceptions) +CFLAGS-fgetws_chk.c = -D_IO_MTSAFE_IO $(exceptions) +CFLAGS-fgetws_u_chk.c = -D_IO_MTSAFE_IO $(exceptions) +CFLAGS-read_chk.c = -fexceptions -fasynchronous-unwind-tables +CFLAGS-pread_chk.c = -fexceptions -fasynchronous-unwind-tables +CFLAGS-pread64_chk.c = -fexceptions -fasynchronous-unwind-tables +CFLAGS-recv_chk.c = -fexceptions -fasynchronous-unwind-tables +CFLAGS-recvfrom_chk.c = -fexceptions -fasynchronous-unwind-tables + +tst-chk1-ENV = LOCPATH=$(common-objpfx)localedata +tst-chk2-ENV = LOCPATH=$(common-objpfx)localedata +tst-chk3-ENV = LOCPATH=$(common-objpfx)localedata +tst-lfschk1-ENV = LOCPATH=$(common-objpfx)localedata +tst-lfschk2-ENV = LOCPATH=$(common-objpfx)localedata +tst-lfschk3-ENV = LOCPATH=$(common-objpfx)localedata tests = backtrace-tst tst-chk1 tst-chk2 tst-chk3 \ - test-strcpy_chk test-stpcpy_chk + tst-lfschk1 tst-lfschk2 tst-lfschk3 test-strcpy_chk test-stpcpy_chk extra-libs = libSegFault libpcprofile extra-libs-others = $(extra-libs) @@ -70,6 +107,8 @@ generated = catchsegv xtrace include ../Rules +sLIBdir := $(shell echo $(slibdir) | sed 's,lib\(\|64\)$$,\\\\$$LIB,') + $(objpfx)catchsegv: catchsegv.sh $(common-objpfx)soversions.mk \ $(common-objpfx)config.make slibpfx=`echo $(slibdir)|sed 's/lib\(64\|\)$$/\\\\\\\\$$LIB/'`; \ @@ -82,7 +121,7 @@ $(objpfx)pcprofiledump: $(objpfx)pcprofiledump.o $(objpfx)xtrace: xtrace.sh rm -f $@.new sed -e 's|@BASH@|$(BASH)|' -e 's|@VERSION@|$(version)|' \ - -e 's|@SLIBDIR@|$(slibdir)|' -e 's|@BINDIR@|$(bindir)|' $^ > $@.new \ + -e 's|@SLIBDIR@|$(sLIBdir)|' -e 's|@BINDIR@|$(bindir)|' $^ > $@.new \ && rm -f $@ && mv $@.new $@ && chmod +x $@ # Depend on libc.so so a DT_NEEDED is generated in the shared objects. diff --git a/debug/Versions b/debug/Versions index 07d6fbb830..5c87af27c1 100644 --- a/debug/Versions +++ b/debug/Versions @@ -18,4 +18,25 @@ libc { __printf_chk; __fprintf_chk; __vprintf_chk; __vfprintf_chk; __gets_chk; } + GLIBC_2.4 { + __fgets_chk; __fgets_unlocked_chk; + __read_chk; __pread_chk; __pread64_chk; + __readlink_chk; __getcwd_chk; __getwd_chk; + __recv_chk; __recvfrom_chk; + __realpath_chk; __ptsname_r_chk; __wctomb_chk; + __stpncpy_chk; + __wcscpy_chk; __wmemcpy_chk; __wmemmove_chk; __wmempcpy_chk; __wcpcpy_chk; + __wcsncpy_chk; __wcscat_chk; __wcsncat_chk; __wmemset_chk; __wcpncpy_chk; + __swprintf_chk; __vswprintf_chk; __wprintf_chk; __fwprintf_chk; + __vwprintf_chk; __vfwprintf_chk; __fgetws_chk; __fgetws_unlocked_chk; + __confstr_chk; __getgroups_chk; __ttyname_r_chk; __getlogin_r_chk; + __gethostname_chk; __getdomainname_chk; __wcrtomb_chk; __mbsnrtowcs_chk; + __wcsnrtombs_chk; __mbsrtowcs_chk; __wcsrtombs_chk; __mbstowcs_chk; + __wcstombs_chk; + + __stack_chk_fail; + } + GLIBC_2.5 { + __readlinkat_chk; + } } diff --git a/debug/backtrace.c b/debug/backtrace.c new file mode 100644 index 0000000000..f2d52372d5 --- /dev/null +++ b/debug/backtrace.c @@ -0,0 +1,94 @@ +/* Return backtrace of current program state. Generic version. + Copyright (C) 1998, 2000, 2002, 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998. + + 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 <execinfo.h> +#include <signal.h> +#include <frame.h> +#include <sigcontextinfo.h> +#include <bp-checks.h> +#include <ldsodefs.h> + +/* This implementation assumes a stack layout that matches the defaults + used by gcc's `__builtin_frame_address' and `__builtin_return_address' + (FP is the frame pointer register): + + +-----------------+ +-----------------+ + FP -> | previous FP --------> | previous FP ------>... + | | | | + | return address | | return address | + +-----------------+ +-----------------+ + + */ + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#ifndef CURRENT_STACK_FRAME +# define CURRENT_STACK_FRAME ({ char __csf; &__csf; }) +#endif + +/* By default we assume that the stack grows downward. */ +#ifndef INNER_THAN +# define INNER_THAN < +#endif + +/* By default assume the `next' pointer in struct layout points to the + next struct layout. */ +#ifndef ADVANCE_STACK_FRAME +# define ADVANCE_STACK_FRAME(next) BOUNDED_1 ((struct layout *) (next)) +#endif + +/* By default, the frame pointer is just what we get from gcc. */ +#ifndef FIRST_FRAME_POINTER +# define FIRST_FRAME_POINTER __builtin_frame_address (0) +#endif + +int +__backtrace (array, size) + void **array; + int size; +{ + struct layout *current; + void *__unbounded top_frame; + void *__unbounded top_stack; + int cnt = 0; + + top_frame = FIRST_FRAME_POINTER; + top_stack = CURRENT_STACK_FRAME; + + /* We skip the call to this function, it makes no sense to record it. */ + current = BOUNDED_1 ((struct layout *) top_frame); + while (cnt < size) + { + if ((void *) current INNER_THAN top_stack + || !((void *) current INNER_THAN __libc_stack_end)) + /* This means the address is out of range. Note that for the + toplevel we see a frame pointer with value NULL which clearly is + out of range. */ + break; + + array[cnt++] = current->return_address; + + current = ADVANCE_STACK_FRAME (current->next); + } + + return cnt; +} +weak_alias (__backtrace, backtrace) +libc_hidden_def (__backtrace) diff --git a/debug/backtracesyms.c b/debug/backtracesyms.c new file mode 100644 index 0000000000..db7ba36d0f --- /dev/null +++ b/debug/backtracesyms.c @@ -0,0 +1,58 @@ +/* Return list with names for address in backtrace. + Copyright (C) 1998, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998. + + 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 <execinfo.h> +#include <stdlib.h> +#include <string.h> + + +/* Assume the worst for the width of an address. */ +#define WORD_WIDTH 16 + + +char ** +__backtrace_symbols (array, size) + void *const *array; + int size; +{ + int cnt; + size_t total = 0; + char **result; + + /* We can compute the text size needed for the symbols since we print + them all as "[+0x<addr>]". */ + total = size * (WORD_WIDTH + 6); + + /* Allocate memory for the result. */ + result = malloc (size * sizeof (char *) + total); + if (result != NULL) + { + char *last = (char *) (result + size); + + for (cnt = 0; cnt < size; ++cnt) + { + result[cnt] = last; + last += 1 + sprintf (last, "[+%p]", array[cnt]); + } + } + + return result; +} +weak_alias (__backtrace_symbols, backtrace_symbols) diff --git a/debug/backtracesymsfd.c b/debug/backtracesymsfd.c new file mode 100644 index 0000000000..b01f8b0094 --- /dev/null +++ b/debug/backtracesymsfd.c @@ -0,0 +1,64 @@ +/* Write formatted list with names for addresses in backtrace to a file. + Copyright (C) 1998, 2003, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998. + + 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 <execinfo.h> +#include <string.h> +#include <sys/uio.h> + +#include <stdio-common/_itoa.h> +#include <not-cancel.h> + +#if __ELF_NATIVE_CLASS == 32 +# define WORD_WIDTH 8 +#else +/* We assume 64bits. */ +# define WORD_WIDTH 16 +#endif + + +void +__backtrace_symbols_fd (array, size, fd) + void *const *array; + int size; + int fd; +{ + struct iovec iov[3]; + int cnt; + + for (cnt = 0; cnt < size; ++cnt) + { + char buf[WORD_WIDTH]; + + iov[0].iov_base = (void *) "[0x"; + iov[0].iov_len = 3; + + iov[1].iov_base = _itoa_word ((unsigned long int) array[cnt], + &buf[WORD_WIDTH], 16, 0); + iov[1].iov_len = &buf[WORD_WIDTH] - (char *) iov[1].iov_base; + + iov[2].iov_base = (void *) "]\n"; + iov[2].iov_len = 2; + + /* We prefer to use the non-cancelable interface if it is available. */ + writev_not_cancel_no_status (fd, iov, 3); + } +} +weak_alias (__backtrace_symbols_fd, backtrace_symbols_fd) +libc_hidden_def (__backtrace_symbols_fd) diff --git a/debug/catchsegv.sh b/debug/catchsegv.sh index 14556f712a..f4d971e34b 100755 --- a/debug/catchsegv.sh +++ b/debug/catchsegv.sh @@ -1,5 +1,5 @@ #! /bin/sh -# Copyright (C) 1998, 1999, 2001, 2003, 2004 Free Software Foundation, Inc. +# Copyright (C) 1998,1999,2001,2003,2004,2006 Free Software Foundation, Inc. # This file is part of the GNU C Library. # Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998. @@ -39,7 +39,7 @@ if test $# -eq 0; then ;; --v | --ve | --ver | --vers | --versi | --versio | --version) echo 'catchsegv (GNU libc) @VERSION@' - echo 'Copyright (C) 2004 Free Software Foundation, Inc. + echo 'Copyright (C) 2006 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Written by Ulrich Drepper.' diff --git a/debug/chk_fail.c b/debug/chk_fail.c index dc1c3d70b6..0cfca295a9 100644 --- a/debug/chk_fail.c +++ b/debug/chk_fail.c @@ -1,5 +1,4 @@ - -/* Copyright (C) 2004 Free Software Foundation, Inc. +/* Copyright (C) 2004, 2005 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 @@ -21,10 +20,15 @@ #include <stdlib.h> +extern char **__libc_argv attribute_hidden; + void __attribute__ ((noreturn)) __chk_fail (void) { - __libc_fatal ("*** buffer overflow detected ***\n"); + /* The loop is added only to keep gcc happy. */ + while (1) + __libc_message (2, "*** buffer overflow detected ***: %s terminated\n", + __libc_argv[0] ?: "<unknown>"); } libc_hidden_def (__chk_fail) diff --git a/debug/confstr_chk.c b/debug/confstr_chk.c new file mode 100644 index 0000000000..dae7714fcf --- /dev/null +++ b/debug/confstr_chk.c @@ -0,0 +1,30 @@ +/* Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@readhat.com>, 20055. + + 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 <unistd.h> + + +size_t +__confstr_chk (int name, char *buf, size_t len, size_t buflen) +{ + if (__builtin_expect (buflen < len, 0)) + __chk_fail (); + + return confstr (name, buf, len); +} diff --git a/debug/execinfo.h b/debug/execinfo.h index fa9927c71a..c1614cc1f0 100644 --- a/debug/execinfo.h +++ b/debug/execinfo.h @@ -1,4 +1,4 @@ -/* Copyright (C) 1998, 1999, 2004 Free Software Foundation, Inc. +/* Copyright (C) 1998, 1999, 2004, 2005 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 @@ -35,8 +35,7 @@ extern char **backtrace_symbols (void *__const *__array, int __size) /* This function is similar to backtrace_symbols() but it writes the result - immediately to a file and can therefore also be used in situations where - malloc() is not usable anymore. */ + immediately to a file. */ extern void backtrace_symbols_fd (void *__const *__array, int __size, int __fd) __THROW __nonnull ((1)); diff --git a/debug/fgets_chk.c b/debug/fgets_chk.c new file mode 100644 index 0000000000..27fbede7f0 --- /dev/null +++ b/debug/fgets_chk.c @@ -0,0 +1,67 @@ +/* Copyright (C) 1993, 1995, 1996, 1997, 1998, 1999, 2002, 2003, 2005 + 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 "libioP.h" +#include <stdio.h> +#include <sys/param.h> + +char * +__fgets_chk (buf, size, n, fp) + char *buf; + size_t size; + int n; + _IO_FILE *fp; +{ + _IO_size_t count; + char *result; + CHECK_FILE (fp, NULL); + if (n <= 0) + return NULL; + _IO_acquire_lock (fp); + /* 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 = fp->_IO_file_flags & _IO_ERR_SEEN; + fp->_IO_file_flags &= ~_IO_ERR_SEEN; + count = INTUSE(_IO_getline) (fp, buf, MIN ((size_t) n - 1, size), '\n', 1); + /* If we read in some bytes and errno is EAGAIN, that error will + be reported for next read. */ + if (count == 0 || ((fp->_IO_file_flags & _IO_ERR_SEEN) + && errno != EAGAIN)) + result = NULL; + else if (count >= size) + __chk_fail (); + else + { + buf[count] = '\0'; + result = buf; + } + fp->_IO_file_flags |= old_error; + _IO_release_lock (fp); + return result; +} diff --git a/debug/fgets_u_chk.c b/debug/fgets_u_chk.c new file mode 100644 index 0000000000..324d7e371b --- /dev/null +++ b/debug/fgets_u_chk.c @@ -0,0 +1,65 @@ +/* Copyright (C) 1993, 1995, 1996, 1997, 1998, 1999, 2002, 2003, 2005 + 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 "libioP.h" +#include <stdio.h> +#include <sys/param.h> + +char * +__fgets_unlocked_chk (buf, size, n, fp) + char *buf; + size_t size; + int n; + _IO_FILE *fp; +{ + _IO_size_t count; + char *result; + CHECK_FILE (fp, NULL); + if (n <= 0) + return NULL; + /* 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 = fp->_IO_file_flags & _IO_ERR_SEEN; + fp->_IO_file_flags &= ~_IO_ERR_SEEN; + count = INTUSE(_IO_getline) (fp, buf, MIN ((size_t) n - 1, size), '\n', 1); + /* If we read in some bytes and errno is EAGAIN, that error will + be reported for next read. */ + if (count == 0 || ((fp->_IO_file_flags & _IO_ERR_SEEN) + && errno != EAGAIN)) + result = NULL; + else if (count >= size) + __chk_fail (); + else + { + buf[count] = '\0'; + result = buf; + } + fp->_IO_file_flags |= old_error; + return result; +} diff --git a/debug/fgetws_chk.c b/debug/fgetws_chk.c new file mode 100644 index 0000000000..d080ccb473 --- /dev/null +++ b/debug/fgetws_chk.c @@ -0,0 +1,54 @@ +/* Copyright (C) 1993, 1995, 1996, 1997, 1998, 1999, 2001, 2005 + 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 "libioP.h" +#include <wchar.h> +#include <sys/param.h> + +wchar_t * +__fgetws_chk (wchar_t *buf, size_t size, int n, _IO_FILE *fp) +{ + _IO_size_t count; + wchar_t *result; + int old_error; + CHECK_FILE (fp, NULL); + if (n <= 0) + return NULL; + _IO_acquire_lock (fp); + /* 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. */ + old_error = fp->_IO_file_flags & _IO_ERR_SEEN; + fp->_IO_file_flags &= ~_IO_ERR_SEEN; + count = _IO_getwline (fp, buf, MIN ((size_t) n - 1, size), L'\n', 1); + /* If we read in some bytes and errno is EAGAIN, that error will + be reported for next read. */ + if (count == 0 || (_IO_ferror_unlocked (fp) && errno != EAGAIN)) + result = NULL; + else if (count >= size) + __chk_fail (); + else + { + buf[count] = '\0'; + result = buf; + } + fp->_IO_file_flags |= old_error; + _IO_release_lock (fp); + return result; +} diff --git a/debug/fgetws_u_chk.c b/debug/fgetws_u_chk.c new file mode 100644 index 0000000000..b6cc87b80d --- /dev/null +++ b/debug/fgetws_u_chk.c @@ -0,0 +1,61 @@ +/* Copyright (C) 1993, 95, 96, 97, 98, 99, 2005 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 "libioP.h" +#include <wchar.h> +#include <sys/param.h> + +wchar_t * +__fgetws_unlocked_chk (wchar_t *buf, size_t size, int n, _IO_FILE *fp) +{ + _IO_size_t count; + wchar_t *result; + int old_error; + CHECK_FILE (fp, NULL); + if (n <= 0) + return NULL; + /* 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. */ + old_error = fp->_IO_file_flags & _IO_ERR_SEEN; + fp->_IO_file_flags &= ~_IO_ERR_SEEN; + count = _IO_getwline (fp, buf, MIN ((size_t) n - 1, size), L'\n', 1); + /* If we read in some bytes and errno is EAGAIN, that error will + be reported for next read. */ + if (count == 0 || ((fp->_IO_file_flags & _IO_ERR_SEEN) + && errno != EAGAIN)) + result = NULL; + else if (count >= size) + __chk_fail (); + else + { + buf[count] = '\0'; + result = buf; + } + fp->_IO_file_flags |= old_error; + return result; +} diff --git a/debug/fprintf_chk.c b/debug/fprintf_chk.c index 2b7d22b6a6..58b5fb2b3e 100644 --- a/debug/fprintf_chk.c +++ b/debug/fprintf_chk.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991, 1995, 1996, 1997, 2001, 2004 +/* Copyright (C) 1991, 1995, 1996, 1997, 2001, 2004, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -24,7 +24,7 @@ /* Write formatted output to FP from the format string FORMAT. */ int -__fprintf_chk (FILE *fp, int flag, const char *format, ...) +___fprintf_chk (FILE *fp, int flag, const char *format, ...) { va_list ap; int done; @@ -43,3 +43,4 @@ __fprintf_chk (FILE *fp, int flag, const char *format, ...) return done; } +ldbl_strong_alias (___fprintf_chk, __fprintf_chk) diff --git a/debug/fwprintf_chk.c b/debug/fwprintf_chk.c new file mode 100644 index 0000000000..710c89f3c8 --- /dev/null +++ b/debug/fwprintf_chk.c @@ -0,0 +1,45 @@ +/* Copyright (C) 1991, 1995, 1996, 1997, 2001, 2004, 2005 + 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 <wchar.h> +#include "../libio/libioP.h" + + +/* Write formatted output to FP from the format string FORMAT. */ +int +__fwprintf_chk (FILE *fp, int flag, const wchar_t *format, ...) +{ + va_list ap; + int done; + + _IO_acquire_lock (fp); + if (flag > 0) + fp->_flags2 |= _IO_FLAGS2_FORTIFY; + + va_start (ap, format); + done = _IO_vfwprintf (fp, format, ap); + va_end (ap); + + if (flag > 0) + fp->_flags2 &= ~_IO_FLAGS2_FORTIFY; + _IO_release_lock (fp); + + return done; +} diff --git a/debug/getcwd_chk.c b/debug/getcwd_chk.c new file mode 100644 index 0000000000..cb864c858e --- /dev/null +++ b/debug/getcwd_chk.c @@ -0,0 +1,31 @@ +/* Copyright (C) 2005 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 <errno.h> +#include <unistd.h> +#include <sys/param.h> + + +char * +__getcwd_chk (char *buf, size_t size, size_t buflen) +{ + if (size > buflen) + __chk_fail (); + + return __getcwd (buf, size); +} diff --git a/debug/getdomainname_chk.c b/debug/getdomainname_chk.c new file mode 100644 index 0000000000..a85464589b --- /dev/null +++ b/debug/getdomainname_chk.c @@ -0,0 +1,29 @@ +/* Copyright (C) 2005 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 <unistd.h> + + +int +__getdomainname_chk (char *buf, size_t buflen, size_t nreal) +{ + if (buflen > nreal) + __chk_fail (); + + return getdomainname (buf, buflen); +} diff --git a/debug/getgroups_chk.c b/debug/getgroups_chk.c new file mode 100644 index 0000000000..c877ddb9ca --- /dev/null +++ b/debug/getgroups_chk.c @@ -0,0 +1,30 @@ +/* Copyright (C) 2005 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 <errno.h> +#include <unistd.h> + + +int +__getgroups_chk (int size, __gid_t list[], size_t listlen) +{ + if (__builtin_expect (size * sizeof (__gid_t) > listlen, 0)) + __chk_fail (); + + return __getgroups (size, list); +} diff --git a/debug/gethostname_chk.c b/debug/gethostname_chk.c new file mode 100644 index 0000000000..734cc56b0b --- /dev/null +++ b/debug/gethostname_chk.c @@ -0,0 +1,29 @@ +/* Copyright (C) 2005 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 <unistd.h> + + +int +__gethostname_chk (char *buf, size_t buflen, size_t nreal) +{ + if (buflen > nreal) + __chk_fail (); + + return __gethostname (buf, buflen); +} diff --git a/debug/getlogin_r_chk.c b/debug/getlogin_r_chk.c new file mode 100644 index 0000000000..ae495cd7ab --- /dev/null +++ b/debug/getlogin_r_chk.c @@ -0,0 +1,29 @@ +/* Copyright (C) 2005 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 <unistd.h> + + +int +__getlogin_r_chk (char *buf, size_t buflen, size_t nreal) +{ + if (buflen > nreal) + __chk_fail (); + + return getlogin_r (buf, buflen); +} diff --git a/debug/getwd_chk.c b/debug/getwd_chk.c new file mode 100644 index 0000000000..898af28d3f --- /dev/null +++ b/debug/getwd_chk.c @@ -0,0 +1,34 @@ +/* Copyright (C) 2005 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 <errno.h> +#include <unistd.h> +#include <sys/param.h> + + +char * +__getwd_chk (char *buf, size_t buflen) +{ + char *res = __getcwd (buf, buflen); + if (res == NULL && errno == ERANGE) + __chk_fail (); + return res; +} + +link_warning (getwd, + "the `getwd' function is dangerous and should not be used.") diff --git a/debug/mbsnrtowcs_chk.c b/debug/mbsnrtowcs_chk.c new file mode 100644 index 0000000000..8872540ee0 --- /dev/null +++ b/debug/mbsnrtowcs_chk.c @@ -0,0 +1,31 @@ +/* Copyright (C) 2005 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 <locale.h> +#include <wchar.h> + + +size_t +__mbsnrtowcs_chk (wchar_t *dst, __const char **src, size_t nmc, size_t len, + mbstate_t *ps, size_t dstlen) +{ + if (__builtin_expect (dstlen < len, 0)) + __chk_fail (); + + return __mbsnrtowcs (dst, src, nmc, len, ps); +} diff --git a/debug/mbsrtowcs_chk.c b/debug/mbsrtowcs_chk.c new file mode 100644 index 0000000000..22d5a35580 --- /dev/null +++ b/debug/mbsrtowcs_chk.c @@ -0,0 +1,31 @@ +/* Copyright (C) 2005 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 <locale.h> +#include <wchar.h> + + +size_t +__mbsrtowcs_chk (wchar_t *dst, __const char **src, size_t len, + mbstate_t *ps, size_t dstlen) +{ + if (__builtin_expect (dstlen < len, 0)) + __chk_fail (); + + return __mbsrtowcs (dst, src, len, ps); +} diff --git a/debug/mbstowcs_chk.c b/debug/mbstowcs_chk.c new file mode 100644 index 0000000000..d1403c5d2b --- /dev/null +++ b/debug/mbstowcs_chk.c @@ -0,0 +1,35 @@ +/* Copyright (C) 2005 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 <locale.h> +#include <string.h> +#include <wchar.h> + + +size_t +__mbstowcs_chk (wchar_t *dst, const char *src, size_t len, size_t dstlen) +{ + if (__builtin_expect (dstlen < len, 0)) + __chk_fail (); + + mbstate_t state; + + memset (&state, '\0', sizeof state); + /* Return how many we wrote (or maybe an error). */ + return __mbsrtowcs (dst, &src, len, &state); +} diff --git a/debug/memcpy_chk.c b/debug/memcpy_chk.c new file mode 100644 index 0000000000..638cd0e4fb --- /dev/null +++ b/debug/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/debug/memmove_chk.c b/debug/memmove_chk.c new file mode 100644 index 0000000000..f3b74d23d9 --- /dev/null +++ b/debug/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/debug/mempcpy_chk.c b/debug/mempcpy_chk.c new file mode 100644 index 0000000000..5297bbab92 --- /dev/null +++ b/debug/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/debug/memset_chk.c b/debug/memset_chk.c new file mode 100644 index 0000000000..d6206ffc99 --- /dev/null +++ b/debug/memset_chk.c @@ -0,0 +1,92 @@ +/* Copyright (C) 1991, 1997, 2003, 2004, 2005 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/debug/pread64_chk.c b/debug/pread64_chk.c new file mode 100644 index 0000000000..318579f0b5 --- /dev/null +++ b/debug/pread64_chk.c @@ -0,0 +1,30 @@ +/* Copyright (C) 2005 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 <unistd.h> +#include <sys/param.h> + + +ssize_t +__pread64_chk (int fd, void *buf, size_t nbytes, off64_t offset, size_t buflen) +{ + if (nbytes > buflen) + __chk_fail (); + + return __libc_pread64 (fd, buf, nbytes, offset); +} diff --git a/debug/pread_chk.c b/debug/pread_chk.c new file mode 100644 index 0000000000..de111eaf82 --- /dev/null +++ b/debug/pread_chk.c @@ -0,0 +1,30 @@ +/* Copyright (C) 2005 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 <unistd.h> +#include <sys/param.h> + + +ssize_t +__pread_chk (int fd, void *buf, size_t nbytes, off_t offset, size_t buflen) +{ + if (nbytes > buflen) + __chk_fail (); + + return __pread (fd, buf, nbytes, offset); +} diff --git a/debug/printf_chk.c b/debug/printf_chk.c index 86096b45c0..b8f00965dc 100644 --- a/debug/printf_chk.c +++ b/debug/printf_chk.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991, 1995, 1996, 1997, 2001, 2004 +/* Copyright (C) 1991, 1995, 1996, 1997, 2001, 2004, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -24,7 +24,7 @@ /* Write formatted output to stdout from the format string FORMAT. */ int -__printf_chk (int flag, const char *format, ...) +___printf_chk (int flag, const char *format, ...) { va_list ap; int done; @@ -43,3 +43,4 @@ __printf_chk (int flag, const char *format, ...) return done; } +ldbl_strong_alias (___printf_chk, __printf_chk) diff --git a/debug/ptsname_r_chk.c b/debug/ptsname_r_chk.c new file mode 100644 index 0000000000..5f03592bd1 --- /dev/null +++ b/debug/ptsname_r_chk.c @@ -0,0 +1,29 @@ +/* Copyright (C) 2005 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> + + +int +__ptsname_r_chk (int fd, char *buf, size_t buflen, size_t nreal) +{ + if (buflen > nreal) + __chk_fail (); + + return __ptsname_r (fd, buf, buflen); +} diff --git a/debug/read_chk.c b/debug/read_chk.c new file mode 100644 index 0000000000..da2bc945b7 --- /dev/null +++ b/debug/read_chk.c @@ -0,0 +1,38 @@ +/* Copyright (C) 2005 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 <unistd.h> +#include <sys/param.h> +#ifdef HAVE_INLINED_SYSCALLS +# include <errno.h> +# include <sysdep.h> +#endif + + +ssize_t +__read_chk (int fd, void *buf, size_t nbytes, size_t buflen) +{ + if (nbytes > buflen) + __chk_fail (); + +#ifdef HAVE_INLINED_SYSCALLS + return INLINE_SYSCALL (read, 3, fd, buf, nbytes); +#else + return __read (fd, buf, nbytes); +#endif +} diff --git a/debug/readlink_chk.c b/debug/readlink_chk.c new file mode 100644 index 0000000000..ac18ee2c29 --- /dev/null +++ b/debug/readlink_chk.c @@ -0,0 +1,38 @@ +/* Copyright (C) 2005 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 <unistd.h> +#include <sys/param.h> +#ifdef HAVE_INLINED_SYSCALLS +# include <errno.h> +# include <sysdep.h> +#endif + + +ssize_t +__readlink_chk (const char *path, void *buf, size_t len, size_t buflen) +{ + if (len > buflen) + __chk_fail (); + +#ifdef HAVE_INLINED_SYSCALLS + return INLINE_SYSCALL (readlink, 3, path, buf, len); +#else + return __readlink (path, buf, len); +#endif +} diff --git a/debug/readlinkat_chk.c b/debug/readlinkat_chk.c new file mode 100644 index 0000000000..eab99c0ea9 --- /dev/null +++ b/debug/readlinkat_chk.c @@ -0,0 +1,31 @@ +/* Copyright (C) 2006 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 <unistd.h> +#include <sys/param.h> + + +ssize_t +__readlinkat_chk (int fd, const char *path, void *buf, size_t len, + size_t buflen) +{ + if (len > buflen) + __chk_fail (); + + return readlinkat (fd, path, buf, len); +} diff --git a/debug/readonly-area.c b/debug/readonly-area.c new file mode 100644 index 0000000000..4b8172f193 --- /dev/null +++ b/debug/readonly-area.c @@ -0,0 +1,34 @@ +/* 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> + +/* Return 1 if the whole area PTR .. PTR+SIZE is not writable. + Return -1 if it is writable. */ + +int +__readonly_area (const void *ptr, size_t size) +{ + /* We cannot determine in general whether memory is writable or not. + This must be handled in a system-dependent manner. to not + unconditionally break code we need to return here a positive + answer. This disables this security measure but that is the + price people have to pay for using systems without a real + implementation of this interface. */ + return 1; +} diff --git a/debug/realpath_chk.c b/debug/realpath_chk.c new file mode 100644 index 0000000000..961aea0b85 --- /dev/null +++ b/debug/realpath_chk.c @@ -0,0 +1,60 @@ +/* Copyright (C) 2005 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 <limits.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + + +char * +__realpath_chk (const char *buf, char *resolved, size_t resolvedlen) +{ +#ifdef PATH_MAX + if (resolvedlen < PATH_MAX) + __chk_fail (); + + return __realpath (buf, resolved); +#else + long int pathmax =__pathconf (buf, _PC_PATH_MAX); + if (pathmax != -1) + { + /* We do have a fixed limit. */ + if (resolvedlen < pathmax) + __chk_fail (); + + return __realpath (buf, resolved); + } + + /* Since there is no fixed limit we check whether the size is large + enough. */ + char *res = __realpath (buf, NULL); + if (res != NULL) + { + size_t actlen = strlen (res) + 1; + if (actlen > resolvedlen) + __chk_fail (); + + memcpy (resolved, res, actlen); + free (res); + res = resolved; + } + + return res; +#endif +} diff --git a/debug/recv_chk.c b/debug/recv_chk.c new file mode 100644 index 0000000000..479ebdfe72 --- /dev/null +++ b/debug/recv_chk.c @@ -0,0 +1,30 @@ +/* Copyright (C) 2005 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 <sys/param.h> +#include <sys/socket.h> + + +ssize_t +__recv_chk (int fd, void *buf, size_t n, size_t buflen, int flags) +{ + if (n > buflen) + __chk_fail (); + + return __recv (fd, buf, n, flags); +} diff --git a/debug/recvfrom_chk.c b/debug/recvfrom_chk.c new file mode 100644 index 0000000000..9790a15deb --- /dev/null +++ b/debug/recvfrom_chk.c @@ -0,0 +1,31 @@ +/* Copyright (C) 2005 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 <sys/param.h> +#include <sys/socket.h> + + +ssize_t +__recvfrom_chk (int fd, void *buf, size_t n, size_t buflen, int flags, + __SOCKADDR_ARG addr, socklen_t *addr_len) +{ + if (n > buflen) + __chk_fail (); + + return __recvfrom (fd, buf, n, flags, addr, addr_len); +} diff --git a/debug/segfault.c b/debug/segfault.c new file mode 100644 index 0000000000..f141fff661 --- /dev/null +++ b/debug/segfault.c @@ -0,0 +1,214 @@ +/* Catch segmentation faults and print backtrace. + Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998. + + 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 <alloca.h> +#include <ctype.h> +#include <errno.h> +#include <execinfo.h> +#include <fcntl.h> +#include <signal.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <stdio-common/_itoa.h> +#include <ldsodefs.h> + +#include <bp-checks.h> + +/* This file defines macros to access the content of the sigcontext element + passed up by the signal handler. */ +#include <sigcontextinfo.h> + +/* Get code to possibly dump the content of all registers. */ +#include <register-dump.h> + +/* We'll use tis a lot. */ +#define WRITE_STRING(s) write (fd, s, strlen (s)) + +/* Name of the output file. */ +static const char *fname; + + +/* We better should not use `strerror' since it can call far too many + other functions which might fail. Do it here ourselves. */ +static void +write_strsignal (int fd, int signal) +{ + if (signal < 0 || signal >= _NSIG || _sys_siglist[signal] == NULL) + { + char buf[30]; + char *ptr = _itoa_word (signal, &buf[sizeof (buf)], 10, 0); + WRITE_STRING ("signal "); + write (fd, buf, &buf[sizeof (buf)] - ptr); + } + else + WRITE_STRING (_sys_siglist[signal]); +} + + +/* This function is called when a segmentation fault is caught. The system + is in an instable state now. This means especially that malloc() might + not work anymore. */ +static void +catch_segfault (int signal, SIGCONTEXT ctx) +{ + int fd, cnt, i; + void **arr; + struct sigaction sa; + uintptr_t pc; + + /* This is the name of the file we are writing to. If none is given + or we cannot write to this file write to stderr. */ + fd = 2; + if (fname != NULL) + { + fd = open (fname, O_TRUNC | O_WRONLY | O_CREAT, 0666); + if (fd == -1) + fd = 2; + } + + WRITE_STRING ("*** "); + write_strsignal (fd, signal); + WRITE_STRING ("\n"); + +#ifdef REGISTER_DUMP + REGISTER_DUMP; +#endif + + WRITE_STRING ("\nBacktrace:\n"); + + /* Get the backtrace. */ + arr = alloca (256 * sizeof (void *)); + cnt = backtrace (arr, 256); + + /* Now try to locate the PC from signal context in the backtrace. + Normally it will be found at arr[2], but it might appear later + if there were some signal handler wrappers. Allow a few bytes + difference to cope with as many arches as possible. */ + pc = (uintptr_t) GET_PC (ctx); + for (i = 0; i < cnt; ++i) + if ((uintptr_t) arr[i] >= pc - 16 && (uintptr_t) arr[i] <= pc + 16) + break; + + /* If we haven't found it, better dump full backtrace even including + the signal handler frames instead of not dumping anything. */ + if (i == cnt) + i = 0; + + /* Now generate nicely formatted output. */ + __backtrace_symbols_fd (arr + i, cnt - i, fd); + +#ifdef HAVE_PROC_SELF + /* Now the link map. */ + int mapfd = open ("/proc/self/maps", O_RDONLY); + if (mapfd != -1) + { + write (fd, "\nMemory map:\n\n", 14); + + char buf[256]; + ssize_t n; + + while ((n = TEMP_FAILURE_RETRY (read (mapfd, buf, sizeof (buf)))) > 0) + TEMP_FAILURE_RETRY (write (fd, buf, n)); + + close (mapfd); + } +#endif + + /* Pass on the signal (so that a core file is produced). */ + sa.sa_handler = SIG_DFL; + sigemptyset (&sa.sa_mask); + sa.sa_flags = 0; + sigaction (signal, &sa, NULL); + raise (signal); +} + + +static void +__attribute__ ((constructor)) +install_handler (void) +{ + struct sigaction sa; + const char *sigs = getenv ("SEGFAULT_SIGNALS"); + const char *name; + + sa.sa_handler = (void *) catch_segfault; + sigemptyset (&sa.sa_mask); + sa.sa_flags = SA_RESTART; + + /* Maybe we are expected to use an alternative stack. */ + if (getenv ("SEGFAULT_USE_ALTSTACK") != 0) + { + void *stack_mem = malloc (2 * SIGSTKSZ); + struct sigaltstack ss; + + if (stack_mem != NULL) + { + ss.ss_sp = stack_mem; + ss.ss_flags = 0; + ss.ss_size = 2 * SIGSTKSZ; + + if (sigaltstack (&ss, NULL) == 0) + sa.sa_flags |= SA_ONSTACK; + } + } + + if (sigs == NULL) + sigaction (SIGSEGV, &sa, NULL); + else if (sigs[0] == '\0') + /* Do not do anything. */ + return; + else + { + const char *where; + int all = __strcasecmp (sigs, "all") == 0; + +#define INSTALL_FOR_SIG(sig, name) \ + where = __strcasestr (sigs, name); \ + if (all || (where != NULL \ + && (where == sigs || !isalnum (where[-1])) \ + && !isalnum (where[sizeof (name) - 1]))) \ + sigaction (sig, &sa, NULL); + + INSTALL_FOR_SIG (SIGSEGV, "segv"); + INSTALL_FOR_SIG (SIGILL, "ill"); +#ifdef SIGBUS + INSTALL_FOR_SIG (SIGBUS, "bus"); +#endif +#ifdef SIGSTKFLT + INSTALL_FOR_SIG (SIGSTKFLT, "stkflt"); +#endif + INSTALL_FOR_SIG (SIGABRT, "abrt"); + INSTALL_FOR_SIG (SIGFPE, "fpe"); + } + + /* Preserve the output file name if there is any given. */ + name = getenv ("SEGFAULT_OUTPUT_NAME"); + if (name != NULL && name[0] != '\0') + { + int ret = access (name, R_OK | W_OK); + + if (ret == 0 || (ret == -1 && errno == ENOENT)) + fname = __strdup (name); + } +} diff --git a/debug/snprintf_chk.c b/debug/snprintf_chk.c index 5a77afef29..315d47c88b 100644 --- a/debug/snprintf_chk.c +++ b/debug/snprintf_chk.c @@ -1,4 +1,5 @@ -/* Copyright (C) 1991, 1995, 1997, 1998, 2004 Free Software Foundation, Inc. +/* Copyright (C) 1991, 1995, 1997, 1998, 2004, 2006 + 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,6 +17,7 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ +#include <libioP.h> #include <stdarg.h> #include <stdio.h> @@ -24,8 +26,8 @@ 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, ...) +___snprintf_chk (char *s, size_t maxlen, int flags, size_t slen, + const char *format, ...) { va_list arg; int done; @@ -36,3 +38,4 @@ __snprintf_chk (char *s, size_t maxlen, int flags, size_t slen, return done; } +ldbl_strong_alias (___snprintf_chk, __snprintf_chk) diff --git a/debug/sprintf_chk.c b/debug/sprintf_chk.c index d141633b9f..658c0cccda 100644 --- a/debug/sprintf_chk.c +++ b/debug/sprintf_chk.c @@ -1,4 +1,5 @@ -/* Copyright (C) 1991,1995,1997,1998,2002,2004 Free Software Foundation, Inc. +/* Copyright (C) 1991, 1995, 1997, 1998, 2002, 2004, 2006 + 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,13 +17,14 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ +#include <libioP.h> #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, ...) +___sprintf_chk (char *s, int flags, size_t slen, const char *format, ...) { va_list arg; int done; @@ -33,3 +35,4 @@ __sprintf_chk (char *s, int flags, size_t slen, const char *format, ...) return done; } +ldbl_strong_alias (___sprintf_chk, __sprintf_chk) diff --git a/debug/stack_chk_fail.c b/debug/stack_chk_fail.c new file mode 100644 index 0000000000..298b323671 --- /dev/null +++ b/debug/stack_chk_fail.c @@ -0,0 +1,33 @@ +/* Copyright (C) 2005 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 <stdio.h> +#include <stdlib.h> + + +extern char **__libc_argv attribute_hidden; + +void +__attribute__ ((noreturn)) +__stack_chk_fail (void) +{ + /* The loop is added only to keep gcc happy. */ + while (1) + __libc_message (1, "*** stack smashing detected ***: %s terminated\n", + __libc_argv[0] ?: "<unknown>"); +} diff --git a/debug/stack_chk_fail_local.c b/debug/stack_chk_fail_local.c new file mode 100644 index 0000000000..de0de8f397 --- /dev/null +++ b/debug/stack_chk_fail_local.c @@ -0,0 +1,30 @@ +/* Copyright (C) 2005 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 <sys/cdefs.h> + +extern void __stack_chk_fail (void) __attribute__ ((noreturn)); + +/* On some architectures, this helps needless PIC pointer setup + that would be needed just for the __stack_chk_fail call. */ + +void __attribute__ ((noreturn)) attribute_hidden +__stack_chk_fail_local (void) +{ + __stack_chk_fail (); +} diff --git a/debug/stpcpy_chk.c b/debug/stpcpy_chk.c new file mode 100644 index 0000000000..dacda0115a --- /dev/null +++ b/debug/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/debug/stpncpy_chk.c b/debug/stpncpy_chk.c new file mode 100644 index 0000000000..d136339dea --- /dev/null +++ b/debug/stpncpy_chk.c @@ -0,0 +1,85 @@ +/* Copyright (C) 1993,1995,1996,1997,2002,2005 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. */ + +/* This is almost copied from strncpy.c, written by Torbjorn Granlund. */ + +#include <string.h> + + +/* Copy no more than N characters of SRC to DEST, returning the address of + the terminating '\0' in DEST, if any, or else DEST + N. */ +char * +__stpncpy_chk (char *dest, const char *src, size_t n, size_t destlen) +{ + char c; + char *s = dest; + + if (__builtin_expect (destlen < n, 0)) + __chk_fail (); + + if (n >= 4) + { + size_t n4 = n >> 2; + + for (;;) + { + c = *src++; + *dest++ = c; + if (c == '\0') + break; + c = *src++; + *dest++ = c; + if (c == '\0') + break; + c = *src++; + *dest++ = c; + if (c == '\0') + break; + c = *src++; + *dest++ = c; + if (c == '\0') + break; + if (--n4 == 0) + goto last_chars; + } + n -= dest - s; + goto zero_fill; + } + + last_chars: + n &= 3; + if (n == 0) + return dest; + + for (;;) + { + c = *src++; + --n; + *dest++ = c; + if (c == '\0') + break; + if (n == 0) + return dest; + } + + zero_fill: + while (n-- > 0) + dest[n] = '\0'; + + return dest - 1; +} diff --git a/debug/strcat_chk.c b/debug/strcat_chk.c new file mode 100644 index 0000000000..b3fb3470b7 --- /dev/null +++ b/debug/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/debug/strcpy_chk.c b/debug/strcpy_chk.c new file mode 100644 index 0000000000..a4d909feda --- /dev/null +++ b/debug/strcpy_chk.c @@ -0,0 +1,68 @@ +/* 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; + + while (__builtin_expect (destlen >= 4, 0)) + { + c = s[0]; + s[off] = c; + if (c == '\0') + return dest; + c = s[1]; + s[off + 1] = c; + if (c == '\0') + return dest; + c = s[2]; + s[off + 2] = c; + if (c == '\0') + return dest; + c = s[3]; + s[off + 3] = c; + if (c == '\0') + return dest; + destlen -= 4; + s += 4; + } + + do + { + if (__builtin_expect (destlen-- == 0, 0)) + __chk_fail (); + c = *s; + *(s++ + off) = c; + } + while (c != '\0'); + + return dest; +} diff --git a/debug/strncat_chk.c b/debug/strncat_chk.c new file mode 100644 index 0000000000..953b435a4b --- /dev/null +++ b/debug/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/debug/strncpy_chk.c b/debug/strncpy_chk.c new file mode 100644 index 0000000000..bdede7738b --- /dev/null +++ b/debug/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/debug/swprintf_chk.c b/debug/swprintf_chk.c new file mode 100644 index 0000000000..554cbe66a3 --- /dev/null +++ b/debug/swprintf_chk.c @@ -0,0 +1,37 @@ +/* Copyright (C) 1991,1995,1997,1998,1999,2000,2003,2005 + 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 <wchar.h> + +/* Write formatted output into S, according to the format string FORMAT. */ +/* VARARGS5 */ +int +__swprintf_chk (wchar_t *s, size_t n, int flag, size_t s_len, + const wchar_t *format, ...) +{ + va_list arg; + int done; + + va_start (arg, format); + done = __vswprintf_chk (s, n, flag, s_len, format, arg); + va_end (arg); + + return done; +} diff --git a/debug/tst-chk1.c b/debug/tst-chk1.c index 0df660d57f..c450744af5 100644 --- a/debug/tst-chk1.c +++ b/debug/tst-chk1.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2004 Free Software Foundation, Inc. +/* Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Jakub Jelinek <jakub@redhat.com>, 2004. @@ -17,7 +17,12 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ +/* Hack: make sure GCC doesn't know __chk_fail () will not return. */ +#define __noreturn__ + +#include <assert.h> #include <fcntl.h> +#include <locale.h> #include <paths.h> #include <setjmp.h> #include <signal.h> @@ -25,6 +30,9 @@ #include <stdlib.h> #include <string.h> #include <unistd.h> +#include <wchar.h> +#include <sys/socket.h> +#include <sys/un.h> char *temp_filename; static void do_prepare (void); @@ -69,13 +77,20 @@ handler (int sig) } char buf[10]; +wchar_t wbuf[10]; volatile size_t l0; volatile char *p; +volatile wchar_t *wp; const char *str1 = "JIHGFEDCBA"; const char *str2 = "F"; const char *str3 = "%s%n%s%n"; const char *str4 = "Hello, "; const char *str5 = "World!\n"; +const wchar_t *wstr1 = L"JIHGFEDCBA"; +const wchar_t *wstr2 = L"F"; +const wchar_t *wstr3 = L"%s%n%s%n"; +const wchar_t *wstr4 = L"Hello, "; +const wchar_t *wstr5 = L"World!\n"; char buf2[10] = "%s"; int num1 = 67; int num2 = 987654; @@ -120,6 +135,7 @@ do_test (void) setenv ("LIBC_FATAL_STDERR_", "1", 1); struct A { char buf1[9]; char buf2[1]; } a; + struct wA { wchar_t buf1[9]; wchar_t buf2[1]; } wa; printf ("Test checking routines at fortify level %d\n", #ifdef __USE_FORTIFY_LEVEL @@ -135,7 +151,8 @@ do_test (void) if (memcmp (buf, "aabcdefghi", 10)) FAIL (); - if (mempcpy (buf + 5, "abcde", 5) != buf + 10 || memcmp (buf, "aabcdabcde", 10)) + if (mempcpy (buf + 5, "abcde", 5) != buf + 10 + || memcmp (buf, "aabcdabcde", 10)) FAIL (); memset (buf + 8, 'j', 2); @@ -166,7 +183,8 @@ do_test (void) if (memcmp (buf, "aabcdefghi", 10)) FAIL (); - if (mempcpy (buf + 5, "abcde", l0 + 5) != buf + 10 || memcmp (buf, "aabcdabcde", 10)) + if (mempcpy (buf + 5, "abcde", l0 + 5) != buf + 10 + || memcmp (buf, "aabcdabcde", 10)) FAIL (); memset (buf + 8, 'j', l0 + 2); @@ -184,20 +202,24 @@ do_test (void) if (memcmp (buf, "aabcEDX\0\0", 10)) FAIL (); - if (sprintf (buf + 7, "%d", num1) != 2 || memcmp (buf, "aabcEDX67", 10)) + if (stpncpy (buf + 5, "cd", l0 + 5) != buf + 7 + || memcmp (buf, "aabcEcd\0\0", 10)) + FAIL (); + + if (sprintf (buf + 7, "%d", num1) != 2 || memcmp (buf, "aabcEcd67", 10)) FAIL (); - if (snprintf (buf + 7, 3, "%d", num2) != 6 || memcmp (buf, "aabcEDX98", 10)) + if (snprintf (buf + 7, 3, "%d", num2) != 6 || memcmp (buf, "aabcEcd98", 10)) FAIL (); buf[l0 + 8] = '\0'; strcat (buf, "A"); - if (memcmp (buf, "aabcEDX9A", 10)) + if (memcmp (buf, "aabcEcd9A", 10)) FAIL (); buf[l0 + 7] = '\0'; strncat (buf, "ZYXWV", l0 + 2); - if (memcmp (buf, "aabcEDXZY", 10)) + if (memcmp (buf, "aabcEcdZY", 10)) FAIL (); memcpy (a.buf1, "abcdefghij", l0 + 10); @@ -213,7 +235,7 @@ do_test (void) if (memcmp (a.buf1, "aabcdabcjj", 10)) FAIL (); -#if __USE_FORTIFY_LEVEL < 2 +#if __USE_FORTIFY_LEVEL < 2 || !__GNUC_PREREQ (4, 0) /* 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. */ @@ -221,14 +243,16 @@ do_test (void) if (memcmp (a.buf1, "aabcEDCBA", 10)) FAIL (); - if (stpcpy (a.buf1 + 8, str2) != a.buf1 + 9 || memcmp (a.buf1, "aabcEDCBF", 10)) + 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)) + if (sprintf (a.buf1 + 7, "%d", num1) != 2 + || memcmp (a.buf1, "aabcEDX67", 10)) FAIL (); if (snprintf (a.buf1 + 7, 3, "%d", num2) != 6 @@ -279,6 +303,10 @@ do_test (void) CHK_FAIL_END CHK_FAIL_START + stpncpy (buf + 6, "cd", l0 + 5); + CHK_FAIL_END + + CHK_FAIL_START sprintf (buf + 8, "%d", num1); CHK_FAIL_END @@ -312,7 +340,7 @@ do_test (void) memset (a.buf1 + 9, 'j', l0 + 2); CHK_FAIL_END -#if __USE_FORTIFY_LEVEL >= 2 +#if __USE_FORTIFY_LEVEL >= 2 && __GNUC_PREREQ (4, 0) # define O 0 #else # define O 1 @@ -349,6 +377,219 @@ do_test (void) CHK_FAIL_END #endif + + /* These ops can be done without runtime checking of object size. */ + wmemcpy (wbuf, L"abcdefghij", 10); + wmemmove (wbuf + 1, wbuf, 9); + if (wmemcmp (wbuf, L"aabcdefghi", 10)) + FAIL (); + + if (wmempcpy (wbuf + 5, L"abcde", 5) != wbuf + 10 + || wmemcmp (wbuf, L"aabcdabcde", 10)) + FAIL (); + + wmemset (wbuf + 8, L'j', 2); + if (wmemcmp (wbuf, L"aabcdabcjj", 10)) + FAIL (); + + wcscpy (wbuf + 4, L"EDCBA"); + if (wmemcmp (wbuf, L"aabcEDCBA", 10)) + FAIL (); + + if (wcpcpy (wbuf + 8, L"F") != wbuf + 9 || wmemcmp (wbuf, L"aabcEDCBF", 10)) + FAIL (); + + wcsncpy (wbuf + 6, L"X", 4); + if (wmemcmp (wbuf, L"aabcEDX\0\0", 10)) + FAIL (); + + if (swprintf (wbuf + 7, 3, L"%ls", L"987654") >= 0 + || wmemcmp (wbuf, L"aabcEDX98", 10)) + FAIL (); + + if (swprintf (wbuf + 7, 3, L"64") != 2 + || wmemcmp (wbuf, L"aabcEDX64", 10)) + FAIL (); + + /* These ops need runtime checking, but shouldn't __chk_fail. */ + wmemcpy (wbuf, L"abcdefghij", l0 + 10); + wmemmove (wbuf + 1, wbuf, l0 + 9); + if (wmemcmp (wbuf, L"aabcdefghi", 10)) + FAIL (); + + if (wmempcpy (wbuf + 5, L"abcde", l0 + 5) != wbuf + 10 + || wmemcmp (wbuf, L"aabcdabcde", 10)) + FAIL (); + + wmemset (wbuf + 8, L'j', l0 + 2); + if (wmemcmp (wbuf, L"aabcdabcjj", 10)) + FAIL (); + + wcscpy (wbuf + 4, wstr1 + 5); + if (wmemcmp (wbuf, L"aabcEDCBA", 10)) + FAIL (); + + if (wcpcpy (wbuf + 8, wstr2) != wbuf + 9 || wmemcmp (wbuf, L"aabcEDCBF", 10)) + FAIL (); + + wcsncpy (wbuf + 6, L"X", l0 + 4); + if (wmemcmp (wbuf, L"aabcEDX\0\0", 10)) + FAIL (); + + if (wcpncpy (wbuf + 5, L"cd", l0 + 5) != wbuf + 7 + || wmemcmp (wbuf, L"aabcEcd\0\0", 10)) + FAIL (); + + if (swprintf (wbuf + 7, 3, L"%d", num2) >= 0 + || wmemcmp (wbuf, L"aabcEcd98", 10)) + FAIL (); + + wbuf[l0 + 8] = L'\0'; + wcscat (wbuf, L"A"); + if (wmemcmp (wbuf, L"aabcEcd9A", 10)) + FAIL (); + + wbuf[l0 + 7] = L'\0'; + wcsncat (wbuf, L"ZYXWV", l0 + 2); + if (wmemcmp (wbuf, L"aabcEcdZY", 10)) + FAIL (); + + wmemcpy (wa.buf1, L"abcdefghij", l0 + 10); + wmemmove (wa.buf1 + 1, wa.buf1, l0 + 9); + if (wmemcmp (wa.buf1, L"aabcdefghi", 10)) + FAIL (); + + if (wmempcpy (wa.buf1 + 5, L"abcde", l0 + 5) != wa.buf1 + 10 + || wmemcmp (wa.buf1, L"aabcdabcde", 10)) + FAIL (); + + wmemset (wa.buf1 + 8, L'j', l0 + 2); + if (wmemcmp (wa.buf1, L"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. */ + wcscpy (wa.buf1 + 4, wstr1 + 5); + if (wmemcmp (wa.buf1, L"aabcEDCBA", 10)) + FAIL (); + + if (wcpcpy (wa.buf1 + 8, wstr2) != wa.buf1 + 9 + || wmemcmp (wa.buf1, L"aabcEDCBF", 10)) + FAIL (); + + wcsncpy (wa.buf1 + 6, L"X", l0 + 4); + if (wmemcmp (wa.buf1, L"aabcEDX\0\0", 10)) + FAIL (); + + if (swprintf (wa.buf1 + 7, 3, L"%d", num2) >= 0 + || wmemcmp (wa.buf1, L"aabcEDX98", 10)) + FAIL (); + + wa.buf1[l0 + 8] = L'\0'; + wcscat (wa.buf1, L"A"); + if (wmemcmp (wa.buf1, L"aabcEDX9A", 10)) + FAIL (); + + wa.buf1[l0 + 7] = L'\0'; + wcsncat (wa.buf1, L"ZYXWV", l0 + 2); + if (wmemcmp (wa.buf1, L"aabcEDXZY", 10)) + FAIL (); + +#endif + +#if __USE_FORTIFY_LEVEL >= 1 + /* Now check if all buffer overflows are caught at runtime. */ + + CHK_FAIL_START + wmemcpy (wbuf + 1, L"abcdefghij", l0 + 10); + CHK_FAIL_END + + CHK_FAIL_START + wmemmove (wbuf + 2, wbuf + 1, l0 + 9); + CHK_FAIL_END + + CHK_FAIL_START + wp = wmempcpy (wbuf + 6, L"abcde", l0 + 5); + CHK_FAIL_END + + CHK_FAIL_START + wmemset (wbuf + 9, L'j', l0 + 2); + CHK_FAIL_END + + CHK_FAIL_START + wcscpy (wbuf + 5, wstr1 + 5); + CHK_FAIL_END + + CHK_FAIL_START + wp = wcpcpy (wbuf + 9, wstr2); + CHK_FAIL_END + + CHK_FAIL_START + wcsncpy (wbuf + 7, L"X", l0 + 4); + CHK_FAIL_END + + CHK_FAIL_START + wcpncpy (wbuf + 6, L"cd", l0 + 5); + CHK_FAIL_END + + wmemcpy (wbuf, wstr1 + 2, l0 + 9); + CHK_FAIL_START + wcscat (wbuf, L"AB"); + CHK_FAIL_END + + wmemcpy (wbuf, wstr1 + 3, l0 + 8); + CHK_FAIL_START + wcsncat (wbuf, L"ZYXWV", l0 + 3); + CHK_FAIL_END + + CHK_FAIL_START + wmemcpy (wa.buf1 + 1, L"abcdefghij", l0 + 10); + CHK_FAIL_END + + CHK_FAIL_START + wmemmove (wa.buf1 + 2, wa.buf1 + 1, l0 + 9); + CHK_FAIL_END + + CHK_FAIL_START + wp = wmempcpy (wa.buf1 + 6, L"abcde", l0 + 5); + CHK_FAIL_END + + CHK_FAIL_START + wmemset (wa.buf1 + 9, L'j', l0 + 2); + CHK_FAIL_END + +#if __USE_FORTIFY_LEVEL >= 2 +# define O 0 +#else +# define O 1 +#endif + + CHK_FAIL_START + wcscpy (wa.buf1 + (O + 4), wstr1 + 5); + CHK_FAIL_END + + CHK_FAIL_START + wp = wcpcpy (wa.buf1 + (O + 8), wstr2); + CHK_FAIL_END + + CHK_FAIL_START + wcsncpy (wa.buf1 + (O + 6), L"X", l0 + 4); + CHK_FAIL_END + + wmemcpy (wa.buf1, wstr1 + (3 - O), l0 + 8 + O); + CHK_FAIL_START + wcscat (wa.buf1, L"AB"); + CHK_FAIL_END + + wmemcpy (wa.buf1, wstr1 + (4 - O), l0 + 7 + O); + CHK_FAIL_START + wcsncat (wa.buf1, L"ZYXWV", l0 + 3); + CHK_FAIL_END +#endif + + /* Now checks for %n protection. */ /* Constant literals passed directly are always ok @@ -455,6 +696,121 @@ do_test (void) CHK_FAIL_END #endif + rewind (stdin); + + if (fgets (buf, sizeof (buf), stdin) != buf + || memcmp (buf, "abcdefgh\n", 10)) + FAIL (); + if (fgets (buf, sizeof (buf), stdin) != buf || memcmp (buf, "ABCDEFGHI", 10)) + FAIL (); + + rewind (stdin); + + if (fgets (buf, l0 + sizeof (buf), stdin) != buf + || memcmp (buf, "abcdefgh\n", 10)) + FAIL (); + +#if __USE_FORTIFY_LEVEL >= 1 + CHK_FAIL_START + if (fgets (buf, sizeof (buf) + 1, stdin) != buf) + FAIL (); + CHK_FAIL_END + + CHK_FAIL_START + if (fgets (buf, l0 + sizeof (buf) + 1, stdin) != buf) + FAIL (); + CHK_FAIL_END +#endif + + rewind (stdin); + + if (fgets_unlocked (buf, sizeof (buf), stdin) != buf + || memcmp (buf, "abcdefgh\n", 10)) + FAIL (); + if (fgets_unlocked (buf, sizeof (buf), stdin) != buf + || memcmp (buf, "ABCDEFGHI", 10)) + FAIL (); + + rewind (stdin); + + if (fgets_unlocked (buf, l0 + sizeof (buf), stdin) != buf + || memcmp (buf, "abcdefgh\n", 10)) + FAIL (); + +#if __USE_FORTIFY_LEVEL >= 1 + CHK_FAIL_START + if (fgets_unlocked (buf, sizeof (buf) + 1, stdin) != buf) + FAIL (); + CHK_FAIL_END + + CHK_FAIL_START + if (fgets_unlocked (buf, l0 + sizeof (buf) + 1, stdin) != buf) + FAIL (); + CHK_FAIL_END +#endif + + lseek (fileno (stdin), 0, SEEK_SET); + + if (read (fileno (stdin), buf, sizeof (buf) - 1) != sizeof (buf) - 1 + || memcmp (buf, "abcdefgh\n", 9)) + FAIL (); + if (read (fileno (stdin), buf, sizeof (buf) - 1) != sizeof (buf) - 1 + || memcmp (buf, "ABCDEFGHI", 9)) + FAIL (); + + lseek (fileno (stdin), 0, SEEK_SET); + + if (read (fileno (stdin), buf, l0 + sizeof (buf) - 1) != sizeof (buf) - 1 + || memcmp (buf, "abcdefgh\n", 9)) + FAIL (); + +#if __USE_FORTIFY_LEVEL >= 1 + CHK_FAIL_START + if (read (fileno (stdin), buf, sizeof (buf) + 1) != sizeof (buf) + 1) + FAIL (); + CHK_FAIL_END +#endif + + if (pread (fileno (stdin), buf, sizeof (buf) - 1, sizeof (buf) - 2) + != sizeof (buf) - 1 + || memcmp (buf, "\nABCDEFGH", 9)) + FAIL (); + if (pread (fileno (stdin), buf, sizeof (buf) - 1, 0) != sizeof (buf) - 1 + || memcmp (buf, "abcdefgh\n", 9)) + FAIL (); + if (pread (fileno (stdin), buf, l0 + sizeof (buf) - 1, sizeof (buf) - 3) + != sizeof (buf) - 1 + || memcmp (buf, "h\nABCDEFG", 9)) + FAIL (); + +#if __USE_FORTIFY_LEVEL >= 1 + CHK_FAIL_START + if (pread (fileno (stdin), buf, sizeof (buf) + 1, 2 * sizeof (buf)) + != sizeof (buf) + 1) + FAIL (); + CHK_FAIL_END +#endif + + if (pread64 (fileno (stdin), buf, sizeof (buf) - 1, sizeof (buf) - 2) + != sizeof (buf) - 1 + || memcmp (buf, "\nABCDEFGH", 9)) + FAIL (); + if (pread64 (fileno (stdin), buf, sizeof (buf) - 1, 0) != sizeof (buf) - 1 + || memcmp (buf, "abcdefgh\n", 9)) + FAIL (); + if (pread64 (fileno (stdin), buf, l0 + sizeof (buf) - 1, sizeof (buf) - 3) + != sizeof (buf) - 1 + || memcmp (buf, "h\nABCDEFG", 9)) + FAIL (); + +#if __USE_FORTIFY_LEVEL >= 1 + CHK_FAIL_START + if (pread64 (fileno (stdin), buf, sizeof (buf) + 1, 2 * sizeof (buf)) + != sizeof (buf) + 1) + FAIL (); + CHK_FAIL_END +#endif + if (freopen (temp_filename, "r", stdin) == NULL) { puts ("could not open temporary file"); @@ -491,5 +847,474 @@ do_test (void) snprintf (buf, sizeof (buf), "%3$d\n", 1, 2, 3, 4); CHK_FAIL2_END + int sp[2]; + if (socketpair (PF_UNIX, SOCK_STREAM, 0, sp)) + FAIL (); + else + { + const char *sendstr = "abcdefgh\nABCDEFGH\n0123456789\n"; + if (send (sp[0], sendstr, strlen (sendstr), 0) != strlen (sendstr)) + FAIL (); + + char recvbuf[12]; + if (recv (sp[1], recvbuf, sizeof recvbuf, MSG_PEEK) + != sizeof recvbuf + || memcmp (recvbuf, sendstr, sizeof recvbuf) != 0) + FAIL (); + + if (recv (sp[1], recvbuf + 6, l0 + sizeof recvbuf - 7, MSG_PEEK) + != sizeof recvbuf - 7 + || memcmp (recvbuf + 6, sendstr, sizeof recvbuf - 7) != 0) + FAIL (); + +#if __USE_FORTIFY_LEVEL >= 1 + CHK_FAIL_START + if (recv (sp[1], recvbuf + 1, sizeof recvbuf, MSG_PEEK) + != sizeof recvbuf) + FAIL (); + CHK_FAIL_END + + CHK_FAIL_START + if (recv (sp[1], recvbuf + 4, l0 + sizeof recvbuf - 3, MSG_PEEK) + != sizeof recvbuf - 3) + FAIL (); + CHK_FAIL_END +#endif + + socklen_t sl; + struct sockaddr_un sa_un; + + sl = sizeof (sa_un); + if (recvfrom (sp[1], recvbuf, sizeof recvbuf, MSG_PEEK, &sa_un, &sl) + != sizeof recvbuf + || memcmp (recvbuf, sendstr, sizeof recvbuf) != 0) + FAIL (); + + sl = sizeof (sa_un); + if (recvfrom (sp[1], recvbuf + 6, l0 + sizeof recvbuf - 7, MSG_PEEK, + &sa_un, &sl) != sizeof recvbuf - 7 + || memcmp (recvbuf + 6, sendstr, sizeof recvbuf - 7) != 0) + FAIL (); + +#if __USE_FORTIFY_LEVEL >= 1 + CHK_FAIL_START + sl = sizeof (sa_un); + if (recvfrom (sp[1], recvbuf + 1, sizeof recvbuf, MSG_PEEK, &sa_un, &sl) + != sizeof recvbuf) + FAIL (); + CHK_FAIL_END + + CHK_FAIL_START + sl = sizeof (sa_un); + if (recvfrom (sp[1], recvbuf + 4, l0 + sizeof recvbuf - 3, MSG_PEEK, + &sa_un, &sl) != sizeof recvbuf - 3) + FAIL (); + CHK_FAIL_END +#endif + + close (sp[0]); + close (sp[1]); + } + + char fname[] = "/tmp/tst-chk1-dir-XXXXXX\0foo"; + char *enddir = strchr (fname, '\0'); + if (mkdtemp (fname) == NULL) + { + printf ("mkdtemp failed: %m\n"); + return 1; + } + *enddir = '/'; + if (symlink ("bar", fname) != 0) + FAIL (); + + char readlinkbuf[4]; + if (readlink (fname, readlinkbuf, 4) != 3 + || memcmp (readlinkbuf, "bar", 3) != 0) + FAIL (); + if (readlink (fname, readlinkbuf + 1, l0 + 3) != 3 + || memcmp (readlinkbuf, "bbar", 4) != 0) + FAIL (); + +#if __USE_FORTIFY_LEVEL >= 1 + CHK_FAIL_START + if (readlink (fname, readlinkbuf + 2, l0 + 3) != 3) + FAIL (); + CHK_FAIL_END + + CHK_FAIL_START + if (readlink (fname, readlinkbuf + 3, 4) != 3) + FAIL (); + CHK_FAIL_END +#endif + + int tmpfd = open ("/tmp", O_RDONLY | O_DIRECTORY); + if (tmpfd < 0) + FAIL (); + + if (readlinkat (tmpfd, fname + sizeof ("/tmp/") - 1, readlinkbuf, 4) != 3 + || memcmp (readlinkbuf, "bar", 3) != 0) + FAIL (); + if (readlinkat (tmpfd, fname + sizeof ("/tmp/") - 1, readlinkbuf + 1, + l0 + 3) != 3 + || memcmp (readlinkbuf, "bbar", 4) != 0) + FAIL (); + +#if __USE_FORTIFY_LEVEL >= 1 + CHK_FAIL_START + if (readlinkat (tmpfd, fname + sizeof ("/tmp/") - 1, readlinkbuf + 2, + l0 + 3) != 3) + FAIL (); + CHK_FAIL_END + + CHK_FAIL_START + if (readlinkat (tmpfd, fname + sizeof ("/tmp/") - 1, readlinkbuf + 3, + 4) != 3) + FAIL (); + CHK_FAIL_END +#endif + + close (tmpfd); + + char *cwd1 = getcwd (NULL, 0); + if (cwd1 == NULL) + FAIL (); + + char *cwd2 = getcwd (NULL, 250); + if (cwd2 == NULL) + FAIL (); + + if (cwd1 && cwd2) + { + if (strcmp (cwd1, cwd2) != 0) + FAIL (); + + *enddir = '\0'; + if (chdir (fname)) + FAIL (); + + char *cwd3 = getcwd (NULL, 0); + if (cwd3 == NULL) + FAIL (); + if (strcmp (fname, cwd3) != 0) + printf ("getcwd after chdir is '%s' != '%s'," + "get{c,}wd tests skipped\n", cwd3, fname); + else + { + char getcwdbuf[sizeof fname - 3]; + + char *cwd4 = getcwd (getcwdbuf, sizeof getcwdbuf); + if (cwd4 != getcwdbuf + || strcmp (getcwdbuf, fname) != 0) + FAIL (); + + cwd4 = getcwd (getcwdbuf + 1, l0 + sizeof getcwdbuf - 1); + if (cwd4 != getcwdbuf + 1 + || getcwdbuf[0] != fname[0] + || strcmp (getcwdbuf + 1, fname) != 0) + FAIL (); + +#if __USE_FORTIFY_LEVEL >= 1 + CHK_FAIL_START + if (getcwd (getcwdbuf + 2, l0 + sizeof getcwdbuf) + != getcwdbuf + 2) + FAIL (); + CHK_FAIL_END + + CHK_FAIL_START + if (getcwd (getcwdbuf + 2, sizeof getcwdbuf) + != getcwdbuf + 2) + FAIL (); + CHK_FAIL_END +#endif + + if (getwd (getcwdbuf) != getcwdbuf + || strcmp (getcwdbuf, fname) != 0) + FAIL (); + + if (getwd (getcwdbuf + 1) != getcwdbuf + 1 + || strcmp (getcwdbuf + 1, fname) != 0) + FAIL (); + +#if __USE_FORTIFY_LEVEL >= 1 + CHK_FAIL_START + if (getwd (getcwdbuf + 2) != getcwdbuf + 2) + FAIL (); + CHK_FAIL_END +#endif + } + + if (chdir (cwd1) != 0) + FAIL (); + free (cwd3); + } + + free (cwd1); + free (cwd2); + *enddir = '/'; + if (unlink (fname) != 0) + FAIL (); + + *enddir = '\0'; + if (rmdir (fname) != 0) + FAIL (); + + +#if PATH_MAX > 0 + char largebuf[PATH_MAX]; + char *realres = realpath (".", largebuf); + if (realres != largebuf) + FAIL (); + +# if __USE_FORTIFY_LEVEL >= 1 + CHK_FAIL_START + char realbuf[1]; + realres = realpath (".", realbuf); + if (realres != realbuf) + FAIL (); + CHK_FAIL_END +# endif +#endif + + if (setlocale (LC_ALL, "de_DE.UTF-8") != NULL) + { + assert (MB_CUR_MAX <= 10); + + /* First a simple test. */ + char enough[10]; + if (wctomb (enough, L'A') != 1) + FAIL (); + +#if __USE_FORTIFY_LEVEL >= 1 + /* We know the wchar_t encoding is ISO 10646. So pick a + character which has a multibyte representation which does not + fit. */ + CHK_FAIL_START + char smallbuf[2]; + if (wctomb (smallbuf, L'\x100') != 2) + FAIL (); + CHK_FAIL_END +#endif + + mbstate_t s; + memset (&s, '\0', sizeof (s)); + if (wcrtomb (enough, L'D', &s) != 1 || enough[0] != 'D') + FAIL (); + +#if __USE_FORTIFY_LEVEL >= 1 + /* We know the wchar_t encoding is ISO 10646. So pick a + character which has a multibyte representation which does not + fit. */ + CHK_FAIL_START + char smallbuf[2]; + if (wcrtomb (smallbuf, L'\x100', &s) != 2) + FAIL (); + CHK_FAIL_END +#endif + + wchar_t wenough[10]; + memset (&s, '\0', sizeof (s)); + const char *cp = "A"; + if (mbsrtowcs (wenough, &cp, 10, &s) != 1 + || wcscmp (wenough, L"A") != 0) + FAIL (); + + cp = "BC"; + if (mbsrtowcs (wenough, &cp, l0 + 10, &s) != 2 + || wcscmp (wenough, L"BC") != 0) + FAIL (); + +#if __USE_FORTIFY_LEVEL >= 1 + CHK_FAIL_START + wchar_t wsmallbuf[2]; + cp = "ABC"; + mbsrtowcs (wsmallbuf, &cp, 10, &s); + CHK_FAIL_END +#endif + + cp = "A"; + if (mbstowcs (wenough, cp, 10) != 1 + || wcscmp (wenough, L"A") != 0) + FAIL (); + + cp = "DEF"; + if (mbstowcs (wenough, cp, l0 + 10) != 3 + || wcscmp (wenough, L"DEF") != 0) + FAIL (); + +#if __USE_FORTIFY_LEVEL >= 1 + CHK_FAIL_START + wchar_t wsmallbuf[2]; + cp = "ABC"; + mbstowcs (wsmallbuf, cp, 10); + CHK_FAIL_END +#endif + + memset (&s, '\0', sizeof (s)); + cp = "ABC"; + wcscpy (wenough, L"DEF"); + if (mbsnrtowcs (wenough, &cp, 1, 10, &s) != 1 + || wcscmp (wenough, L"AEF") != 0) + FAIL (); + + cp = "IJ"; + if (mbsnrtowcs (wenough, &cp, 1, l0 + 10, &s) != 1 + || wcscmp (wenough, L"IEF") != 0) + FAIL (); + +#if __USE_FORTIFY_LEVEL >= 1 + CHK_FAIL_START + wchar_t wsmallbuf[2]; + cp = "ABC"; + mbsnrtowcs (wsmallbuf, &cp, 3, 10, &s); + CHK_FAIL_END +#endif + + memset (&s, '\0', sizeof (s)); + const wchar_t *wcp = L"A"; + if (wcsrtombs (enough, &wcp, 10, &s) != 1 + || strcmp (enough, "A") != 0) + FAIL (); + + wcp = L"BC"; + if (wcsrtombs (enough, &wcp, l0 + 10, &s) != 2 + || strcmp (enough, "BC") != 0) + FAIL (); + +#if __USE_FORTIFY_LEVEL >= 1 + CHK_FAIL_START + char smallbuf[2]; + wcp = L"ABC"; + wcsrtombs (smallbuf, &wcp, 10, &s); + CHK_FAIL_END +#endif + + memset (enough, 'Z', sizeof (enough)); + wcp = L"EF"; + if (wcstombs (enough, wcp, 10) != 2 + || strcmp (enough, "EF") != 0) + FAIL (); + + wcp = L"G"; + if (wcstombs (enough, wcp, l0 + 10) != 1 + || strcmp (enough, "G") != 0) + FAIL (); + +#if __USE_FORTIFY_LEVEL >= 1 + CHK_FAIL_START + char smallbuf[2]; + wcp = L"ABC"; + wcstombs (smallbuf, wcp, 10); + CHK_FAIL_END +#endif + + memset (&s, '\0', sizeof (s)); + wcp = L"AB"; + if (wcsnrtombs (enough, &wcp, 1, 10, &s) != 1 + || strcmp (enough, "A") != 0) + FAIL (); + + wcp = L"BCD"; + if (wcsnrtombs (enough, &wcp, 1, l0 + 10, &s) != 1 + || strcmp (enough, "B") != 0) + FAIL (); + +#if __USE_FORTIFY_LEVEL >= 1 + CHK_FAIL_START + char smallbuf[2]; + wcp = L"ABC"; + wcsnrtombs (smallbuf, &wcp, 3, 10, &s); + CHK_FAIL_END +#endif + } + else + { + puts ("cannot set locale"); + ret = 1; + } + + fd = posix_openpt (O_RDWR); + if (fd != -1) + { + char enough[1000]; + if (ptsname_r (fd, enough, sizeof (enough)) != 0) + FAIL (); + +#if __USE_FORTIFY_LEVEL >= 1 + CHK_FAIL_START + char smallbuf[2]; + if (ptsname_r (fd, smallbuf, sizeof (smallbuf) + 1) == 0) + FAIL (); + CHK_FAIL_END +#endif + close (fd); + } + +#if PATH_MAX > 0 + confstr (_CS_GNU_LIBC_VERSION, largebuf, sizeof (largebuf)); +# if __USE_FORTIFY_LEVEL >= 1 + CHK_FAIL_START + char smallbuf[1]; + confstr (_CS_GNU_LIBC_VERSION, smallbuf, sizeof (largebuf)); + CHK_FAIL_END +# endif +#endif + + gid_t grpslarge[5]; + int ngr = getgroups (5, grpslarge); + asm volatile ("" : : "r" (ngr)); +#if __USE_FORTIFY_LEVEL >= 1 + CHK_FAIL_START + char smallbuf[1]; + ngr = getgroups (5, (gid_t *) smallbuf); + asm volatile ("" : : "r" (ngr)); + CHK_FAIL_END +#endif + + fd = open (_PATH_TTY, O_RDONLY); + if (fd != -1) + { + char enough[1000]; + if (ttyname_r (fd, enough, sizeof (enough)) != 0) + FAIL (); + +#if __USE_FORTIFY_LEVEL >= 1 + CHK_FAIL_START + char smallbuf[2]; + if (ttyname_r (fd, smallbuf, sizeof (smallbuf) + 1) == 0) + FAIL (); + CHK_FAIL_END +#endif + close (fd); + } + + char hostnamelarge[1000]; + gethostname (hostnamelarge, sizeof (hostnamelarge)); +#if __USE_FORTIFY_LEVEL >= 1 + CHK_FAIL_START + char smallbuf[1]; + gethostname (smallbuf, sizeof (hostnamelarge)); + CHK_FAIL_END +#endif + + char loginlarge[1000]; + getlogin_r (loginlarge, sizeof (hostnamelarge)); +#if __USE_FORTIFY_LEVEL >= 1 + CHK_FAIL_START + char smallbuf[1]; + getlogin_r (smallbuf, sizeof (loginlarge)); + CHK_FAIL_END +#endif + + char domainnamelarge[1000]; + int res = getdomainname (domainnamelarge, sizeof (domainnamelarge)); + asm volatile ("" : : "r" (res)); +#if __USE_FORTIFY_LEVEL >= 1 + CHK_FAIL_START + char smallbuf[1]; + res = getdomainname (smallbuf, sizeof (domainnamelarge)); + asm volatile ("" : : "r" (res)); + CHK_FAIL_END +#endif + return ret; } diff --git a/debug/tst-lfschk1.c b/debug/tst-lfschk1.c new file mode 100644 index 0000000000..f3e6d47d5e --- /dev/null +++ b/debug/tst-lfschk1.c @@ -0,0 +1,2 @@ +#define _FILE_OFFSET_BITS 64 +#include "tst-chk1.c" diff --git a/debug/tst-lfschk2.c b/debug/tst-lfschk2.c new file mode 100644 index 0000000000..95d4db1d32 --- /dev/null +++ b/debug/tst-lfschk2.c @@ -0,0 +1,2 @@ +#define _FILE_OFFSET_BITS 64 +#include "tst-chk2.c" diff --git a/debug/tst-lfschk3.c b/debug/tst-lfschk3.c new file mode 100644 index 0000000000..50a1ae1258 --- /dev/null +++ b/debug/tst-lfschk3.c @@ -0,0 +1,2 @@ +#define _FILE_OFFSET_BITS 64 +#include "tst-chk3.c" diff --git a/debug/ttyname_r_chk.c b/debug/ttyname_r_chk.c new file mode 100644 index 0000000000..9b06d5a718 --- /dev/null +++ b/debug/ttyname_r_chk.c @@ -0,0 +1,29 @@ +/* Copyright (C) 2005 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 <unistd.h> + + +int +__ttyname_r_chk (int fd, char *buf, size_t buflen, size_t nreal) +{ + if (buflen > nreal) + __chk_fail (); + + return __ttyname_r (fd, buf, buflen); +} diff --git a/debug/vfprintf_chk.c b/debug/vfprintf_chk.c index c8e7c3bf3f..bd2796eaf7 100644 --- a/debug/vfprintf_chk.c +++ b/debug/vfprintf_chk.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991, 1995, 1996, 1997, 2001, 2004 +/* Copyright (C) 1991, 1995, 1996, 1997, 2001, 2004, 2005, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -24,7 +24,7 @@ /* Write formatted output to FP from the format string FORMAT. */ int -__vfprintf_chk (FILE *fp, int flag, const char *format, va_list ap) +___vfprintf_chk (FILE *fp, int flag, const char *format, va_list ap) { int done; @@ -40,3 +40,5 @@ __vfprintf_chk (FILE *fp, int flag, const char *format, va_list ap) return done; } +ldbl_hidden_def (___vfprintf_chk, __vfprintf_chk) +ldbl_strong_alias (___vfprintf_chk, __vfprintf_chk) diff --git a/debug/vfwprintf_chk.c b/debug/vfwprintf_chk.c new file mode 100644 index 0000000000..a2612d53e9 --- /dev/null +++ b/debug/vfwprintf_chk.c @@ -0,0 +1,43 @@ +/* Copyright (C) 1991, 1995, 1996, 1997, 2001, 2004, 2005, 2006 + 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 <wchar.h> +#include "../libio/libioP.h" + + +/* Write formatted output to FP from the format string FORMAT. */ +int +__vfwprintf_chk (FILE *fp, int flag, const wchar_t *format, va_list ap) +{ + int done; + + _IO_acquire_lock (fp); + if (flag > 0) + fp->_flags2 |= _IO_FLAGS2_FORTIFY; + + done = _IO_vfwprintf (fp, format, ap); + + if (flag > 0) + fp->_flags2 &= ~_IO_FLAGS2_FORTIFY; + _IO_release_lock (fp); + + return done; +} +libc_hidden_def (__vfwprintf_chk) diff --git a/debug/vprintf_chk.c b/debug/vprintf_chk.c index 1fd5bcd849..68a63ee7f9 100644 --- a/debug/vprintf_chk.c +++ b/debug/vprintf_chk.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991, 1995, 1996, 1997, 2001, 2004 +/* Copyright (C) 1991, 1995, 1996, 1997, 2001, 2004, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -24,7 +24,7 @@ /* Write formatted output to stdout from the format string FORMAT. */ int -__vprintf_chk (int flag, const char *format, va_list ap) +___vprintf_chk (int flag, const char *format, va_list ap) { int done; @@ -40,3 +40,4 @@ __vprintf_chk (int flag, const char *format, va_list ap) return done; } +ldbl_strong_alias (___vprintf_chk, __vprintf_chk) diff --git a/debug/vsnprintf_chk.c b/debug/vsnprintf_chk.c index a0fd4ebfdc..c46937ff6f 100644 --- a/debug/vsnprintf_chk.c +++ b/debug/vsnprintf_chk.c @@ -1,4 +1,5 @@ -/* Copyright (C) 1991, 1995, 1997, 1998, 2004 Free Software Foundation, Inc. +/* Copyright (C) 1991, 1995, 1997, 1998, 2004, 2006 + 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 @@ -27,8 +28,8 @@ extern const struct _IO_jump_t _IO_strn_jumps attribute_hidden; 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) +___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 @@ -67,4 +68,5 @@ __vsnprintf_chk (char *s, size_t maxlen, int flags, size_t slen, *sf.f._sbf._f._IO_write_ptr = '\0'; return ret; } -libc_hidden_def (__vsnprintf_chk) +ldbl_hidden_def (___vsnprintf_chk, __vsnprintf_chk) +ldbl_strong_alias (___vsnprintf_chk, __vsnprintf_chk) diff --git a/debug/vsprintf_chk.c b/debug/vsprintf_chk.c index f41c5fc64b..6538064dce 100644 --- a/debug/vsprintf_chk.c +++ b/debug/vsprintf_chk.c @@ -1,4 +1,5 @@ -/* Copyright (C) 1994, 1997, 1999-2003, 2004 Free Software Foundation, Inc. +/* Copyright (C) 1994, 1997, 1999-2003, 2004, 2006 + 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 @@ -61,8 +62,8 @@ static const struct _IO_jump_t _IO_str_chk_jumps = int -__vsprintf_chk (char *s, int flags, size_t slen, const char *format, - va_list args) +___vsprintf_chk (char *s, int flags, size_t slen, const char *format, + va_list args) { _IO_strfile f; int ret; @@ -88,4 +89,5 @@ __vsprintf_chk (char *s, int flags, size_t slen, const char *format, *f._sbf._f._IO_write_ptr = '\0'; return ret; } -libc_hidden_def (__vsprintf_chk) +ldbl_hidden_def (___vsprintf_chk, __vsprintf_chk) +ldbl_strong_alias (___vsprintf_chk, __vsprintf_chk) diff --git a/debug/vswprintf_chk.c b/debug/vswprintf_chk.c new file mode 100644 index 0000000000..f9a50c6e5d --- /dev/null +++ b/debug/vswprintf_chk.c @@ -0,0 +1,75 @@ +/* Copyright (C) 1991,1995,1997,1998,2004,2005 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 <wchar.h> +#include "../libio/libioP.h" +#include "../libio/strfile.h" + + +/* Write formatted output into S, according to the format + string FORMAT, writing no more than MAXLEN characters. */ +/* VARARGS5 */ +int +__vswprintf_chk (wchar_t *s, size_t maxlen, int flags, size_t slen, + const wchar_t *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_wstrnfile sf; + struct _IO_wide_data wd; + 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 (__builtin_expect (maxlen == 0, 0)) + /* Since we have to write at least the terminating L'\0' a buffer + length of zero always makes the function fail. */ + return -1; + + _IO_no_init (&sf.f._sbf._f, _IO_USER_LOCK, 0, &wd, &_IO_wstrn_jumps); + _IO_fwide (&sf.f._sbf._f, 1); + s[0] = L'\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_FORTIFY; + + _IO_wstr_init_static (&sf.f._sbf._f, s, maxlen - 1, s); + ret = _IO_vfwprintf ((_IO_FILE *) &sf.f._sbf, format, args); + + if (sf.f._sbf._f._wide_data->_IO_buf_base == sf.overflow_buf) + /* ISO C99 requires swprintf/vswprintf to return an error if the + output does not fit int he provided buffer. */ + return -1; + + /* Terminate the string. */ + *sf.f._sbf._f._wide_data->_IO_write_ptr = '\0'; + + return ret; +} +libc_hidden_def (__vswprintf_chk) diff --git a/debug/vwprintf_chk.c b/debug/vwprintf_chk.c new file mode 100644 index 0000000000..3b959b2968 --- /dev/null +++ b/debug/vwprintf_chk.c @@ -0,0 +1,43 @@ +/* Copyright (C) 1991, 1995, 1996, 1997, 2001, 2004, 2005 + 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 <wchar.h> +#include "../libio/libioP.h" + + +/* Write formatted output to stdout from the format string FORMAT. */ +int +__vwprintf_chk (int flag, const wchar_t *format, va_list ap) +{ + int done; + + _IO_acquire_lock (stdout); + if (flag > 0) + stdout->_flags2 |= _IO_FLAGS2_FORTIFY; + + done = _IO_vfwprintf (stdout, format, ap); + + if (flag > 0) + stdout->_flags2 &= ~_IO_FLAGS2_FORTIFY; + _IO_release_lock (stdout); + + return done; +} diff --git a/debug/warning-nop.c b/debug/warning-nop.c new file mode 100644 index 0000000000..8f2f66e16a --- /dev/null +++ b/debug/warning-nop.c @@ -0,0 +1,53 @@ +/* Dummy nop functions to elicit link-time warnings. + Copyright (C) 2005 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 <sys/cdefs.h> + +static void +nop (void) +{ +} + +/* Don't insert any other #include's before this #undef! */ + +#undef __warndecl +#define __warndecl(name, msg) \ + extern void name (void) __attribute__ ((alias ("nop"))) attribute_hidden; \ + link_warning (name, msg) + +#undef __USE_FORTIFY_LEVEL +#define __USE_FORTIFY_LEVEL 99 + +/* Following here we need an #include for each public header file + that uses __warndecl. */ + +/* Define away to avoid warnings with compilers that do not have these + builtins. */ +#define __builtin___memcpy_chk(dest, src, len, bos) NULL +#define __builtin___memmove_chk(dest, src, len, bos) NULL +#define __builtin___mempcpy_chk(dest, src, len, bos) NULL +#define __builtin___memset_chk(dest, ch, len, bos) NULL +#define __builtin___stpcpy_chk(dest, src, bos) NULL +#define __builtin___strcat_chk(dest, src, bos) NULL +#define __builtin___strcpy_chk(dest, src, bos) NULL +#define __builtin___strncat_chk(dest, src, len, bos) NULL +#define __builtin___strncpy_chk(dest, src, len, bos) NULL +#define __builtin_object_size(bos, level) 0 + +#include <string.h> diff --git a/debug/wcpcpy_chk.c b/debug/wcpcpy_chk.c new file mode 100644 index 0000000000..c48ec68ccc --- /dev/null +++ b/debug/wcpcpy_chk.c @@ -0,0 +1,45 @@ +/* Copyright (C) 1996, 1997, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1996. + + 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 <wchar.h> + +#define __need_ptrdiff_t +#include <stddef.h> + + +/* Copy SRC to DEST, returning the address of the terminating L'\0' in + DEST. Check for overflows. */ +wchar_t * +__wcpcpy_chk (wchar_t *dest, const wchar_t *src, size_t destlen) +{ + wchar_t *wcp = (wchar_t *) dest - 1; + wint_t c; + const ptrdiff_t off = src - dest + 1; + + do + { + if (__builtin_expect (destlen-- == 0, 0)) + __chk_fail (); + c = wcp[off]; + *++wcp = c; + } + while (c != L'\0'); + + return wcp; +} diff --git a/debug/wcpncpy_chk.c b/debug/wcpncpy_chk.c new file mode 100644 index 0000000000..ea1340191a --- /dev/null +++ b/debug/wcpncpy_chk.c @@ -0,0 +1,33 @@ +/* Copyright (C) 1995, 1996, 1997, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995. + + 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 <wchar.h> + + +/* Copy no more than N wide-characters of SRC to DEST. */ +wchar_t * +__wcpncpy_chk (wchar_t *dest, const wchar_t *src, size_t n, size_t destlen) +{ + if (__builtin_expect (destlen < n, 0)) + __chk_fail (); + + /* This function is not often enough used to justify not using a + tail call. */ + return __wcpncpy (dest, src, n); +} diff --git a/debug/wcrtomb_chk.c b/debug/wcrtomb_chk.c new file mode 100644 index 0000000000..228430f373 --- /dev/null +++ b/debug/wcrtomb_chk.c @@ -0,0 +1,35 @@ +/* Copyright (C) 2005 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 <langinfo.h> +#include <locale.h> +#include <stdlib.h> +#include <wchar.h> +#include <locale/localeinfo.h> + + +size_t +__wcrtomb_chk (char *s, wchar_t wchar, mbstate_t *ps, size_t buflen) +{ + /* We do not have to implement the full wctomb semantics since we + know that S cannot be NULL when we come here. */ + if (buflen < MB_CUR_MAX) + __chk_fail (); + + return __wcrtomb (s, wchar, ps); +} diff --git a/debug/wcscat_chk.c b/debug/wcscat_chk.c new file mode 100644 index 0000000000..eef04519fd --- /dev/null +++ b/debug/wcscat_chk.c @@ -0,0 +1,55 @@ +/* Copyright (C) 1995, 1996, 1997, 2001, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995. + + 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 <wchar.h> + + +/* Append SRC on the end of DEST. Check for overflows. */ +wchar_t * +__wcscat_chk (wchar_t *dest, const wchar_t *src, size_t destlen) +{ + register wchar_t *s1 = dest; + register const wchar_t *s2 = src; + wchar_t c; + + /* Find the end of the string. */ + do + { + if (__builtin_expect (destlen-- == 0, 0)) + __chk_fail (); + c = *s1++; + } + while (c != L'\0'); + + /* Make S1 point before the next character, so we can increment + it while memory is read (wins on pipelined cpus). */ + s1 -= 2; + ++destlen; + + do + { + if (__builtin_expect (destlen-- == 0, 0)) + __chk_fail (); + c = *s2++; + *++s1 = c; + } + while (c != L'\0'); + + return dest; +} diff --git a/debug/wcscpy_chk.c b/debug/wcscpy_chk.c new file mode 100644 index 0000000000..93b78cd01c --- /dev/null +++ b/debug/wcscpy_chk.c @@ -0,0 +1,61 @@ +/* Copyright (C) 1995, 1996, 1997, 2003, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995. + + 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 <wchar.h> + + +/* Copy SRC to DEST. */ +wchar_t * +__wcscpy_chk (wchar_t *dest, const wchar_t *src, size_t n) +{ + wint_t c; + wchar_t *wcp; + + if (__alignof__ (wchar_t) >= sizeof (wchar_t)) + { + const ptrdiff_t off = dest - src - 1; + + wcp = (wchar_t *) src; + + do + { + if (__builtin_expect (n-- == 0, 0)) + __chk_fail (); + c = *wcp++; + wcp[off] = c; + } + while (c != L'\0'); + } + else + { + wcp = dest; + + do + { + if (__builtin_expect (n-- == 0, 0)) + __chk_fail (); + c = *src++; + *wcp++ = c; + } + while (c != L'\0'); + } + + return dest; +} diff --git a/debug/wcsncat_chk.c b/debug/wcsncat_chk.c new file mode 100644 index 0000000000..b28773ff27 --- /dev/null +++ b/debug/wcsncat_chk.c @@ -0,0 +1,96 @@ +/* Copyright (C) 1995, 1996, 1997, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995. + + 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 <wchar.h> + + +/* Append no more than N wide-character of SRC onto DEST. */ +wchar_t * +__wcsncat_chk (wchar_t *dest, const wchar_t *src, size_t n, size_t destlen) +{ + wchar_t c; + wchar_t * const s = dest; + + /* Find the end of DEST. */ + do + { + if (__builtin_expect (destlen-- == 0, 0)) + __chk_fail (); + c = *dest++; + } + while (c != L'\0'); + + /* Make DEST point before next character, so we can increment + it while memory is read (wins on pipelined cpus). */ + ++destlen; + dest -= 2; + + if (n >= 4) + { + size_t n4 = n >> 2; + do + { + if (__builtin_expect (destlen-- == 0, 0)) + __chk_fail (); + c = *src++; + *++dest = c; + if (c == L'\0') + return s; + if (__builtin_expect (destlen-- == 0, 0)) + __chk_fail (); + c = *src++; + *++dest = c; + if (c == L'\0') + return s; + if (__builtin_expect (destlen-- == 0, 0)) + __chk_fail (); + c = *src++; + *++dest = c; + if (c == L'\0') + return s; + if (__builtin_expect (destlen-- == 0, 0)) + __chk_fail (); + c = *src++; + *++dest = c; + if (c == L'\0') + return s; + } while (--n4 > 0); + n &= 3; + } + + while (n > 0) + { + if (__builtin_expect (destlen-- == 0, 0)) + __chk_fail (); + c = *src++; + *++dest = c; + if (c == L'\0') + return s; + n--; + } + + if (c != L'\0') + { + if (__builtin_expect (destlen-- == 0, 0)) + __chk_fail (); + *++dest = L'\0'; + } + + return s; +} diff --git a/debug/wcsncpy_chk.c b/debug/wcsncpy_chk.c new file mode 100644 index 0000000000..199e4b01ab --- /dev/null +++ b/debug/wcsncpy_chk.c @@ -0,0 +1,33 @@ +/* Copyright (C) 1995, 1996, 1997, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995. + + 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 <wchar.h> + + +/* Copy no more than N wide-characters of SRC to DEST. */ +wchar_t * +__wcsncpy_chk (wchar_t *dest, const wchar_t *src, size_t n, size_t destlen) +{ + if (__builtin_expect (destlen < n, 0)) + __chk_fail (); + + /* This function is not often enough used to justify not using a + tail call. */ + return __wcsncpy (dest, src, n); +} diff --git a/debug/wcsnrtombs_chk.c b/debug/wcsnrtombs_chk.c new file mode 100644 index 0000000000..67644bd557 --- /dev/null +++ b/debug/wcsnrtombs_chk.c @@ -0,0 +1,31 @@ +/* Copyright (C) 2005 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 <locale.h> +#include <wchar.h> + + +size_t +__wcsnrtombs_chk (char *dst, __const wchar_t **src, size_t nwc, size_t len, + mbstate_t *ps, size_t dstlen) +{ + if (__builtin_expect (dstlen < len, 0)) + __chk_fail (); + + return __wcsnrtombs (dst, src, nwc, len, ps); +} diff --git a/debug/wcsrtombs_chk.c b/debug/wcsrtombs_chk.c new file mode 100644 index 0000000000..9334267bae --- /dev/null +++ b/debug/wcsrtombs_chk.c @@ -0,0 +1,31 @@ +/* Copyright (C) 2005 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 <locale.h> +#include <wchar.h> + + +size_t +__wcsrtombs_chk (char *dst, __const wchar_t **src, size_t len, + mbstate_t *ps, size_t dstlen) +{ + if (__builtin_expect (dstlen < len, 0)) + __chk_fail (); + + return __wcsrtombs (dst, src, len, ps); +} diff --git a/debug/wcstombs_chk.c b/debug/wcstombs_chk.c new file mode 100644 index 0000000000..0da48f9803 --- /dev/null +++ b/debug/wcstombs_chk.c @@ -0,0 +1,36 @@ +/* Copyright (C) 2005 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 <locale.h> +#include <string.h> +#include <wchar.h> + + +size_t +__wcstombs_chk (char *dst, __const wchar_t *src, size_t len, size_t dstlen) +{ + if (__builtin_expect (dstlen < len, 0)) + __chk_fail (); + + mbstate_t state; + + memset (&state, '\0', sizeof state); + + /* Return how many we wrote (or maybe an error). */ + return __wcsrtombs (dst, &src, len, &state); +} diff --git a/debug/wctomb_chk.c b/debug/wctomb_chk.c new file mode 100644 index 0000000000..d0366346b8 --- /dev/null +++ b/debug/wctomb_chk.c @@ -0,0 +1,36 @@ +/* Copyright (C) 2005 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 <locale.h> +#include <stdlib.h> +#include <wcsmbs/wcsmbsload.h> + + +extern mbstate_t __no_r_state attribute_hidden; /* Defined in mbtowc.c. */ + + +int +__wctomb_chk (char *s, wchar_t wchar, size_t buflen) +{ + /* We do not have to implement the full wctomb semantics since we + know that S cannot be NULL when we come here. */ + if (buflen < MB_CUR_MAX) + __chk_fail (); + + return __wcrtomb (s, wchar, &__no_r_state); +} diff --git a/debug/wmemcpy_chk.c b/debug/wmemcpy_chk.c new file mode 100644 index 0000000000..eeee927e91 --- /dev/null +++ b/debug/wmemcpy_chk.c @@ -0,0 +1,30 @@ +/* Copyright (C) 1996, 1997, 1999, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@gnu.org>, 1996. + + 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 <wchar.h> +#include <string.h> + + +wchar_t * +__wmemcpy_chk (wchar_t *s1, const wchar_t *s2, size_t n, size_t ns1) +{ + if (__builtin_expect (ns1 < n, 0)) + __chk_fail (); + return (wchar_t *) memcpy ((char *) s1, (char *) s2, n * sizeof (wchar_t)); +} diff --git a/debug/wmemmove_chk.c b/debug/wmemmove_chk.c new file mode 100644 index 0000000000..da0446eb28 --- /dev/null +++ b/debug/wmemmove_chk.c @@ -0,0 +1,30 @@ +/* Copyright (C) 1996, 1997, 1999, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper, <drepper@gnu.ai.mit.edu> + + 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 <wchar.h> +#include <string.h> + + +wchar_t * +__wmemmove_chk (wchar_t *s1, const wchar_t *s2, size_t n, size_t ns1) +{ + if (__builtin_expect (ns1 < n, 0)) + __chk_fail (); + return (wchar_t *) memmove ((char *) s1, (char *) s2, n * sizeof (wchar_t)); +} diff --git a/debug/wmempcpy_chk.c b/debug/wmempcpy_chk.c new file mode 100644 index 0000000000..52c629a354 --- /dev/null +++ b/debug/wmempcpy_chk.c @@ -0,0 +1,31 @@ +/* Copyright (C) 1999, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@gnu.org>, 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. */ + +#include <wchar.h> +#include <string.h> + + +wchar_t * +__wmempcpy_chk (wchar_t *s1, const wchar_t *s2, size_t n, size_t ns1) +{ + if (__builtin_expect (ns1 < n, 0)) + __chk_fail (); + return (wchar_t *) __mempcpy ((char *) s1, (char *) s2, + n * sizeof (wchar_t)); +} diff --git a/debug/wmemset_chk.c b/debug/wmemset_chk.c new file mode 100644 index 0000000000..5ed88e83a2 --- /dev/null +++ b/debug/wmemset_chk.c @@ -0,0 +1,30 @@ +/* Copyright (C) 1996,97,99,2002,2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@gnu.org>, 1996. + + 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 <wchar.h> + + +wchar_t * +__wmemset_chk (wchar_t *s, wchar_t c, size_t n, size_t dstlen) +{ + if (__builtin_expect (dstlen < n, 0)) + __chk_fail (); + + return wmemset (s, c, n); +} diff --git a/debug/wprintf_chk.c b/debug/wprintf_chk.c new file mode 100644 index 0000000000..e0a82617ad --- /dev/null +++ b/debug/wprintf_chk.c @@ -0,0 +1,46 @@ +/* Copyright (C) 1991, 1995, 1996, 1997, 2001, 2004, 2005 + 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 <wchar.h> +#include "../libio/libioP.h" + + +/* Write formatted output to stdout from the format string FORMAT. */ +int +__wprintf_chk (int flag, const wchar_t *format, ...) +{ + va_list ap; + int done; + + _IO_acquire_lock (stdout); + if (flag > 0) + stdout->_flags2 |= _IO_FLAGS2_FORTIFY; + + va_start (ap, format); + done = _IO_vfwprintf (stdout, format, ap); + va_end (ap); + + if (flag > 0) + stdout->_flags2 &= ~_IO_FLAGS2_FORTIFY; + _IO_release_lock (stdout); + + return done; +} diff --git a/debug/xtrace.sh b/debug/xtrace.sh index 4ce8888490..c913c76d21 100755 --- a/debug/xtrace.sh +++ b/debug/xtrace.sh @@ -1,5 +1,5 @@ #! @BASH@ -# Copyright (C) 1999, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. +# Copyright (C) 1999, 2001-2006, 2007 Free Software Foundation, Inc. # This file is part of the GNU C Library. # Contributed by Ulrich Drepper <drepper@gnu.org>, 1999. @@ -18,8 +18,8 @@ # Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA # 02111-1307 USA. -pcprofileso=@SLIBDIR@/libpcprofile.so -pcprofiledump=@BINDIR@/pcprofiledump +pcprofileso='@SLIBDIR@/libpcprofile.so' +pcprofiledump='@BINDIR@/pcprofiledump' TEXTDOMAIN=libc # Print usage message. @@ -64,7 +64,7 @@ do_version() { printf $"Copyright (C) %s Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -" "2004" +" "2006" printf $"Written by %s. " "Ulrich Drepper" exit 0 @@ -107,7 +107,7 @@ while test $# -gt 0; do --d=* | --da=* | --dat=* | --data=*) data=${1##*=} ;; - -? | --h | --he | --hel | --help) + -\? | --h | --he | --hel | --help) do_help ;; -V | --v | --ve | --ver | --vers | --versi | --versio | --version) @@ -161,32 +161,32 @@ if test -n "$data"; then while read fct; do read file if test "$fct" != '??' -a "$file" != '??:0'; then - format_line $fct $file + format_line "$fct" "$file" fi done else - fifo=$(mktemp -u ${TMPDIR:-/tmp}/xtrace.XXXXXX) + fifo=$(mktemp -ut xtrace.XXXXXX) || exit + trap 'rm -f "$fifo"; exit 1' HUP INT QUIT TERM PIPE mkfifo -m 0600 $fifo || exit 1 - trap 'rm $fifo; exit 1' SIGINT SIGTERM SIGPIPE # Now start the program and let it write to the FIFO. $TERMINAL_PROG -T "xtrace - $program $*" -e /bin/sh -c "LD_PRELOAD=$pcprofileso PCPROFILE_OUTPUT=$fifo $program $*; read < $fifo" & termpid=$! - $pcprofiledump -u $fifo | + $pcprofiledump -u "$fifo" | while read line; do - echo $line | + echo "$line" | sed 's/this = \([^,]*\).*/\1/' | - addr2line -fC -e $program + addr2line -fC -e "$program" done | while read fct; do read file if test "$fct" != '??' -a "$file" != '??:0'; then - format_line $fct $file + format_line "$fct" "$file" fi done read -p "Press return here to close $TERMINAL_PROG($program)." - echo > $fifo - rm $fifo + echo > "$fifo" + rm "$fifo" fi exit 0 |