mirror of
				https://github.com/GrapheneOS/hardened_malloc.git
				synced 2025-10-31 00:06:33 +01:00 
			
		
		
		
	perform size checks on memcpy/memmove/memset
Signed-off-by: Tavi <tavi@divested.dev> Co-authored-by: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com>
This commit is contained in:
		
							parent
							
								
									4fe9018b6f
								
							
						
					
					
						commit
						0cada13b78
					
				
					 45 changed files with 1112 additions and 13 deletions
				
			
		|  | @ -28,6 +28,7 @@ common_cflags = [ | ||||||
|     "-DN_ARENA=1", |     "-DN_ARENA=1", | ||||||
|     "-DCONFIG_STATS=true", |     "-DCONFIG_STATS=true", | ||||||
|     "-DCONFIG_SELF_INIT=false", |     "-DCONFIG_SELF_INIT=false", | ||||||
|  |     "-DCONFIG_BLOCK_OPS_CHECK_SIZE=false", | ||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
| cc_defaults { | cc_defaults { | ||||||
|  |  | ||||||
							
								
								
									
										24
									
								
								CREDITS
									
										
									
									
									
								
							
							
						
						
									
										24
									
								
								CREDITS
									
										
									
									
									
								
							|  | @ -23,6 +23,30 @@ h_malloc.c open-addressed hash table (regions_grow, regions_insert, regions_find | ||||||
|     ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |     ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||||||
|     OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |     OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||||||
| 
 | 
 | ||||||
|  | memcpy.c, memccpy.c, memmove.c, memset.c, wmemset.c: | ||||||
|  |     Copyright © 2005-2020 Rich Felker, et al. | ||||||
|  | 
 | ||||||
|  |     Permission is hereby granted, free of charge, to any person obtaining | ||||||
|  |     a copy of this software and associated documentation files (the | ||||||
|  |     "Software"), to deal in the Software without restriction, including | ||||||
|  |     without limitation the rights to use, copy, modify, merge, publish, | ||||||
|  |     distribute, sublicense, and/or sell copies of the Software, and to | ||||||
|  |     permit persons to whom the Software is furnished to do so, subject to | ||||||
|  |     the following conditions: | ||||||
|  | 
 | ||||||
|  |     The above copyright notice and this permission notice shall be | ||||||
|  |     included in all copies or substantial portions of the Software. | ||||||
|  | 
 | ||||||
|  |     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||||||
|  |     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||||
|  |     MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | ||||||
|  |     IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | ||||||
|  |     CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||||||
|  |     TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||||||
|  |     SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||||
|  | 
 | ||||||
|  |     Contributor list: https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT | ||||||
|  | 
 | ||||||
| libdivide: | libdivide: | ||||||
| 
 | 
 | ||||||
|     Copyright (C) 2010 - 2019 ridiculous_fish, <libdivide@ridiculousfish.com> |     Copyright (C) 2010 - 2019 ridiculous_fish, <libdivide@ridiculousfish.com> | ||||||
|  |  | ||||||
							
								
								
									
										26
									
								
								Makefile
									
										
									
									
									
								
							
							
						
						
									
										26
									
								
								Makefile
									
										
									
									
									
								
							|  | @ -40,6 +40,10 @@ CXXFLAGS := $(CXXFLAGS) -std=c++17 -fsized-deallocation $(SHARED_FLAGS) | ||||||
| LDFLAGS := $(LDFLAGS) -Wl,-O1,--as-needed,-z,defs,-z,relro,-z,now,-z,nodlopen,-z,text | LDFLAGS := $(LDFLAGS) -Wl,-O1,--as-needed,-z,defs,-z,relro,-z,now,-z,nodlopen,-z,text | ||||||
| 
 | 
 | ||||||
| SOURCES := chacha.c h_malloc.c memory.c pages.c random.c util.c | SOURCES := chacha.c h_malloc.c memory.c pages.c random.c util.c | ||||||
|  | ifeq ($(CONFIG_BLOCK_OPS_CHECK_SIZE),true) | ||||||
|  |     SOURCES += memcpy.c memccpy.c memmove.c memset.c wmemset.c | ||||||
|  |     BOSC_EXTRAS := musl.h | ||||||
|  | endif | ||||||
| OBJECTS := $(SOURCES:.c=.o) | OBJECTS := $(SOURCES:.c=.o) | ||||||
| 
 | 
 | ||||||
| ifeq ($(CONFIG_CXX_ALLOCATOR),true) | ifeq ($(CONFIG_CXX_ALLOCATOR),true) | ||||||
|  | @ -89,6 +93,10 @@ ifeq (,$(filter $(CONFIG_SELF_INIT),true false)) | ||||||
|     $(error CONFIG_SELF_INIT must be true or false) |     $(error CONFIG_SELF_INIT must be true or false) | ||||||
| endif | endif | ||||||
| 
 | 
 | ||||||
|  | ifeq (,$(filter $(CONFIG_BLOCK_OPS_CHECK_SIZE),true false)) | ||||||
|  |     $(error CONFIG_BLOCK_OPS_CHECK_SIZE must be true or false) | ||||||
|  | endif | ||||||
|  | 
 | ||||||
| CPPFLAGS += \
 | CPPFLAGS += \
 | ||||||
|     -DCONFIG_SEAL_METADATA=$(CONFIG_SEAL_METADATA) \
 |     -DCONFIG_SEAL_METADATA=$(CONFIG_SEAL_METADATA) \
 | ||||||
|     -DZERO_ON_FREE=$(CONFIG_ZERO_ON_FREE) \
 |     -DZERO_ON_FREE=$(CONFIG_ZERO_ON_FREE) \
 | ||||||
|  | @ -108,7 +116,8 @@ CPPFLAGS += \ | ||||||
|     -DCONFIG_CLASS_REGION_SIZE=$(CONFIG_CLASS_REGION_SIZE) \
 |     -DCONFIG_CLASS_REGION_SIZE=$(CONFIG_CLASS_REGION_SIZE) \
 | ||||||
|     -DN_ARENA=$(CONFIG_N_ARENA) \
 |     -DN_ARENA=$(CONFIG_N_ARENA) \
 | ||||||
|     -DCONFIG_STATS=$(CONFIG_STATS) \
 |     -DCONFIG_STATS=$(CONFIG_STATS) \
 | ||||||
|     -DCONFIG_SELF_INIT=$(CONFIG_SELF_INIT) |     -DCONFIG_SELF_INIT=$(CONFIG_SELF_INIT) \
 | ||||||
|  |     -DCONFIG_BLOCK_OPS_CHECK_SIZE=$(CONFIG_BLOCK_OPS_CHECK_SIZE) | ||||||
| 
 | 
 | ||||||
| $(OUT)/libhardened_malloc$(SUFFIX).so: $(OBJECTS) | $(OUT) | $(OUT)/libhardened_malloc$(SUFFIX).so: $(OBJECTS) | $(OUT) | ||||||
| 	$(CC) $(CFLAGS) $(LDFLAGS) -shared $^ $(LDLIBS) -o $@ | 	$(CC) $(CFLAGS) $(LDFLAGS) -shared $^ $(LDLIBS) -o $@ | ||||||
|  | @ -118,7 +127,7 @@ $(OUT): | ||||||
| 
 | 
 | ||||||
| $(OUT)/chacha.o: chacha.c chacha.h util.h $(CONFIG_FILE) | $(OUT) | $(OUT)/chacha.o: chacha.c chacha.h util.h $(CONFIG_FILE) | $(OUT) | ||||||
| 	$(COMPILE.c) $(OUTPUT_OPTION) $< | 	$(COMPILE.c) $(OUTPUT_OPTION) $< | ||||||
| $(OUT)/h_malloc.o: h_malloc.c include/h_malloc.h mutex.h memory.h pages.h random.h util.h $(CONFIG_FILE) | $(OUT) | $(OUT)/h_malloc.o: h_malloc.c include/h_malloc.h mutex.h memory.h $(BOSC_EXTRAS) pages.h random.h util.h $(CONFIG_FILE) | $(OUT) | ||||||
| 	$(COMPILE.c) $(OUTPUT_OPTION) $< | 	$(COMPILE.c) $(OUTPUT_OPTION) $< | ||||||
| $(OUT)/memory.o: memory.c memory.h util.h $(CONFIG_FILE) | $(OUT) | $(OUT)/memory.o: memory.c memory.h util.h $(CONFIG_FILE) | $(OUT) | ||||||
| 	$(COMPILE.c) $(OUTPUT_OPTION) $< | 	$(COMPILE.c) $(OUTPUT_OPTION) $< | ||||||
|  | @ -126,11 +135,22 @@ $(OUT)/new.o: new.cc include/h_malloc.h util.h $(CONFIG_FILE) | $(OUT) | ||||||
| 	$(COMPILE.cc) $(OUTPUT_OPTION) $< | 	$(COMPILE.cc) $(OUTPUT_OPTION) $< | ||||||
| $(OUT)/pages.o: pages.c pages.h memory.h util.h $(CONFIG_FILE) | $(OUT) | $(OUT)/pages.o: pages.c pages.h memory.h util.h $(CONFIG_FILE) | $(OUT) | ||||||
| 	$(COMPILE.c) $(OUTPUT_OPTION) $< | 	$(COMPILE.c) $(OUTPUT_OPTION) $< | ||||||
| $(OUT)/random.o: random.c random.h chacha.h util.h $(CONFIG_FILE) | $(OUT) | $(OUT)/random.o: random.c random.h chacha.h $(BOSC_EXTRAS) util.h $(CONFIG_FILE) | $(OUT) | ||||||
| 	$(COMPILE.c) $(OUTPUT_OPTION) $< | 	$(COMPILE.c) $(OUTPUT_OPTION) $< | ||||||
| $(OUT)/util.o: util.c util.h $(CONFIG_FILE) | $(OUT) | $(OUT)/util.o: util.c util.h $(CONFIG_FILE) | $(OUT) | ||||||
| 	$(COMPILE.c) $(OUTPUT_OPTION) $< | 	$(COMPILE.c) $(OUTPUT_OPTION) $< | ||||||
| 
 | 
 | ||||||
|  | $(OUT)/memcpy.o: memcpy.c musl.h $(CONFIG_FILE) | $(OUT) | ||||||
|  | 	$(COMPILE.c) -Wno-cast-align $(OUTPUT_OPTION) $< | ||||||
|  | $(OUT)/memccpy.o: memccpy.c musl.h $(CONFIG_FILE) | $(OUT) | ||||||
|  | 	$(COMPILE.c) -Wno-cast-align $(OUTPUT_OPTION) $< | ||||||
|  | $(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)/wmemset.o: wmemset.c musl.h $(CONFIG_FILE) | $(OUT) | ||||||
|  | 	$(COMPILE.c) $(OUTPUT_OPTION) $< | ||||||
|  | 
 | ||||||
| check: tidy | check: tidy | ||||||
| 
 | 
 | ||||||
| tidy: | tidy: | ||||||
|  |  | ||||||
|  | @ -276,6 +276,9 @@ The following boolean configuration options are available: | ||||||
|   hardware, which may become drastically lower in the future. Whether or not |   hardware, which may become drastically lower in the future. Whether or not | ||||||
|   this feature is enabled, the metadata is all contained within an isolated |   this feature is enabled, the metadata is all contained within an isolated | ||||||
|   memory region with high entropy random guard regions around it. |   memory region with high entropy random guard regions around it. | ||||||
|  | * `CONFIG_BLOCK_OPS_CHECK_SIZE`: `true` or `false` (default) to ensure length | ||||||
|  |   parameter of the memcpy/memccpy/memmove/memset block operations and their | ||||||
|  |   wide variants are within approximate bounds to minimize buffer overflows. | ||||||
| 
 | 
 | ||||||
| The following integer configuration options are available: | The following integer configuration options are available: | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -21,3 +21,4 @@ CONFIG_CLASS_REGION_SIZE := 34359738368 # 32GiB | ||||||
| CONFIG_N_ARENA := 4 | CONFIG_N_ARENA := 4 | ||||||
| CONFIG_STATS := false | CONFIG_STATS := false | ||||||
| CONFIG_SELF_INIT := true | CONFIG_SELF_INIT := true | ||||||
|  | CONFIG_BLOCK_OPS_CHECK_SIZE := false | ||||||
|  |  | ||||||
|  | @ -21,3 +21,4 @@ CONFIG_CLASS_REGION_SIZE := 34359738368 # 32GiB | ||||||
| CONFIG_N_ARENA := 4 | CONFIG_N_ARENA := 4 | ||||||
| CONFIG_STATS := false | CONFIG_STATS := false | ||||||
| CONFIG_SELF_INIT := true | CONFIG_SELF_INIT := true | ||||||
|  | CONFIG_BLOCK_OPS_CHECK_SIZE := false | ||||||
|  |  | ||||||
							
								
								
									
										114
									
								
								h_malloc.c
									
										
									
									
									
								
							
							
						
						
									
										114
									
								
								h_malloc.c
									
										
									
									
									
								
							|  | @ -20,6 +20,10 @@ | ||||||
| #include "random.h" | #include "random.h" | ||||||
| #include "util.h" | #include "util.h" | ||||||
| 
 | 
 | ||||||
|  | #if CONFIG_BLOCK_OPS_CHECK_SIZE && !defined(HAS_ARM_MTE) | ||||||
|  | #include "musl.h" | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
| #ifdef USE_PKEY | #ifdef USE_PKEY | ||||||
| #include <sys/mman.h> | #include <sys/mman.h> | ||||||
| #endif | #endif | ||||||
|  | @ -528,7 +532,7 @@ static void set_canary(UNUSED const struct slab_metadata *metadata, UNUSED void | ||||||
|     } |     } | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|     memcpy((char *)p + size - canary_size, &metadata->canary_value, canary_size); |     h_memcpy_internal((char *)p + size - canary_size, &metadata->canary_value, canary_size); | ||||||
| #endif | #endif | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -541,7 +545,7 @@ static void check_canary(UNUSED const struct slab_metadata *metadata, UNUSED con | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|     u64 canary_value; |     u64 canary_value; | ||||||
|     memcpy(&canary_value, (const char *)p + size - canary_size, canary_size); |     h_memcpy_internal(&canary_value, (const char *)p + size - canary_size, canary_size); | ||||||
| 
 | 
 | ||||||
| #ifdef HAS_ARM_MTE | #ifdef HAS_ARM_MTE | ||||||
|     if (unlikely(canary_value == 0)) { |     if (unlikely(canary_value == 0)) { | ||||||
|  | @ -831,7 +835,7 @@ static inline void deallocate_small(void *p, const size_t *expected_size) { | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|         if (ZERO_ON_FREE && !skip_zero) { |         if (ZERO_ON_FREE && !skip_zero) { | ||||||
|             memset(p, 0, size - canary_size); |             h_memset_internal(p, 0, size - canary_size); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -1502,7 +1506,7 @@ EXPORT void *h_calloc(size_t nmemb, size_t size) { | ||||||
|     total_size = adjust_size_for_canary(total_size); |     total_size = adjust_size_for_canary(total_size); | ||||||
|     void *p = alloc(total_size); |     void *p = alloc(total_size); | ||||||
|     if (!ZERO_ON_FREE && likely(p != NULL) && total_size && total_size <= max_slab_size_class) { |     if (!ZERO_ON_FREE && likely(p != NULL) && total_size && total_size <= max_slab_size_class) { | ||||||
|         memset(p, 0, total_size - canary_size); |         h_memset_internal(p, 0, total_size - canary_size); | ||||||
|     } |     } | ||||||
| #ifdef HAS_ARM_MTE | #ifdef HAS_ARM_MTE | ||||||
|     // use an assert instead of adding a conditional to memset() above (freed memory is always
 |     // use an assert instead of adding a conditional to memset() above (freed memory is always
 | ||||||
|  | @ -1624,7 +1628,7 @@ EXPORT void *h_realloc(void *old, size_t size) { | ||||||
|                 mutex_unlock(&ra->lock); |                 mutex_unlock(&ra->lock); | ||||||
| 
 | 
 | ||||||
|                 if (memory_remap_fixed(old, old_size, new, size)) { |                 if (memory_remap_fixed(old, old_size, new, size)) { | ||||||
|                     memcpy(new, old, copy_size); |                     h_memcpy_internal(new, old, copy_size); | ||||||
|                     deallocate_pages(old, old_size, old_guard_size); |                     deallocate_pages(old, old_size, old_guard_size); | ||||||
|                 } else { |                 } else { | ||||||
|                     memory_unmap((char *)old - old_guard_size, old_guard_size); |                     memory_unmap((char *)old - old_guard_size, old_guard_size); | ||||||
|  | @ -1646,7 +1650,7 @@ EXPORT void *h_realloc(void *old, size_t size) { | ||||||
|     if (copy_size > 0 && copy_size <= max_slab_size_class) { |     if (copy_size > 0 && copy_size <= max_slab_size_class) { | ||||||
|         copy_size -= canary_size; |         copy_size -= canary_size; | ||||||
|     } |     } | ||||||
|     memcpy(new, old_orig, copy_size); |     h_memcpy_internal(new, old_orig, copy_size); | ||||||
|     if (old_size <= max_slab_size_class) { |     if (old_size <= max_slab_size_class) { | ||||||
|         deallocate_small(old, NULL); |         deallocate_small(old, NULL); | ||||||
|     } else { |     } else { | ||||||
|  | @ -1874,6 +1878,104 @@ EXPORT size_t h_malloc_object_size_fast(const void *p) { | ||||||
|     return SIZE_MAX; |     return SIZE_MAX; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | #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)) { | ||||||
|  |         return dst; | ||||||
|  |     } | ||||||
|  |     if (unlikely(dst < (src + len) && (dst + len) > src)) { | ||||||
|  |         fatal_error("memcpy overlap"); | ||||||
|  |     } | ||||||
|  |     if (unlikely(len > malloc_object_size(src))) { | ||||||
|  |         fatal_error("memcpy read overflow"); | ||||||
|  |     } | ||||||
|  |     if (unlikely(len > malloc_object_size(dst))) { | ||||||
|  |         fatal_error("memcpy buffer overflow"); | ||||||
|  |     } | ||||||
|  |     return musl_memcpy(dst, src, len); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | EXPORT void *memccpy(void *restrict dst, const void *restrict src, int value, size_t len) { | ||||||
|  |     if (unlikely(dst == src || len == 0)) { | ||||||
|  |         return dst; | ||||||
|  |     } | ||||||
|  |     if (unlikely(dst < (src + len) && (dst + len) > src)) { | ||||||
|  |         fatal_error("memccpy overlap"); | ||||||
|  |     } | ||||||
|  |     if (unlikely(len > malloc_object_size(src))) { | ||||||
|  |         fatal_error("memccpy read overflow"); | ||||||
|  |     } | ||||||
|  |     if (unlikely(len > malloc_object_size(dst))) { | ||||||
|  |         fatal_error("memccpy buffer overflow"); | ||||||
|  |     } | ||||||
|  |     return musl_memccpy(dst, src, value, len); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | EXPORT void *memmove(void *dst, const void *src, size_t len) { | ||||||
|  |     if (unlikely(dst == src || len == 0)) { | ||||||
|  |         return dst; | ||||||
|  |     } | ||||||
|  |     if (unlikely(len > malloc_object_size(src))) { | ||||||
|  |         fatal_error("memmove read overflow"); | ||||||
|  |     } | ||||||
|  |     if (unlikely(len > malloc_object_size(dst))) { | ||||||
|  |         fatal_error("memmove buffer overflow"); | ||||||
|  |     } | ||||||
|  |     return musl_memmove(dst, src, len); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | EXPORT void *memset(void *dst, int value, size_t len) { | ||||||
|  |     if (unlikely(len == 0)) { | ||||||
|  |         return dst; | ||||||
|  |     } | ||||||
|  |     if (unlikely(len > malloc_object_size(dst))) { | ||||||
|  |         fatal_error("memset buffer overflow"); | ||||||
|  |     } | ||||||
|  |     return musl_memset(dst, value, len); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | EXPORT wchar_t *wmemcpy(wchar_t *restrict dst, const wchar_t *restrict src, size_t len) { | ||||||
|  |     if (unlikely(dst == src || len == 0)) { | ||||||
|  |         return dst; | ||||||
|  |     } | ||||||
|  |     if (unlikely(dst < (src + len) && (dst + len) > src)) { | ||||||
|  |         fatal_error("wmemcpy overlap"); | ||||||
|  |     } | ||||||
|  |     size_t lenAdj = len * sizeof(wchar_t); | ||||||
|  |     if (unlikely(lenAdj > malloc_object_size(src))) { | ||||||
|  |         fatal_error("wmemcpy read overflow"); | ||||||
|  |     } | ||||||
|  |     if (unlikely(lenAdj > malloc_object_size(dst))) { | ||||||
|  |         fatal_error("wmemcpy buffer overflow"); | ||||||
|  |     } | ||||||
|  |     return (wchar_t *)musl_memcpy((char *)dst, (const char *)src, lenAdj); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | EXPORT wchar_t *wmemmove(wchar_t *dst, const wchar_t *src, size_t len) { | ||||||
|  |     if (unlikely(dst == src || len == 0)) { | ||||||
|  |         return dst; | ||||||
|  |     } | ||||||
|  |     size_t lenAdj = len * sizeof(wchar_t); | ||||||
|  |     if (unlikely(lenAdj > malloc_object_size(src))) { | ||||||
|  |         fatal_error("wmemmove read overflow"); | ||||||
|  |     } | ||||||
|  |     if (unlikely(lenAdj > malloc_object_size(dst))) { | ||||||
|  |         fatal_error("wmemmove buffer overflow"); | ||||||
|  |     } | ||||||
|  |     return (wchar_t *)musl_memmove((char *)dst, (const char *)src, lenAdj); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | EXPORT wchar_t *wmemset(wchar_t *dst, wchar_t value, size_t len) { | ||||||
|  |     if (unlikely(len == 0)) { | ||||||
|  |         return dst; | ||||||
|  |     } | ||||||
|  |     if (unlikely((len * sizeof(wchar_t)) > 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) */ | ||||||
|  | 
 | ||||||
| EXPORT int h_mallopt(UNUSED int param, UNUSED int value) { | EXPORT int h_mallopt(UNUSED int param, UNUSED int value) { | ||||||
| #ifdef __ANDROID__ | #ifdef __ANDROID__ | ||||||
|     if (param == M_PURGE) { |     if (param == M_PURGE) { | ||||||
|  |  | ||||||
|  | @ -55,6 +55,23 @@ __attribute__((malloc)) __attribute__((alloc_size(2))) __attribute__((alloc_alig | ||||||
| void *h_aligned_alloc(size_t alignment, size_t size); | void *h_aligned_alloc(size_t alignment, size_t size); | ||||||
| void h_free(void *ptr); | void h_free(void *ptr); | ||||||
| 
 | 
 | ||||||
|  | #if CONFIG_BLOCK_OPS_CHECK_SIZE && !defined(HAS_ARM_MTE) | ||||||
|  | void *memcpy(void *dst, const void *src, size_t len); | ||||||
|  | void *memccpy(void *dst, const void *src, int value, size_t len); | ||||||
|  | void *memmove(void *dst, const void *src, size_t len); | ||||||
|  | void *memset(void *dst, int value, size_t len); | ||||||
|  | wchar_t *wmemcpy(wchar_t *dst, const wchar_t *src, size_t len); | ||||||
|  | wchar_t *wmemmove(wchar_t *dst, const wchar_t *src, size_t len); | ||||||
|  | wchar_t *wmemset(wchar_t *dst, wchar_t value, size_t len); | ||||||
|  | #define h_memcpy_internal musl_memcpy | ||||||
|  | #define h_memmove_internal musl_memmove | ||||||
|  | #define h_memset_internal musl_memset | ||||||
|  | #else | ||||||
|  | #define h_memcpy_internal memcpy | ||||||
|  | #define h_memmove_internal memmove | ||||||
|  | #define h_memset_internal memset | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
| // POSIX
 | // POSIX
 | ||||||
| int h_posix_memalign(void **memptr, size_t alignment, size_t size); | int h_posix_memalign(void **memptr, size_t alignment, size_t size); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										38
									
								
								memccpy.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								memccpy.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,38 @@ | ||||||
|  | #include "musl.h" | ||||||
|  | 
 | ||||||
|  | /* Copied from musl libc version 1.2.5 licensed under the MIT license */ | ||||||
|  | 
 | ||||||
|  | #include <string.h> | ||||||
|  | #include <stdint.h> | ||||||
|  | #include <limits.h> | ||||||
|  | 
 | ||||||
|  | #define ALIGN (sizeof(size_t)-1) | ||||||
|  | #define ONES ((size_t)-1/UCHAR_MAX) | ||||||
|  | #define HIGHS (ONES * (UCHAR_MAX/2+1)) | ||||||
|  | #define HASZERO(x) (((x)-ONES) & ~(x) & HIGHS) | ||||||
|  | 
 | ||||||
|  | void *musl_memccpy(void *restrict dest, const void *restrict src, int c, size_t n) | ||||||
|  | { | ||||||
|  | 	unsigned char *d = dest; | ||||||
|  | 	const unsigned char *s = src; | ||||||
|  | 
 | ||||||
|  | 	c = (unsigned char)c; | ||||||
|  | #ifdef __GNUC__ | ||||||
|  | 	typedef size_t __attribute__((__may_alias__)) word; | ||||||
|  | 	word *wd; | ||||||
|  | 	const word *ws; | ||||||
|  | 	if (((uintptr_t)s & ALIGN) == ((uintptr_t)d & ALIGN)) { | ||||||
|  | 		for (; ((uintptr_t)s & ALIGN) && n && (*d=*s)!=c; n--, s++, d++); | ||||||
|  | 		if ((uintptr_t)s & ALIGN) goto tail; | ||||||
|  | 		size_t k = ONES * c; | ||||||
|  | 		wd=(void *)d; ws=(const void *)s; | ||||||
|  | 		for (; n>=sizeof(size_t) && !HASZERO(*ws^k); | ||||||
|  | 		       n-=sizeof(size_t), ws++, wd++) *wd = *ws; | ||||||
|  | 		d=(void *)wd; s=(const void *)ws; | ||||||
|  | 	} | ||||||
|  | #endif | ||||||
|  | 	for (; n && (*d=*s)!=c; n--, s++, d++); | ||||||
|  | tail: | ||||||
|  | 	if (n) return d+1; | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
							
								
								
									
										132
									
								
								memcpy.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										132
									
								
								memcpy.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,132 @@ | ||||||
|  | #include "musl.h" | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * Copied from musl libc version 1.2.5 licensed under the MIT license | ||||||
|  |  * | ||||||
|  |  * Christian Göttsche: Added const qualifiers to retain const correctness. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #include <string.h> | ||||||
|  | #include <stdint.h> | ||||||
|  | #include <endian.h> | ||||||
|  | 
 | ||||||
|  | void *musl_memcpy(void *restrict dest, const void *restrict src, size_t n) | ||||||
|  | { | ||||||
|  | 	unsigned char *d = dest; | ||||||
|  | 	const unsigned char *s = src; | ||||||
|  | 
 | ||||||
|  | #ifdef __GNUC__ | ||||||
|  | 
 | ||||||
|  | #if __BYTE_ORDER == __LITTLE_ENDIAN | ||||||
|  | #define LS >> | ||||||
|  | #define RS << | ||||||
|  | #else | ||||||
|  | #define LS << | ||||||
|  | #define RS >> | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | 	typedef uint32_t __attribute__((__may_alias__)) u32; | ||||||
|  | 	uint32_t w, x; | ||||||
|  | 
 | ||||||
|  | 	for (; (uintptr_t)s % 4 && n; n--) *d++ = *s++; | ||||||
|  | 
 | ||||||
|  | 	if ((uintptr_t)d % 4 == 0) { | ||||||
|  | 		for (; n>=16; s+=16, d+=16, n-=16) { | ||||||
|  | 			*(u32 *)(d+0) = *(const u32 *)(s+0); | ||||||
|  | 			*(u32 *)(d+4) = *(const u32 *)(s+4); | ||||||
|  | 			*(u32 *)(d+8) = *(const u32 *)(s+8); | ||||||
|  | 			*(u32 *)(d+12) = *(const u32 *)(s+12); | ||||||
|  | 		} | ||||||
|  | 		if (n&8) { | ||||||
|  | 			*(u32 *)(d+0) = *(const u32 *)(s+0); | ||||||
|  | 			*(u32 *)(d+4) = *(const u32 *)(s+4); | ||||||
|  | 			d += 8; s += 8; | ||||||
|  | 		} | ||||||
|  | 		if (n&4) { | ||||||
|  | 			*(u32 *)(d+0) = *(const u32 *)(s+0); | ||||||
|  | 			d += 4; s += 4; | ||||||
|  | 		} | ||||||
|  | 		if (n&2) { | ||||||
|  | 			*d++ = *s++; *d++ = *s++; | ||||||
|  | 		} | ||||||
|  | 		if (n&1) { | ||||||
|  | 			*d = *s; | ||||||
|  | 		} | ||||||
|  | 		return dest; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (n >= 32) switch ((uintptr_t)d % 4) { | ||||||
|  | 	case 1: | ||||||
|  | 		w = *(const u32 *)s; | ||||||
|  | 		*d++ = *s++; | ||||||
|  | 		*d++ = *s++; | ||||||
|  | 		*d++ = *s++; | ||||||
|  | 		n -= 3; | ||||||
|  | 		for (; n>=17; s+=16, d+=16, n-=16) { | ||||||
|  | 			x = *(const u32 *)(s+1); | ||||||
|  | 			*(u32 *)(d+0) = (w LS 24) | (x RS 8); | ||||||
|  | 			w = *(const u32 *)(s+5); | ||||||
|  | 			*(u32 *)(d+4) = (x LS 24) | (w RS 8); | ||||||
|  | 			x = *(const u32 *)(s+9); | ||||||
|  | 			*(u32 *)(d+8) = (w LS 24) | (x RS 8); | ||||||
|  | 			w = *(const u32 *)(s+13); | ||||||
|  | 			*(u32 *)(d+12) = (x LS 24) | (w RS 8); | ||||||
|  | 		} | ||||||
|  | 		break; | ||||||
|  | 	case 2: | ||||||
|  | 		w = *(const u32 *)s; | ||||||
|  | 		*d++ = *s++; | ||||||
|  | 		*d++ = *s++; | ||||||
|  | 		n -= 2; | ||||||
|  | 		for (; n>=18; s+=16, d+=16, n-=16) { | ||||||
|  | 			x = *(const u32 *)(s+2); | ||||||
|  | 			*(u32 *)(d+0) = (w LS 16) | (x RS 16); | ||||||
|  | 			w = *(const u32 *)(s+6); | ||||||
|  | 			*(u32 *)(d+4) = (x LS 16) | (w RS 16); | ||||||
|  | 			x = *(const u32 *)(s+10); | ||||||
|  | 			*(u32 *)(d+8) = (w LS 16) | (x RS 16); | ||||||
|  | 			w = *(const u32 *)(s+14); | ||||||
|  | 			*(u32 *)(d+12) = (x LS 16) | (w RS 16); | ||||||
|  | 		} | ||||||
|  | 		break; | ||||||
|  | 	case 3: | ||||||
|  | 		w = *(const u32 *)s; | ||||||
|  | 		*d++ = *s++; | ||||||
|  | 		n -= 1; | ||||||
|  | 		for (; n>=19; s+=16, d+=16, n-=16) { | ||||||
|  | 			x = *(const u32 *)(s+3); | ||||||
|  | 			*(u32 *)(d+0) = (w LS 8) | (x RS 24); | ||||||
|  | 			w = *(const u32 *)(s+7); | ||||||
|  | 			*(u32 *)(d+4) = (x LS 8) | (w RS 24); | ||||||
|  | 			x = *(const u32 *)(s+11); | ||||||
|  | 			*(u32 *)(d+8) = (w LS 8) | (x RS 24); | ||||||
|  | 			w = *(const u32 *)(s+15); | ||||||
|  | 			*(u32 *)(d+12) = (x LS 8) | (w RS 24); | ||||||
|  | 		} | ||||||
|  | 		break; | ||||||
|  | 	} | ||||||
|  | 	if (n&16) { | ||||||
|  | 		*d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++; | ||||||
|  | 		*d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++; | ||||||
|  | 		*d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++; | ||||||
|  | 		*d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++; | ||||||
|  | 	} | ||||||
|  | 	if (n&8) { | ||||||
|  | 		*d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++; | ||||||
|  | 		*d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++; | ||||||
|  | 	} | ||||||
|  | 	if (n&4) { | ||||||
|  | 		*d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++; | ||||||
|  | 	} | ||||||
|  | 	if (n&2) { | ||||||
|  | 		*d++ = *s++; *d++ = *s++; | ||||||
|  | 	} | ||||||
|  | 	if (n&1) { | ||||||
|  | 		*d = *s; | ||||||
|  | 	} | ||||||
|  | 	return dest; | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | 	for (; n; n--) *d++ = *s++; | ||||||
|  | 	return dest; | ||||||
|  | } | ||||||
							
								
								
									
										50
									
								
								memmove.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								memmove.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,50 @@ | ||||||
|  | #include "musl.h" | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * Copied from musl libc version 1.2.5 licensed under the MIT license | ||||||
|  |  * | ||||||
|  |  * Christian Göttsche: Added const qualifiers to retain const correctness. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #include <string.h> | ||||||
|  | #include <stdint.h> | ||||||
|  | 
 | ||||||
|  | #ifdef __GNUC__ | ||||||
|  | typedef __attribute__((__may_alias__)) size_t WT; | ||||||
|  | #define WS (sizeof(WT)) | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | void *musl_memmove(void *dest, const void *src, size_t n) | ||||||
|  | { | ||||||
|  | 	char *d = dest; | ||||||
|  | 	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 (d<s) { | ||||||
|  | #ifdef __GNUC__ | ||||||
|  | 		if ((uintptr_t)s % WS == (uintptr_t)d % WS) { | ||||||
|  | 			while ((uintptr_t)d % WS) { | ||||||
|  | 				if (!n--) return dest; | ||||||
|  | 				*d++ = *s++; | ||||||
|  | 			} | ||||||
|  | 			for (; n>=WS; n-=WS, d+=WS, s+=WS) *(WT *)d = *(const WT *)s; | ||||||
|  | 		} | ||||||
|  | #endif | ||||||
|  | 		for (; n; n--) *d++ = *s++; | ||||||
|  | 	} else { | ||||||
|  | #ifdef __GNUC__ | ||||||
|  | 		if ((uintptr_t)s % WS == (uintptr_t)d % WS) { | ||||||
|  | 			while ((uintptr_t)(d+n) % WS) { | ||||||
|  | 				if (!n--) return dest; | ||||||
|  | 				d[n] = s[n]; | ||||||
|  | 			} | ||||||
|  | 			while (n>=WS) n-=WS, *(WT *)(d+n) = *(const WT *)(s+n); | ||||||
|  | 		} | ||||||
|  | #endif | ||||||
|  | 		while (n) n--, d[n] = s[n]; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return dest; | ||||||
|  | } | ||||||
							
								
								
									
										94
									
								
								memset.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								memset.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,94 @@ | ||||||
|  | #include "musl.h" | ||||||
|  | 
 | ||||||
|  | /* Copied from musl libc version 1.2.5 licensed under the MIT license */ | ||||||
|  | 
 | ||||||
|  | #include <string.h> | ||||||
|  | #include <stdint.h> | ||||||
|  | 
 | ||||||
|  | void *musl_memset(void *dest, int c, size_t n) | ||||||
|  | { | ||||||
|  | 	unsigned char *s = dest; | ||||||
|  | 	size_t k; | ||||||
|  | 
 | ||||||
|  | 	/* Fill head and tail with minimal branching. Each
 | ||||||
|  | 	 * conditional ensures that all the subsequently used | ||||||
|  | 	 * offsets are well-defined and in the dest region. */ | ||||||
|  | 
 | ||||||
|  | 	if (!n) return dest; | ||||||
|  | 	s[0] = c; | ||||||
|  | 	s[n-1] = c; | ||||||
|  | 	if (n <= 2) return dest; | ||||||
|  | 	s[1] = c; | ||||||
|  | 	s[2] = c; | ||||||
|  | 	s[n-2] = c; | ||||||
|  | 	s[n-3] = c; | ||||||
|  | 	if (n <= 6) return dest; | ||||||
|  | 	s[3] = c; | ||||||
|  | 	s[n-4] = c; | ||||||
|  | 	if (n <= 8) return dest; | ||||||
|  | 
 | ||||||
|  | 	/* Advance pointer to align it at a 4-byte boundary,
 | ||||||
|  | 	 * and truncate n to a multiple of 4. The previous code | ||||||
|  | 	 * already took care of any head/tail that get cut off | ||||||
|  | 	 * by the alignment. */ | ||||||
|  | 
 | ||||||
|  | 	k = -(uintptr_t)s & 3; | ||||||
|  | 	s += k; | ||||||
|  | 	n -= k; | ||||||
|  | 	n &= -4; | ||||||
|  | 
 | ||||||
|  | #ifdef __GNUC__ | ||||||
|  | 	typedef uint32_t __attribute__((__may_alias__)) u32; | ||||||
|  | 	typedef uint64_t __attribute__((__may_alias__)) u64; | ||||||
|  | 
 | ||||||
|  | 	u32 c32 = ((u32)-1)/255 * (unsigned char)c; | ||||||
|  | 
 | ||||||
|  | 	/* In preparation to copy 32 bytes at a time, aligned on
 | ||||||
|  | 	 * an 8-byte bounary, fill head/tail up to 28 bytes each. | ||||||
|  | 	 * As in the initial byte-based head/tail fill, each | ||||||
|  | 	 * conditional below ensures that the subsequent offsets | ||||||
|  | 	 * are valid (e.g. !(n<=24) implies n>=28). */ | ||||||
|  | 
 | ||||||
|  | 	*(u32 *)(s+0) = c32; | ||||||
|  | 	*(u32 *)(s+n-4) = c32; | ||||||
|  | 	if (n <= 8) return dest; | ||||||
|  | 	*(u32 *)(s+4) = c32; | ||||||
|  | 	*(u32 *)(s+8) = c32; | ||||||
|  | 	*(u32 *)(s+n-12) = c32; | ||||||
|  | 	*(u32 *)(s+n-8) = c32; | ||||||
|  | 	if (n <= 24) return dest; | ||||||
|  | 	*(u32 *)(s+12) = c32; | ||||||
|  | 	*(u32 *)(s+16) = c32; | ||||||
|  | 	*(u32 *)(s+20) = c32; | ||||||
|  | 	*(u32 *)(s+24) = c32; | ||||||
|  | 	*(u32 *)(s+n-28) = c32; | ||||||
|  | 	*(u32 *)(s+n-24) = c32; | ||||||
|  | 	*(u32 *)(s+n-20) = c32; | ||||||
|  | 	*(u32 *)(s+n-16) = c32; | ||||||
|  | 
 | ||||||
|  | 	/* Align to a multiple of 8 so we can fill 64 bits at a time,
 | ||||||
|  | 	 * and avoid writing the same bytes twice as much as is | ||||||
|  | 	 * practical without introducing additional branching. */ | ||||||
|  | 
 | ||||||
|  | 	k = 24 + ((uintptr_t)s & 4); | ||||||
|  | 	s += k; | ||||||
|  | 	n -= k; | ||||||
|  | 
 | ||||||
|  | 	/* If this loop is reached, 28 tail bytes have already been
 | ||||||
|  | 	 * filled, so any remainder when n drops below 32 can be | ||||||
|  | 	 * safely ignored. */ | ||||||
|  | 
 | ||||||
|  | 	u64 c64 = c32 | ((u64)c32 << 32); | ||||||
|  | 	for (; n >= 32; n-=32, s+=32) { | ||||||
|  | 		*(u64 *)(s+0) = c64; | ||||||
|  | 		*(u64 *)(s+8) = c64; | ||||||
|  | 		*(u64 *)(s+16) = c64; | ||||||
|  | 		*(u64 *)(s+24) = c64; | ||||||
|  | 	} | ||||||
|  | #else | ||||||
|  | 	/* Pure C fallback with no aliasing violations. */ | ||||||
|  | 	for (; n; n--, s++) *s = c; | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | 	return dest; | ||||||
|  | } | ||||||
							
								
								
									
										9
									
								
								musl.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								musl.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,9 @@ | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <stddef.h> | ||||||
|  | 
 | ||||||
|  | void *musl_memcpy(void *dst, const void *src, size_t len); | ||||||
|  | void *musl_memccpy(void *restrict dest, const void *restrict src, int c, size_t n); | ||||||
|  | void *musl_memmove(void *dst, const void *src, size_t len); | ||||||
|  | void *musl_memset(void *dst, int value, size_t len); | ||||||
|  | wchar_t *musl_wmemset(wchar_t *dst, wchar_t value, size_t len); | ||||||
							
								
								
									
										10
									
								
								random.c
									
										
									
									
									
								
							
							
						
						
									
										10
									
								
								random.c
									
										
									
									
									
								
							|  | @ -5,6 +5,10 @@ | ||||||
| #include "random.h" | #include "random.h" | ||||||
| #include "util.h" | #include "util.h" | ||||||
| 
 | 
 | ||||||
|  | #if CONFIG_BLOCK_OPS_CHECK_SIZE && !defined(HAS_ARM_MTE) | ||||||
|  | #include "musl.h" | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
| #include <sys/random.h> | #include <sys/random.h> | ||||||
| 
 | 
 | ||||||
| static void get_random_seed(void *buf, size_t size) { | static void get_random_seed(void *buf, size_t size) { | ||||||
|  | @ -65,7 +69,7 @@ void get_random_bytes(struct random_state *state, void *buf, size_t size) { | ||||||
| 
 | 
 | ||||||
|         size_t remaining = RANDOM_CACHE_SIZE - state->index; |         size_t remaining = RANDOM_CACHE_SIZE - state->index; | ||||||
|         size_t copy_size = min(size, remaining); |         size_t copy_size = min(size, remaining); | ||||||
|         memcpy(buf, state->cache + state->index, copy_size); |         h_memcpy_internal(buf, state->cache + state->index, copy_size); | ||||||
|         state->index += copy_size; |         state->index += copy_size; | ||||||
| 
 | 
 | ||||||
|         buf = (char *)buf + copy_size; |         buf = (char *)buf + copy_size; | ||||||
|  | @ -79,7 +83,7 @@ u16 get_random_u16(struct random_state *state) { | ||||||
|     if (remaining < sizeof(value)) { |     if (remaining < sizeof(value)) { | ||||||
|         refill(state); |         refill(state); | ||||||
|     } |     } | ||||||
|     memcpy(&value, state->cache + state->index, sizeof(value)); |     h_memcpy_internal(&value, state->cache + state->index, sizeof(value)); | ||||||
|     state->index += sizeof(value); |     state->index += sizeof(value); | ||||||
|     return value; |     return value; | ||||||
| } | } | ||||||
|  | @ -106,7 +110,7 @@ u64 get_random_u64(struct random_state *state) { | ||||||
|     if (remaining < sizeof(value)) { |     if (remaining < sizeof(value)) { | ||||||
|         refill(state); |         refill(state); | ||||||
|     } |     } | ||||||
|     memcpy(&value, state->cache + state->index, sizeof(value)); |     h_memcpy_internal(&value, state->cache + state->index, sizeof(value)); | ||||||
|     state->index += sizeof(value); |     state->index += sizeof(value); | ||||||
|     return value; |     return value; | ||||||
| } | } | ||||||
|  |  | ||||||
							
								
								
									
										6
									
								
								random.h
									
										
									
									
									
								
							
							
						
						
									
										6
									
								
								random.h
									
										
									
									
									
								
							|  | @ -22,4 +22,10 @@ u16 get_random_u16_uniform(struct random_state *state, u16 bound); | ||||||
| u64 get_random_u64(struct random_state *state); | u64 get_random_u64(struct random_state *state); | ||||||
| u64 get_random_u64_uniform(struct random_state *state, u64 bound); | u64 get_random_u64_uniform(struct random_state *state, u64 bound); | ||||||
| 
 | 
 | ||||||
|  | #if CONFIG_BLOCK_OPS_CHECK_SIZE && !defined(HAS_ARM_MTE) | ||||||
|  | #define h_memcpy_internal musl_memcpy | ||||||
|  | #else | ||||||
|  | #define h_memcpy_internal memcpy | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
							
								
								
									
										26
									
								
								test/.gitignore
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										26
									
								
								test/.gitignore
									
										
									
									
										vendored
									
									
								
							|  | @ -41,4 +41,30 @@ overflow_small_8_byte | ||||||
| uninitialized_read_large | uninitialized_read_large | ||||||
| uninitialized_read_small | uninitialized_read_small | ||||||
| realloc_init | realloc_init | ||||||
|  | memcpy_buffer_overflow | ||||||
|  | memcpy_read_overflow | ||||||
|  | memcpy_valid_same | ||||||
|  | memcpy_valid_mismatched | ||||||
|  | memccpy_buffer_overflow | ||||||
|  | memccpy_read_overflow | ||||||
|  | memccpy_valid_same | ||||||
|  | memccpy_valid_mismatched | ||||||
|  | memmove_buffer_overflow | ||||||
|  | memmove_read_overflow | ||||||
|  | memmove_valid_same | ||||||
|  | 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__/ | __pycache__/ | ||||||
|  |  | ||||||
|  | @ -67,7 +67,33 @@ EXECUTABLES := \ | ||||||
|     invalid_malloc_object_size_small \
 |     invalid_malloc_object_size_small \
 | ||||||
|     invalid_malloc_object_size_small_quarantine \
 |     invalid_malloc_object_size_small_quarantine \
 | ||||||
|     impossibly_large_malloc \
 |     impossibly_large_malloc \
 | ||||||
|     realloc_init |     realloc_init \
 | ||||||
|  |     memcpy_buffer_overflow \
 | ||||||
|  |     memcpy_read_overflow \
 | ||||||
|  |     memcpy_valid_same \
 | ||||||
|  |     memcpy_valid_mismatched \
 | ||||||
|  |     memccpy_buffer_overflow \
 | ||||||
|  |     memccpy_read_overflow \
 | ||||||
|  |     memccpy_valid_same \
 | ||||||
|  |     memccpy_valid_mismatched \
 | ||||||
|  |     memmove_buffer_overflow \
 | ||||||
|  |     memmove_read_overflow \
 | ||||||
|  |     memmove_valid_same \
 | ||||||
|  |     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 | ||||||
| 
 | 
 | ||||||
| all: $(EXECUTABLES) | all: $(EXECUTABLES) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										15
									
								
								test/memccpy_buffer_overflow.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								test/memccpy_buffer_overflow.c
									
										
									
									
									
										Normal 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(32); | ||||||
|  |     if (!firstbuffer && !secondbuffer) { | ||||||
|  |         return 1; | ||||||
|  |     } | ||||||
|  |     memset(secondbuffer, 'a', 32); | ||||||
|  |     memccpy(firstbuffer, secondbuffer, 'b', 32); | ||||||
|  |     return 1; | ||||||
|  | } | ||||||
							
								
								
									
										15
									
								
								test/memccpy_read_overflow.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								test/memccpy_read_overflow.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,15 @@ | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <string.h> | ||||||
|  | 
 | ||||||
|  | #include "test_util.h" | ||||||
|  | 
 | ||||||
|  | OPTNONE int main(void) { | ||||||
|  |     char *firstbuffer = malloc(32); | ||||||
|  |     char *secondbuffer = malloc(16); | ||||||
|  |     if (!firstbuffer && !secondbuffer) { | ||||||
|  |         return 1; | ||||||
|  |     } | ||||||
|  |     memset(secondbuffer, 'a', 16); | ||||||
|  |     memccpy(firstbuffer, secondbuffer, 'b', 32); | ||||||
|  |     return 1; | ||||||
|  | } | ||||||
							
								
								
									
										15
									
								
								test/memccpy_valid_mismatched.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								test/memccpy_valid_mismatched.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,15 @@ | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <string.h> | ||||||
|  | 
 | ||||||
|  | #include "test_util.h" | ||||||
|  | 
 | ||||||
|  | OPTNONE int main(void) { | ||||||
|  |     char *firstbuffer = malloc(32); | ||||||
|  |     char *secondbuffer = malloc(16); | ||||||
|  |     if (!firstbuffer && !secondbuffer) { | ||||||
|  |         return 1; | ||||||
|  |     } | ||||||
|  |     memset(secondbuffer, 'a', 16); | ||||||
|  |     memccpy(firstbuffer, secondbuffer, 'b', 16); | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
							
								
								
									
										15
									
								
								test/memccpy_valid_same.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								test/memccpy_valid_same.c
									
										
									
									
									
										Normal 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(16); | ||||||
|  |     if (!firstbuffer && !secondbuffer) { | ||||||
|  |         return 1; | ||||||
|  |     } | ||||||
|  |     memset(secondbuffer, 'a', 16); | ||||||
|  |     memccpy(firstbuffer, secondbuffer, 'b', 16); | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
							
								
								
									
										15
									
								
								test/memcpy_buffer_overflow.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								test/memcpy_buffer_overflow.c
									
										
									
									
									
										Normal 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(32); | ||||||
|  |     if (!firstbuffer && !secondbuffer) { | ||||||
|  |         return 1; | ||||||
|  |     } | ||||||
|  |     memset(secondbuffer, 'a', 32); | ||||||
|  |     memcpy(firstbuffer, secondbuffer, 32); | ||||||
|  |     return 1; | ||||||
|  | } | ||||||
							
								
								
									
										15
									
								
								test/memcpy_read_overflow.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								test/memcpy_read_overflow.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,15 @@ | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <string.h> | ||||||
|  | 
 | ||||||
|  | #include "test_util.h" | ||||||
|  | 
 | ||||||
|  | OPTNONE int main(void) { | ||||||
|  |     char *firstbuffer = malloc(32); | ||||||
|  |     char *secondbuffer = malloc(16); | ||||||
|  |     if (!firstbuffer && !secondbuffer) { | ||||||
|  |         return 1; | ||||||
|  |     } | ||||||
|  |     memset(secondbuffer, 'a', 16); | ||||||
|  |     memcpy(firstbuffer, secondbuffer, 32); | ||||||
|  |     return 1; | ||||||
|  | } | ||||||
							
								
								
									
										15
									
								
								test/memcpy_valid_mismatched.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								test/memcpy_valid_mismatched.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,15 @@ | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <string.h> | ||||||
|  | 
 | ||||||
|  | #include "test_util.h" | ||||||
|  | 
 | ||||||
|  | OPTNONE int main(void) { | ||||||
|  |     char *firstbuffer = malloc(32); | ||||||
|  |     char *secondbuffer = malloc(16); | ||||||
|  |     if (!firstbuffer && !secondbuffer) { | ||||||
|  |         return 1; | ||||||
|  |     } | ||||||
|  |     memset(secondbuffer, 'a', 16); | ||||||
|  |     memcpy(firstbuffer, secondbuffer, 16); | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
							
								
								
									
										15
									
								
								test/memcpy_valid_same.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								test/memcpy_valid_same.c
									
										
									
									
									
										Normal 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(16); | ||||||
|  |     if (!firstbuffer && !secondbuffer) { | ||||||
|  |         return 1; | ||||||
|  |     } | ||||||
|  |     memset(secondbuffer, 'a', 16); | ||||||
|  |     memcpy(firstbuffer, secondbuffer, 16); | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
							
								
								
									
										15
									
								
								test/memmove_buffer_overflow.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								test/memmove_buffer_overflow.c
									
										
									
									
									
										Normal 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(32); | ||||||
|  |     if (!firstbuffer && !secondbuffer) { | ||||||
|  |         return 1; | ||||||
|  |     } | ||||||
|  |     memset(secondbuffer, 'a', 32); | ||||||
|  |     memmove(firstbuffer, secondbuffer, 32); | ||||||
|  |     return 1; | ||||||
|  | } | ||||||
							
								
								
									
										15
									
								
								test/memmove_read_overflow.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								test/memmove_read_overflow.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,15 @@ | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <string.h> | ||||||
|  | 
 | ||||||
|  | #include "test_util.h" | ||||||
|  | 
 | ||||||
|  | OPTNONE int main(void) { | ||||||
|  |     char *firstbuffer = malloc(32); | ||||||
|  |     char *secondbuffer = malloc(16); | ||||||
|  |     if (!firstbuffer && !secondbuffer) { | ||||||
|  |         return 1; | ||||||
|  |     } | ||||||
|  |     memset(secondbuffer, 'a', 16); | ||||||
|  |     memmove(firstbuffer, secondbuffer, 32); | ||||||
|  |     return 1; | ||||||
|  | } | ||||||
							
								
								
									
										15
									
								
								test/memmove_valid_mismatched.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								test/memmove_valid_mismatched.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,15 @@ | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <string.h> | ||||||
|  | 
 | ||||||
|  | #include "test_util.h" | ||||||
|  | 
 | ||||||
|  | OPTNONE int main(void) { | ||||||
|  |     char *firstbuffer = malloc(32); | ||||||
|  |     char *secondbuffer = malloc(16); | ||||||
|  |     if (!firstbuffer && !secondbuffer) { | ||||||
|  |         return 1; | ||||||
|  |     } | ||||||
|  |     memset(secondbuffer, 'a', 16); | ||||||
|  |     memmove(firstbuffer, secondbuffer, 16); | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
							
								
								
									
										15
									
								
								test/memmove_valid_same.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								test/memmove_valid_same.c
									
										
									
									
									
										Normal 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(16); | ||||||
|  |     if (!firstbuffer && !secondbuffer) { | ||||||
|  |         return 1; | ||||||
|  |     } | ||||||
|  |     memset(secondbuffer, 'a', 16); | ||||||
|  |     memmove(firstbuffer, secondbuffer, 16); | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
							
								
								
									
										13
									
								
								test/memset_buffer_overflow.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								test/memset_buffer_overflow.c
									
										
									
									
									
										Normal 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; | ||||||
|  | } | ||||||
							
								
								
									
										13
									
								
								test/memset_valid_mismatched.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								test/memset_valid_mismatched.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,13 @@ | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <string.h> | ||||||
|  | 
 | ||||||
|  | #include "test_util.h" | ||||||
|  | 
 | ||||||
|  | OPTNONE int main(void) { | ||||||
|  |     char *buffer = malloc(32); | ||||||
|  |     if (!buffer) { | ||||||
|  |         return 1; | ||||||
|  |     } | ||||||
|  |     memset(buffer, 'a', 16); | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
							
								
								
									
										13
									
								
								test/memset_valid_same.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								test/memset_valid_same.c
									
										
									
									
									
										Normal 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; | ||||||
|  | } | ||||||
							
								
								
									
										155
									
								
								test/test_smc.py
									
										
									
									
									
								
							
							
						
						
									
										155
									
								
								test/test_smc.py
									
										
									
									
									
								
							|  | @ -238,5 +238,160 @@ class TestSimpleMemoryCorruption(unittest.TestCase): | ||||||
|             "realloc_init") |             "realloc_init") | ||||||
|         self.assertEqual(returncode, 0) |         self.assertEqual(returncode, 0) | ||||||
| 
 | 
 | ||||||
|  |     #def test_memcpy_buffer_overflow(self): | ||||||
|  |     #    _stdout, stderr, returncode = self.run_test( | ||||||
|  |     #        "memcpy_buffer_overflow") | ||||||
|  |     #    self.assertEqual(returncode, -6) | ||||||
|  |     #    self.assertEqual(stderr.decode( | ||||||
|  |     #        "utf-8"), "fatal allocator error: memcpy buffer overflow\n") | ||||||
|  | 
 | ||||||
|  |     #def test_memcpy_read_overflow(self): | ||||||
|  |     #    _stdout, stderr, returncode = self.run_test( | ||||||
|  |     #        "memcpy_read_overflow") | ||||||
|  |     #    self.assertEqual(returncode, -6) | ||||||
|  |     #    self.assertEqual(stderr.decode( | ||||||
|  |     #        "utf-8"), "fatal allocator error: memcpy read overflow\n") | ||||||
|  | 
 | ||||||
|  |     def test_memcpy_valid_same(self): | ||||||
|  |         _stdout, _stderr, returncode = self.run_test( | ||||||
|  |             "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_memccpy_buffer_overflow(self): | ||||||
|  |     #    _stdout, stderr, returncode = self.run_test( | ||||||
|  |     #        "memccpy_buffer_overflow") | ||||||
|  |     #    self.assertEqual(returncode, -6) | ||||||
|  |     #    self.assertEqual(stderr.decode( | ||||||
|  |     #        "utf-8"), "fatal allocator error: memccpy buffer overflow\n") | ||||||
|  | 
 | ||||||
|  |     #def test_memccpy_read_overflow(self): | ||||||
|  |     #    _stdout, stderr, returncode = self.run_test( | ||||||
|  |     #        "memccpy_read_overflow") | ||||||
|  |     #    self.assertEqual(returncode, -6) | ||||||
|  |     #    self.assertEqual(stderr.decode( | ||||||
|  |     #        "utf-8"), "fatal allocator error: memccpy read overflow\n") | ||||||
|  | 
 | ||||||
|  |     def test_memccpy_valid_same(self): | ||||||
|  |         _stdout, _stderr, returncode = self.run_test( | ||||||
|  |             "memccpy_valid_same") | ||||||
|  |         self.assertEqual(returncode, 0) | ||||||
|  | 
 | ||||||
|  |     def test_memccpy_valid_mismatched(self): | ||||||
|  |         _stdout, _stderr, returncode = self.run_test( | ||||||
|  |             "memccpy_valid_mismatched") | ||||||
|  |         self.assertEqual(returncode, 0) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     #def test_memmove_buffer_overflow(self): | ||||||
|  |     #    _stdout, stderr, returncode = self.run_test( | ||||||
|  |     #        "memmove_buffer_overflow") | ||||||
|  |     #    self.assertEqual(returncode, -6) | ||||||
|  |     #    self.assertEqual(stderr.decode( | ||||||
|  |     #        "utf-8"), "fatal allocator error: memmove buffer overflow\n") | ||||||
|  | 
 | ||||||
|  |     #def test_memmove_read_overflow(self): | ||||||
|  |     #    _stdout, stderr, returncode = self.run_test( | ||||||
|  |     #        "memmove_read_overflow") | ||||||
|  |     #    self.assertEqual(returncode, -6) | ||||||
|  |     #    self.assertEqual(stderr.decode( | ||||||
|  |     #        "utf-8"), "fatal allocator error: memmove read overflow\n") | ||||||
|  | 
 | ||||||
|  |     def test_memmove_valid_same(self): | ||||||
|  |         _stdout, _stderr, returncode = self.run_test( | ||||||
|  |             "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_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") | ||||||
|  |         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__': | if __name__ == '__main__': | ||||||
|     unittest.main() |     unittest.main() | ||||||
|  |  | ||||||
							
								
								
									
										15
									
								
								test/wmemcpy_buffer_overflow.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								test/wmemcpy_buffer_overflow.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,15 @@ | ||||||
|  | #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; | ||||||
|  | } | ||||||
							
								
								
									
										15
									
								
								test/wmemcpy_read_overflow.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								test/wmemcpy_read_overflow.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,15 @@ | ||||||
|  | #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; | ||||||
|  | } | ||||||
							
								
								
									
										15
									
								
								test/wmemcpy_valid_mismatched.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								test/wmemcpy_valid_mismatched.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,15 @@ | ||||||
|  | #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; | ||||||
|  | } | ||||||
							
								
								
									
										15
									
								
								test/wmemcpy_valid_same.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								test/wmemcpy_valid_same.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,15 @@ | ||||||
|  | #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; | ||||||
|  | } | ||||||
							
								
								
									
										15
									
								
								test/wmemmove_buffer_overflow.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								test/wmemmove_buffer_overflow.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,15 @@ | ||||||
|  | #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; | ||||||
|  | } | ||||||
							
								
								
									
										15
									
								
								test/wmemmove_read_overflow.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								test/wmemmove_read_overflow.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,15 @@ | ||||||
|  | #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; | ||||||
|  | } | ||||||
							
								
								
									
										15
									
								
								test/wmemmove_valid_mismatched.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								test/wmemmove_valid_mismatched.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,15 @@ | ||||||
|  | #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; | ||||||
|  | } | ||||||
							
								
								
									
										15
									
								
								test/wmemmove_valid_same.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								test/wmemmove_valid_same.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,15 @@ | ||||||
|  | #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; | ||||||
|  | } | ||||||
							
								
								
									
										13
									
								
								test/wmemset_buffer_overflow.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								test/wmemset_buffer_overflow.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,13 @@ | ||||||
|  | #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; | ||||||
|  | } | ||||||
							
								
								
									
										13
									
								
								test/wmemset_valid_mismatched.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								test/wmemset_valid_mismatched.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,13 @@ | ||||||
|  | #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; | ||||||
|  | } | ||||||
							
								
								
									
										13
									
								
								test/wmemset_valid_same.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								test/wmemset_valid_same.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,13 @@ | ||||||
|  | #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
									
								
								wmemset.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								wmemset.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_wmemset(wchar_t *d, wchar_t c, size_t n) | ||||||
|  | { | ||||||
|  | 	wchar_t *ret = d; | ||||||
|  | 	while (n--) *d++ = c; | ||||||
|  | 	return ret; | ||||||
|  | } | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue