mirror of
https://github.com/GrapheneOS/hardened_malloc.git
synced 2025-04-19 22:10:19 +02:00
Compare commits
2 commits
a73585cc39
...
8d05ca8a4b
Author | SHA1 | Date | |
---|---|---|---|
|
8d05ca8a4b | ||
|
c4cefeaa54 |
21 changed files with 55 additions and 268 deletions
2
CREDITS
2
CREDITS
|
@ -23,7 +23,7 @@ h_malloc.c open-addressed hash table (regions_grow, regions_insert, regions_find
|
|||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
memcpy.c, memmove.c, memset.c, wmemset.c:
|
||||
memcpy.c, memmove.c, memset.c and their wide variants:
|
||||
Copyright © 2005-2020 Rich Felker, et al.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
|
|
6
Makefile
6
Makefile
|
@ -41,7 +41,7 @@ LDFLAGS := $(LDFLAGS) -Wl,-O1,--as-needed,-z,defs,-z,relro,-z,now,-z,nodlopen,-z
|
|||
|
||||
SOURCES := chacha.c h_malloc.c memory.c pages.c random.c util.c
|
||||
ifeq ($(CONFIG_BLOCK_OPS_CHECK_SIZE),true)
|
||||
SOURCES += memcpy.c memmove.c memset.c wmemset.c
|
||||
SOURCES += memcpy.c memmove.c memset.c wmemcpy.c wmemmove.c wmemset.c
|
||||
BOSC_EXTRAS := musl.h
|
||||
endif
|
||||
OBJECTS := $(SOURCES:.c=.o)
|
||||
|
@ -146,6 +146,10 @@ $(OUT)/memmove.o: memmove.c musl.h $(CONFIG_FILE) | $(OUT)
|
|||
$(COMPILE.c) -Wno-cast-align $(OUTPUT_OPTION) $<
|
||||
$(OUT)/memset.o: memset.c musl.h $(CONFIG_FILE) | $(OUT)
|
||||
$(COMPILE.c) -Wno-cast-align $(OUTPUT_OPTION) $<
|
||||
$(OUT)/wmemcpy.o: wmemcpy.c musl.h $(CONFIG_FILE) | $(OUT)
|
||||
$(COMPILE.c) $(OUTPUT_OPTION) $<
|
||||
$(OUT)/wmemmove.o: wmemmove.c musl.h $(CONFIG_FILE) | $(OUT)
|
||||
$(COMPILE.c) $(OUTPUT_OPTION) $<
|
||||
$(OUT)/wmemset.o: wmemset.c musl.h $(CONFIG_FILE) | $(OUT)
|
||||
$(COMPILE.c) $(OUTPUT_OPTION) $<
|
||||
|
||||
|
|
34
h_malloc.c
34
h_malloc.c
|
@ -1880,10 +1880,10 @@ EXPORT size_t h_malloc_object_size_fast(const void *p) {
|
|||
|
||||
#if CONFIG_BLOCK_OPS_CHECK_SIZE && !defined(HAS_ARM_MTE)
|
||||
EXPORT void *memcpy(void *restrict dst, const void *restrict src, size_t len) {
|
||||
if (unlikely(dst == src || len == 0)) {
|
||||
if(dst == src || len == 0) {
|
||||
return dst;
|
||||
}
|
||||
if (unlikely(dst < (src + len) && (dst + len) > src)) {
|
||||
if (unlikely(dst < src + len && dst + len > src)) {
|
||||
fatal_error("memcpy overlap");
|
||||
}
|
||||
if (unlikely(len > malloc_object_size(src))) {
|
||||
|
@ -1896,7 +1896,7 @@ EXPORT void *memcpy(void *restrict dst, const void *restrict src, size_t len) {
|
|||
}
|
||||
|
||||
EXPORT void *memmove(void *dst, const void *src, size_t len) {
|
||||
if (unlikely(dst == src || len == 0)) {
|
||||
if(dst == src || len == 0) {
|
||||
return dst;
|
||||
}
|
||||
if (unlikely(len > malloc_object_size(src))) {
|
||||
|
@ -1909,7 +1909,7 @@ EXPORT void *memmove(void *dst, const void *src, size_t len) {
|
|||
}
|
||||
|
||||
EXPORT void *memset(void *dst, int value, size_t len) {
|
||||
if (unlikely(len == 0)) {
|
||||
if(len == 0) {
|
||||
return dst;
|
||||
}
|
||||
if (unlikely(len > malloc_object_size(dst))) {
|
||||
|
@ -1919,46 +1919,44 @@ EXPORT void *memset(void *dst, int value, size_t len) {
|
|||
}
|
||||
|
||||
EXPORT wchar_t *wmemcpy(wchar_t *restrict dst, const wchar_t *restrict src, size_t len) {
|
||||
if (unlikely(dst == src || len == 0)) {
|
||||
if(dst == src || len == 0) {
|
||||
return dst;
|
||||
}
|
||||
if (unlikely(dst < (src + len) && (dst + len) > src)) {
|
||||
if (dst < src + len && dst + len > src) {
|
||||
fatal_error("wmemcpy overlap");
|
||||
}
|
||||
size_t lenAdj = len * sizeof(wchar_t);
|
||||
if (unlikely(lenAdj > malloc_object_size(src))) {
|
||||
if (len > malloc_object_size(src)) {
|
||||
fatal_error("wmemcpy read overflow");
|
||||
}
|
||||
if (unlikely(lenAdj > malloc_object_size(dst))) {
|
||||
if (len > malloc_object_size(dst)) {
|
||||
fatal_error("wmemcpy buffer overflow");
|
||||
}
|
||||
return (wchar_t *)musl_memcpy((char *)dst, (const char *)src, lenAdj);
|
||||
return musl_wmemcpy(dst, src, len);
|
||||
}
|
||||
|
||||
EXPORT wchar_t *wmemmove(wchar_t *dst, const wchar_t *src, size_t len) {
|
||||
if (unlikely(dst == src || len == 0)) {
|
||||
if(dst == src || len == 0) {
|
||||
return dst;
|
||||
}
|
||||
size_t lenAdj = len * sizeof(wchar_t);
|
||||
if (unlikely(lenAdj > malloc_object_size(src))) {
|
||||
if (len > malloc_object_size(src)) {
|
||||
fatal_error("wmemmove read overflow");
|
||||
}
|
||||
if (unlikely(lenAdj > malloc_object_size(dst))) {
|
||||
if (len > malloc_object_size(dst)) {
|
||||
fatal_error("wmemmove buffer overflow");
|
||||
}
|
||||
return (wchar_t *)musl_memmove((char *)dst, (const char *)src, lenAdj);
|
||||
return musl_wmemmove(dst, src, len);
|
||||
}
|
||||
|
||||
EXPORT wchar_t *wmemset(wchar_t *dst, wchar_t value, size_t len) {
|
||||
if (unlikely(len == 0)) {
|
||||
if(len == 0) {
|
||||
return dst;
|
||||
}
|
||||
if (unlikely((len * sizeof(wchar_t)) > malloc_object_size(dst))) {
|
||||
if (len > malloc_object_size(dst)) {
|
||||
fatal_error("wmemset buffer overflow");
|
||||
}
|
||||
return musl_wmemset(dst, value, len);
|
||||
}
|
||||
#endif /* CONFIG_BLOCK_OPS_CHECK_SIZE && !defined(HAS_ARM_MTE) */
|
||||
#endif
|
||||
|
||||
EXPORT int h_mallopt(UNUSED int param, UNUSED int value) {
|
||||
#ifdef __ANDROID__
|
||||
|
|
|
@ -20,7 +20,7 @@ void *musl_memmove(void *dest, const void *src, size_t n)
|
|||
const char *s = src;
|
||||
|
||||
if (d==s) return d;
|
||||
if ((uintptr_t)s-(uintptr_t)d-n <= -2*n) return musl_memcpy(d, s, n);
|
||||
if ((uintptr_t)s-(uintptr_t)d-n <= -2*n) return memcpy(d, s, n);
|
||||
|
||||
if (d<s) {
|
||||
#ifdef __GNUC__
|
||||
|
|
2
musl.h
2
musl.h
|
@ -5,4 +5,6 @@
|
|||
void *musl_memcpy(void *dst, const void *src, size_t len);
|
||||
void *musl_memmove(void *dst, const void *src, size_t len);
|
||||
void *musl_memset(void *dst, int value, size_t len);
|
||||
wchar_t *musl_wmemcpy(wchar_t *dst, const wchar_t *src, size_t len);
|
||||
wchar_t *musl_wmemmove(wchar_t *dst, const wchar_t *src, size_t len);
|
||||
wchar_t *musl_wmemset(wchar_t *dst, wchar_t value, size_t len);
|
||||
|
|
11
test/.gitignore
vendored
11
test/.gitignore
vendored
|
@ -52,15 +52,4 @@ memmove_valid_mismatched
|
|||
memset_buffer_overflow
|
||||
memset_valid_same
|
||||
memset_valid_mismatched
|
||||
wmemcpy_buffer_overflow
|
||||
wmemcpy_read_overflow
|
||||
wmemcpy_valid_same
|
||||
wmemcpy_valid_mismatched
|
||||
wmemmove_buffer_overflow
|
||||
wmemmove_read_overflow
|
||||
wmemmove_valid_same
|
||||
wmemmove_valid_mismatched
|
||||
wmemset_buffer_overflow
|
||||
wmemset_valid_same
|
||||
wmemset_valid_mismatched
|
||||
__pycache__/
|
||||
|
|
|
@ -78,18 +78,7 @@ EXECUTABLES := \
|
|||
memmove_valid_mismatched \
|
||||
memset_buffer_overflow \
|
||||
memset_valid_same \
|
||||
memset_valid_mismatched \
|
||||
wmemcpy_buffer_overflow \
|
||||
wmemcpy_read_overflow \
|
||||
wmemcpy_valid_same \
|
||||
wmemcpy_valid_mismatched \
|
||||
wmemmove_buffer_overflow \
|
||||
wmemmove_read_overflow \
|
||||
wmemmove_valid_same \
|
||||
wmemmove_valid_mismatched \
|
||||
wmemset_buffer_overflow \
|
||||
wmemset_valid_same \
|
||||
wmemset_valid_mismatched
|
||||
memset_valid_mismatched
|
||||
|
||||
all: $(EXECUTABLES)
|
||||
|
||||
|
|
|
@ -293,71 +293,6 @@ class TestSimpleMemoryCorruption(unittest.TestCase):
|
|||
# self.assertEqual(stderr.decode(
|
||||
# "utf-8"), "fatal allocator error: memset buffer overflow\n")
|
||||
|
||||
#def test_wmemcpy_buffer_overflow(self):
|
||||
# _stdout, stderr, returncode = self.run_test(
|
||||
# "wmemcpy_buffer_overflow")
|
||||
# self.assertEqual(returncode, -6)
|
||||
# self.assertEqual(stderr.decode(
|
||||
# "utf-8"), "fatal allocator error: wmemcpy buffer overflow\n")
|
||||
|
||||
#def test_wmemcpy_read_overflow(self):
|
||||
# _stdout, stderr, returncode = self.run_test(
|
||||
# "wmemcpy_read_overflow")
|
||||
# self.assertEqual(returncode, -6)
|
||||
# self.assertEqual(stderr.decode(
|
||||
# "utf-8"), "fatal allocator error: wmemcpy read overflow\n")
|
||||
|
||||
def test_wmemcpy_valid_same(self):
|
||||
_stdout, _stderr, returncode = self.run_test(
|
||||
"wmemcpy_valid_same")
|
||||
self.assertEqual(returncode, 0)
|
||||
|
||||
def test_wmemcpy_valid_mismatched(self):
|
||||
_stdout, _stderr, returncode = self.run_test(
|
||||
"wmemcpy_valid_mismatched")
|
||||
self.assertEqual(returncode, 0)
|
||||
|
||||
#def test_wmemmove_buffer_overflow(self):
|
||||
# _stdout, stderr, returncode = self.run_test(
|
||||
# "wmemmove_buffer_overflow")
|
||||
# self.assertEqual(returncode, -6)
|
||||
# self.assertEqual(stderr.decode(
|
||||
# "utf-8"), "fatal allocator error: wmemmove buffer overflow\n")
|
||||
|
||||
#def test_wmemmove_read_overflow(self):
|
||||
# _stdout, stderr, returncode = self.run_test(
|
||||
# "wmemmove_read_overflow")
|
||||
# self.assertEqual(returncode, -6)
|
||||
# self.assertEqual(stderr.decode(
|
||||
# "utf-8"), "fatal allocator error: wmemmove read overflow\n")
|
||||
|
||||
def test_wmemmove_valid_same(self):
|
||||
_stdout, _stderr, returncode = self.run_test(
|
||||
"wmemmove_valid_same")
|
||||
self.assertEqual(returncode, 0)
|
||||
|
||||
def test_wmemmove_valid_mismatched(self):
|
||||
_stdout, _stderr, returncode = self.run_test(
|
||||
"wmemmove_valid_mismatched")
|
||||
self.assertEqual(returncode, 0)
|
||||
|
||||
#def test_wmemset_buffer_overflow(self):
|
||||
# _stdout, stderr, returncode = self.run_test(
|
||||
# "wmemset_buffer_overflow")
|
||||
# self.assertEqual(returncode, -6)
|
||||
# self.assertEqual(stderr.decode(
|
||||
# "utf-8"), "fatal allocator error: wmemset buffer overflow\n")
|
||||
|
||||
def test_wmemset_valid_same(self):
|
||||
_stdout, _stderr, returncode = self.run_test(
|
||||
"wmemset_valid_same")
|
||||
self.assertEqual(returncode, 0)
|
||||
|
||||
def test_wmemset_valid_mismatched(self):
|
||||
_stdout, _stderr, returncode = self.run_test(
|
||||
"wmemset_valid_mismatched")
|
||||
self.assertEqual(returncode, 0)
|
||||
|
||||
def test_memset_valid_same(self):
|
||||
_stdout, _stderr, returncode = self.run_test(
|
||||
"memset_valid_same")
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
#include <stdlib.h>
|
||||
#include <wchar.h>
|
||||
|
||||
#include "test_util.h"
|
||||
|
||||
OPTNONE int main(void) {
|
||||
wchar_t *firstbuffer = malloc(16 * sizeof(wchar_t));
|
||||
wchar_t *secondbuffer = malloc(32 * sizeof(wchar_t));
|
||||
if (!firstbuffer && !secondbuffer) {
|
||||
return 1;
|
||||
}
|
||||
wmemset(secondbuffer, L'\U0001F642', 32);
|
||||
wmemcpy(firstbuffer, secondbuffer, 32);
|
||||
return 1;
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
#include <stdlib.h>
|
||||
#include <wchar.h>
|
||||
|
||||
#include "test_util.h"
|
||||
|
||||
OPTNONE int main(void) {
|
||||
wchar_t *firstbuffer = malloc(32 * sizeof(wchar_t));
|
||||
wchar_t *secondbuffer = malloc(16 * sizeof(wchar_t));
|
||||
if (!firstbuffer && !secondbuffer) {
|
||||
return 1;
|
||||
}
|
||||
wmemset(secondbuffer, L'\U0001F642', 16);
|
||||
wmemcpy(firstbuffer, secondbuffer, 32);
|
||||
return 1;
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
#include <stdlib.h>
|
||||
#include <wchar.h>
|
||||
|
||||
#include "test_util.h"
|
||||
|
||||
OPTNONE int main(void) {
|
||||
wchar_t *firstbuffer = malloc(32 * sizeof(wchar_t));
|
||||
wchar_t *secondbuffer = malloc(16 * sizeof(wchar_t));
|
||||
if (!firstbuffer && !secondbuffer) {
|
||||
return 1;
|
||||
}
|
||||
wmemset(secondbuffer, L'\U0001F642', 16);
|
||||
wmemcpy(firstbuffer, secondbuffer, 16);
|
||||
return 0;
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
#include <stdlib.h>
|
||||
#include <wchar.h>
|
||||
|
||||
#include "test_util.h"
|
||||
|
||||
OPTNONE int main(void) {
|
||||
wchar_t *firstbuffer = malloc(16 * sizeof(wchar_t));
|
||||
wchar_t *secondbuffer = malloc(16 * sizeof(wchar_t));
|
||||
if (!firstbuffer && !secondbuffer) {
|
||||
return 1;
|
||||
}
|
||||
wmemset(secondbuffer, L'\U0001F642', 16);
|
||||
wmemcpy(firstbuffer, secondbuffer, 16);
|
||||
return 0;
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
#include <stdlib.h>
|
||||
#include <wchar.h>
|
||||
|
||||
#include "test_util.h"
|
||||
|
||||
OPTNONE int main(void) {
|
||||
wchar_t *firstbuffer = malloc(16 * sizeof(wchar_t));
|
||||
wchar_t *secondbuffer = malloc(32 * sizeof(wchar_t));
|
||||
if (!firstbuffer && !secondbuffer) {
|
||||
return 1;
|
||||
}
|
||||
wmemset(secondbuffer, L'\U0001F642', 32);
|
||||
wmemmove(firstbuffer, secondbuffer, 32);
|
||||
return 1;
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
#include <stdlib.h>
|
||||
#include <wchar.h>
|
||||
|
||||
#include "test_util.h"
|
||||
|
||||
OPTNONE int main(void) {
|
||||
wchar_t *firstbuffer = malloc(32 * sizeof(wchar_t));
|
||||
wchar_t *secondbuffer = malloc(16 * sizeof(wchar_t));
|
||||
if (!firstbuffer && !secondbuffer) {
|
||||
return 1;
|
||||
}
|
||||
wmemset(secondbuffer, L'\U0001F642', 16);
|
||||
wmemmove(firstbuffer, secondbuffer, 32);
|
||||
return 1;
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
#include <stdlib.h>
|
||||
#include <wchar.h>
|
||||
|
||||
#include "test_util.h"
|
||||
|
||||
OPTNONE int main(void) {
|
||||
wchar_t *firstbuffer = malloc(32 * sizeof(wchar_t));
|
||||
wchar_t *secondbuffer = malloc(16 * sizeof(wchar_t));
|
||||
if (!firstbuffer && !secondbuffer) {
|
||||
return 1;
|
||||
}
|
||||
wmemset(secondbuffer, L'\U0001F642', 16);
|
||||
wmemmove(firstbuffer, secondbuffer, 16);
|
||||
return 0;
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
#include <stdlib.h>
|
||||
#include <wchar.h>
|
||||
|
||||
#include "test_util.h"
|
||||
|
||||
OPTNONE int main(void) {
|
||||
wchar_t *firstbuffer = malloc(16 * sizeof(wchar_t));
|
||||
wchar_t *secondbuffer = malloc(16 * sizeof(wchar_t));
|
||||
if (!firstbuffer && !secondbuffer) {
|
||||
return 1;
|
||||
}
|
||||
wmemset(secondbuffer, L'\U0001F642', 16);
|
||||
wmemmove(firstbuffer, secondbuffer, 16);
|
||||
return 0;
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
#include <stdlib.h>
|
||||
#include <wchar.h>
|
||||
|
||||
#include "test_util.h"
|
||||
|
||||
OPTNONE int main(void) {
|
||||
wchar_t *buffer = malloc(16 * sizeof(wchar_t));
|
||||
if (!buffer) {
|
||||
return 1;
|
||||
}
|
||||
wmemset(buffer, L'\U0001F642', 32);
|
||||
return 1;
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
#include <stdlib.h>
|
||||
#include <wchar.h>
|
||||
|
||||
#include "test_util.h"
|
||||
|
||||
OPTNONE int main(void) {
|
||||
wchar_t *buffer = malloc(32 * sizeof(wchar_t));
|
||||
if (!buffer) {
|
||||
return 1;
|
||||
}
|
||||
wmemset(buffer, L'\U0001F642', 16);
|
||||
return 0;
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
#include <stdlib.h>
|
||||
#include <wchar.h>
|
||||
|
||||
#include "test_util.h"
|
||||
|
||||
OPTNONE int main(void) {
|
||||
wchar_t *buffer = malloc(16 * sizeof(wchar_t));
|
||||
if (!buffer) {
|
||||
return 1;
|
||||
}
|
||||
wmemset(buffer, L'\U0001F642', 16);
|
||||
return 0;
|
||||
}
|
12
wmemcpy.c
Normal file
12
wmemcpy.c
Normal file
|
@ -0,0 +1,12 @@
|
|||
#include "musl.h"
|
||||
|
||||
/* Copied from musl libc version 1.2.5 licensed under the MIT license */
|
||||
|
||||
#include <wchar.h>
|
||||
|
||||
wchar_t *musl_wmemcpy(wchar_t *restrict d, const wchar_t *restrict s, size_t n)
|
||||
{
|
||||
wchar_t *a = d;
|
||||
while (n--) *d++ = *s++;
|
||||
return a;
|
||||
}
|
17
wmemmove.c
Normal file
17
wmemmove.c
Normal file
|
@ -0,0 +1,17 @@
|
|||
#include "musl.h"
|
||||
|
||||
/* Copied from musl libc version 1.2.5 licensed under the MIT license */
|
||||
|
||||
#include <wchar.h>
|
||||
#include <stdint.h>
|
||||
|
||||
wchar_t *musl_wmemmove(wchar_t *d, const wchar_t *s, size_t n)
|
||||
{
|
||||
wchar_t *d0 = d;
|
||||
if (d == s) return d;
|
||||
if ((uintptr_t)d-(uintptr_t)s < n * sizeof *d)
|
||||
while (n--) d[n] = s[n];
|
||||
else
|
||||
while (n--) *d++ = *s++;
|
||||
return d0;
|
||||
}
|
Loading…
Add table
Reference in a new issue