diff options
| author | Mattias Andrée <maandree@member.fsf.org> | 2015-12-20 17:35:04 +0100 | 
|---|---|---|
| committer | Mattias Andrée <maandree@member.fsf.org> | 2015-12-20 17:35:04 +0100 | 
| commit | 0d4b2f2670b9d90c694a8d5340611481066ea5e6 (patch) | |
| tree | 347089cafd293e525f910c775bcb6af9cfa6c241 /src/alloca | |
| parent | m (diff) | |
| download | slibc-0d4b2f2670b9d90c694a8d5340611481066ea5e6.tar.gz slibc-0d4b2f2670b9d90c694a8d5340611481066ea5e6.tar.bz2 slibc-0d4b2f2670b9d90c694a8d5340611481066ea5e6.tar.xz | |
add needstack
Signed-off-by: Mattias Andrée <maandree@member.fsf.org>
Diffstat (limited to '')
| -rw-r--r-- | src/alloca/needstack.c | 154 | 
1 files changed, 154 insertions, 0 deletions
| diff --git a/src/alloca/needstack.c b/src/alloca/needstack.c new file mode 100644 index 0000000..b75eb02 --- /dev/null +++ b/src/alloca/needstack.c @@ -0,0 +1,154 @@ +/** + * slibc — Yet another C library + * Copyright © 2015  Mattias Andrée (maandree@member.fsf.org) + *  + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + *  + * This program 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 General Public License for more details. + *  + * You should have received a copy of the GNU General Public License + * along with this program.  If not, see <http://www.gnu.org/licenses/>. + */ +#include <slibc/internals.h> +#include <alloca.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <signal.h> + + + +/** + * Unless the stack can grow with `n` bytes + * without overflowing, the program shall + * either be killed by the kernel (SIGSEGV) + * or this function shall indicate that the + * stack cannot be grown. + *  + * @param   n  The number of bytes the stack must be able to grow. + * @return     0 if the stack can grow, 1 otherwise. + */ +int stack_will_overflow(intptr_t n) +{ +  void* prev_brk; +   +  /* TODO This function shall block calls to brk and sbrk. */ +   +  prev_brk = sbrk(n); +  if (prev_brk == (void*)-1) +    return 1; +  if (brk(prev_brk)) +    return 1; /* Should not happen. */ +   +  { +    /* TODO This function shall block calls to signal.h functions. */ +     +    sigset_t old_mask; +    sigset_t new_mask; +    void* old_sigsegv_handler; +     +    old_sigsegv_handler = signal(SIGSEGV, SIG_DFL); +    if (old_sigsegv_handler == SIG_ERR) +      return 1; +     +    if (sigprocmask(SIG_UNBLOCK, &new_mask, &old_mask)) +      return 1; +     +    (void) alloca((size_t)n); +     +    if (sigprocmask(SIG_SETMASK, &old_mask, NULL)) +      return 1; +     +    if (signal(SIGSEGV, Sold_sigsegv_handler) == SIG_ERR) +      return 1; +  } +   +  return 0; +} + + +/** + * Check for execution stack overflow. If the stack of + * overflow, or will overflow, the program shall abort. + *  + * It is possible that the process is killed by SIGSEGV + * instead of aborting. + *  + * This is a Plan 9 from Bell Labs extension. + *  + * @etymology  I (need) addition (stack) space. + *  + * @param  n  The number of bytes the stack will grow by. + *            0 can be used to check for a current stack + *            overflow. Must be non-negative. + *  + * @since  Always. + */ +void (needstack)(int n) +{ +  int tty; +   +  if (stack_will_overflow((intptr_t)n) == 0) +    return; +   +  tty = isatty(STDERR_FILENO); +  fprintf(stderr, +	  _("%(\033[00;01m%)%s%(\033[00m%): " +	    "%(\033[31m%)%s%(\033[00m%)" +	    "%(: %(\033[31m%)hinted stack growth: %i bytes%(\033[00m%)%)\n"), +	  tty, program_invocation_name, tty, +	  tty, (n ? _("imminent stack overflow detected") : _("stack overflow detected")), tty, +	  n != 0, tty, n, tty); +   +  fflush(NULL); /* Flush all streams. */ +  abort(); +} + + +/** + * This function is called if the `needstack` macro is called. + * It enhances the `needstack` function with detail on where + * the program failed. + *  + * You should not use this function directly. + *  + * @param  n     The number of bytes the stack will grow by. 0 can be used + *               to check for a current stack overflow. Must be non-negative. + * @param  file  The filename of the source cose whence the check was made. + * @param  line  The line in the source code whence the check was made. + * @param  func  The function in the source code whence the check was made, + *               `NULL` if unknown (C99 is required.) + */ +void __needstack(int n, const char* file, int line, const char* func) +{ +  int tty; +   +  if (stack_will_overflow((intptr_t)n) == 0) +    return; +   +  tty = isatty(STDERR_FILENO); +  fprintf(stderr, +	  _("%(\033[00;01m%)%s%(\033[00m%): " +	    "%(\033[31m%)%s%(\033[00m%) " +	    "at line %(\033[33m%)%i%(\033[00m%) " +	    "of file %(\033[35m%)%s%(\033[00m%)" +	    "%(, function %(\033[1;34m%)%s%(\033[00m%)%)" +	    "%(: %(\033[31m%)hinted stack growth: %i bytes%(\033[00m%)%)\n"), +	  tty, program_invocation_name, tty, +	  tty, (n ? _("imminent stack overflow detected") : _("stack overflow detected")), tty, +	  tty, line, tty, +	  tty, file, tty, +	  func != NULL, tty, func, tty, +	  n != 0, tty, n, tty); +   +  fflush(NULL); /* Flush all streams. */ +  abort(); +} + | 
