diff options
Diffstat (limited to 'libc')
-rw-r--r-- | libc/Android.mk | 1 | ||||
-rw-r--r-- | libc/bionic/brk.cpp | 46 | ||||
-rw-r--r-- | libc/bionic/sbrk.cpp | 55 |
3 files changed, 41 insertions, 61 deletions
diff --git a/libc/Android.mk b/libc/Android.mk index 984187f1a..9222cbd3f 100644 --- a/libc/Android.mk +++ b/libc/Android.mk @@ -228,7 +228,6 @@ libc_bionic_src_files := \ bionic/pthread_setschedparam.cpp \ bionic/pthread_sigmask.cpp \ bionic/raise.cpp \ - bionic/sbrk.cpp \ bionic/scandir.cpp \ bionic/sched_getaffinity.cpp \ bionic/__set_errno.cpp \ diff --git a/libc/bionic/brk.cpp b/libc/bionic/brk.cpp index 633b914c4..050f36dbe 100644 --- a/libc/bionic/brk.cpp +++ b/libc/bionic/brk.cpp @@ -26,16 +26,52 @@ * SUCH DAMAGE. */ +#define __STDINT_LIMITS + +#include <errno.h> +#include <stdint.h> #include <unistd.h> -/* Shared with sbrk.c. */ -extern "C" void* __bionic_brk; // TODO: should be __LIBC_HIDDEN__ but accidentally exported by NDK :-( +#if __LP64__ +static void* __bionic_brk; +#else +void* __bionic_brk; // Accidentally exported by the NDK. +#endif int brk(void* end_data) { - void* new_brk = __brk(end_data); - if (new_brk != end_data) { + __bionic_brk = __brk(end_data); + if (__bionic_brk < end_data) { + errno = ENOMEM; return -1; } - __bionic_brk = new_brk; return 0; } + +void* sbrk(ptrdiff_t increment) { + // Initialize __bionic_brk if necessary. + if (__bionic_brk == NULL) { + __bionic_brk = __brk(NULL); + } + + // Don't ask the kernel if we already know the answer. + if (increment == 0) { + return __bionic_brk; + } + + // Avoid overflow. + intptr_t old_brk = reinterpret_cast<intptr_t>(__bionic_brk); + if ((increment > 0 && INTPTR_MAX - increment > old_brk) || + (increment < 0 && (increment == PTRDIFF_MIN || old_brk < -increment))) { + errno = ENOMEM; + return reinterpret_cast<void*>(-1); + } + + void* desired_brk = reinterpret_cast<void*>(old_brk + increment); + __bionic_brk = __brk(desired_brk); + + if (__bionic_brk < desired_brk) { + errno = ENOMEM; + return reinterpret_cast<void*>(-1); + } + return reinterpret_cast<void*>(old_brk); +} diff --git a/libc/bionic/sbrk.cpp b/libc/bionic/sbrk.cpp deleted file mode 100644 index 6c9b534c3..000000000 --- a/libc/bionic/sbrk.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include <unistd.h> -#include <errno.h> - -/* Shared with brk.c. */ -extern "C" { - void* __bionic_brk; // TODO: should be __LIBC_HIDDEN__ but accidentally exported by NDK :-( -} - -void* sbrk(ptrdiff_t increment) { - if (__bionic_brk == NULL) { - __bionic_brk = __brk(NULL); - } - - void* original_brk = __bionic_brk; - void* desired_brk = (void*) ((uintptr_t) original_brk + increment); - - void* new_brk = __brk(desired_brk); - if (new_brk == (void*) -1) { - return new_brk; - } else if (new_brk < desired_brk) { - errno = ENOMEM; - return (void*) -1; - } - - __bionic_brk = new_brk; - return original_brk; -} |