Compare commits

..

2 commits

Author SHA1 Message Date
SkewedZeppelin
bf211cd9e4
Merge 4461652d45 into 4fe9018b6f 2025-03-23 00:00:55 +00:00
Tavi
4461652d45
perform size checks on memcpy/memmove/memset
- memset is disabled for now as it causes hangs
- underlying functions were copied from isoalloc, licensed Apache-2.0
	- credit Chris Rohlf for memcpy/memset
	- credit David Carlier for memmove
- use the fast path as some programs crash otherwise

Signed-off-by: Tavi <tavi@divested.dev>
2025-03-22 20:00:39 -04:00
15 changed files with 117 additions and 17 deletions

View file

@ -1875,7 +1875,7 @@ EXPORT size_t h_malloc_object_size_fast(const void *p) {
}
#if CONFIG_BLOCK_OPS_CHECK_SIZE
void *h_memcpy_real(void *dst, const void *src, size_t len) {
inline void *h_memcpy_real(void *dst, const void *src, size_t len) {
char *p_dst = (char *)dst;
char const *p_src = (char const *)src;
@ -1897,7 +1897,7 @@ EXPORT void *h_memcpy(void *dst, const void *src, size_t len) {
return h_memcpy_real(dst, src, len);
}
void *h_memmove_real(void *dst, const void *src, size_t len) {
inline void *h_memmove_real(void *dst, const void *src, size_t len) {
char *p_dst = (char *)dst;
char const *p_src = (char const *)src;
@ -1929,7 +1929,7 @@ EXPORT void *h_memmove(void *dst, const void *src, size_t len) {
return h_memmove_real(dst, src, len);
}
void *h_memset_real(void *dst, int value, size_t len) {
inline void *h_memset_real(void *dst, int value, size_t len) {
char *p_dst = (char *)dst;
while(len--) {

9
test/.gitignore vendored
View file

@ -43,8 +43,13 @@ uninitialized_read_small
realloc_init
memcpy_buffer_overflow
memcpy_read_overflow
memcpy_valid
memcpy_valid_same
memcpy_valid_mismatched
memmove_buffer_overflow
memmove_read_overflow
memmove_valid
memmove_valid_same
memmove_valid_mismatched
memset_buffer_overflow
memset_valid_same
memset_valid_mismatched
__pycache__/

View file

@ -70,10 +70,15 @@ EXECUTABLES := \
realloc_init \
memcpy_buffer_overflow \
memcpy_read_overflow \
memcpy_valid \
memcpy_valid_same \
memcpy_valid_mismatched \
memmove_buffer_overflow \
memmove_read_overflow \
memmove_valid
memmove_valid_same \
memmove_valid_mismatched \
memset_buffer_overflow \
memset_valid_same \
memset_valid_mismatched
all: $(EXECUTABLES)

View file

@ -1,4 +1,3 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

View file

@ -1,4 +1,3 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

View file

@ -0,0 +1,15 @@
#include <stdlib.h>
#include <string.h>
#include "test_util.h"
OPTNONE int main(void) {
char *firstbuffer = malloc(16);
char *secondbuffer = malloc(8);
if (!firstbuffer && !secondbuffer) {
return 1;
}
memset(secondbuffer, 'a', 8);
memcpy(firstbuffer, secondbuffer, 8);
return 0;
}

View file

@ -1,4 +1,3 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

View file

@ -1,4 +1,3 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

View file

@ -1,4 +1,3 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

View file

@ -0,0 +1,15 @@
#include <stdlib.h>
#include <string.h>
#include "test_util.h"
OPTNONE int main(void) {
char *firstbuffer = malloc(16);
char *secondbuffer = malloc(8);
if (!firstbuffer && !secondbuffer) {
return 1;
}
memset(secondbuffer, 'a', 8);
memmove(firstbuffer, secondbuffer, 8);
return 0;
}

View file

@ -1,4 +1,3 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

View file

@ -0,0 +1,13 @@
#include <stdlib.h>
#include <string.h>
#include "test_util.h"
OPTNONE int main(void) {
char *buffer = malloc(16);
if (!buffer) {
return 1;
}
memset(buffer, 'a', 32);
return 1;
}

View file

@ -0,0 +1,13 @@
#include <stdlib.h>
#include <string.h>
#include "test_util.h"
OPTNONE int main(void) {
char *buffer = malloc(16);
if (!buffer) {
return 1;
}
memset(buffer, 'a', 8);
return 0;
}

13
test/memset_valid_same.c Normal file
View file

@ -0,0 +1,13 @@
#include <stdlib.h>
#include <string.h>
#include "test_util.h"
OPTNONE int main(void) {
char *buffer = malloc(16);
if (!buffer) {
return 1;
}
memset(buffer, 'a', 16);
return 0;
}

View file

@ -252,9 +252,14 @@ class TestSimpleMemoryCorruption(unittest.TestCase):
# self.assertEqual(stderr.decode(
# "utf-8"), "fatal allocator error: memcpy read overflow\n")
def test_memcpy_valid(self):
def test_memcpy_valid_same(self):
_stdout, _stderr, returncode = self.run_test(
"memcpy_valid")
"memcpy_valid_same")
self.assertEqual(returncode, 0)
def test_memcpy_valid_mismatched(self):
_stdout, _stderr, returncode = self.run_test(
"memcpy_valid_mismatched")
self.assertEqual(returncode, 0)
#def test_memmove_buffer_overflow(self):
@ -271,9 +276,31 @@ class TestSimpleMemoryCorruption(unittest.TestCase):
# self.assertEqual(stderr.decode(
# "utf-8"), "fatal allocator error: memmove read overflow\n")
def test_memmove_valid(self):
def test_memmove_valid_same(self):
_stdout, _stderr, returncode = self.run_test(
"memmove_valid")
"memmove_valid_same")
self.assertEqual(returncode, 0)
def test_memmove_valid_mismatched(self):
_stdout, _stderr, returncode = self.run_test(
"memmove_valid_mismatched")
self.assertEqual(returncode, 0)
#def test_memset_buffer_overflow(self):
# _stdout, stderr, returncode = self.run_test(
# "memset_buffer_overflow")
# self.assertEqual(returncode, -6)
# self.assertEqual(stderr.decode(
# "utf-8"), "fatal allocator error: memset buffer overflow\n")
def test_memset_valid_same(self):
_stdout, _stderr, returncode = self.run_test(
"memset_valid_same")
self.assertEqual(returncode, 0)
def test_memset_valid_mismatched(self):
_stdout, _stderr, returncode = self.run_test(
"memset_valid_mismatched")
self.assertEqual(returncode, 0)
if __name__ == '__main__':