diff --git a/docs/CMock_Summary.md b/docs/CMock_Summary.md index 28e2a48..b78327d 100644 --- a/docs/CMock_Summary.md +++ b/docs/CMock_Summary.md @@ -881,6 +881,29 @@ based on other settings, particularly Unity's settings. This needs to be something big enough to point anywhere in Cmock's memory space... usually it's a size_t. +* `CMOCK_MEMCPY` + The memory-copy function used by CMock's internals and the generated mocks. + It defaults to `memcpy` from ``. Override alongside `CMOCK_MEMSET` + to supply a custom implementation on targets where the standard library is + unavailable or undesirable: + + ```c + #define CMOCK_MEMCPY(dst, src, size) my_memcpy(dst, src, size) + ``` + +* `CMOCK_MEMSET` + The memory-set function used by CMock's internals to zero-initialize + allocated blocks. It defaults to `memset` from ``. Override + alongside `CMOCK_MEMCPY` to keep CMock fully independent of the standard + library: + + ```c + #define CMOCK_MEMSET(dst, val, size) my_memset(dst, val, size) + ``` + + If both `CMOCK_MEMCPY` and `CMOCK_MEMSET` are defined before including + `cmock.h`, CMock will not pull in `` at all. + Other Tips ========== diff --git a/lib/cmock_generator_plugin_return_thru_ptr.rb b/lib/cmock_generator_plugin_return_thru_ptr.rb index b3bb08f..a821826 100644 --- a/lib/cmock_generator_plugin_return_thru_ptr.rb +++ b/lib/cmock_generator_plugin_return_thru_ptr.rb @@ -83,7 +83,7 @@ class CMockGeneratorPluginReturnThruPtr lines << " cmock_call_instance->ReturnThruPtr_#{arg_name}_Used)\n" lines << " {\n" lines << " UNITY_TEST_ASSERT_NOT_NULL(#{arg_name}, cmock_line, CMockStringPtrIsNULL);\n" - lines << " memcpy((void*)#{arg_name}, (const void*)cmock_call_instance->ReturnThruPtr_#{arg_name}_Val,\n" + lines << " CMOCK_MEMCPY((void*)#{arg_name}, (const void*)cmock_call_instance->ReturnThruPtr_#{arg_name}_Val,\n" lines << " cmock_call_instance->ReturnThruPtr_#{arg_name}_Size);\n" lines << " }\n" end @@ -136,7 +136,7 @@ class CMockGeneratorPluginReturnThruPtr lines << " if (cmock_call_instance->ReturnThruPtr_#{arg_name}_Used)\n" lines << " {\n" lines << " UNITY_TEST_ASSERT_NOT_NULL(#{arg_name}, cmock_line, CMockStringPtrIsNULL);\n" - lines << " memcpy((void*)#{arg_name}, (const void*)cmock_call_instance->ReturnThruPtr_#{arg_name}_Val,\n" + lines << " CMOCK_MEMCPY((void*)#{arg_name}, (const void*)cmock_call_instance->ReturnThruPtr_#{arg_name}_Val,\n" lines << " cmock_call_instance->ReturnThruPtr_#{arg_name}_Size);\n" lines << " }\n" end diff --git a/src/cmock.c b/src/cmock.c index 28f276f..1cc1725 100644 --- a/src/cmock.c +++ b/src/cmock.c @@ -68,7 +68,7 @@ CMOCK_MEM_INDEX_TYPE CMock_Guts_MemNew(CMOCK_MEM_INDEX_TYPE size) /* determine where we're putting this new block, and init its pointer to be the end of the line */ index = CMock_Guts_FreePtr + CMOCK_MEM_INDEX_SIZE; - *(CMOCK_MEM_INDEX_TYPE*)(&CMock_Guts_Buffer[CMock_Guts_FreePtr]) = CMOCK_GUTS_NONE; + CMOCK_MEMSET(&CMock_Guts_Buffer[CMock_Guts_FreePtr], 0, CMOCK_MEM_INDEX_SIZE); CMock_Guts_FreePtr += size; return index; @@ -108,7 +108,7 @@ CMOCK_MEM_INDEX_TYPE CMock_Guts_MemChain(CMOCK_MEM_INDEX_TYPE root_index, CMOCK_ next = root; do { - index = *(CMOCK_MEM_INDEX_TYPE*)((CMOCK_MEM_PTR_AS_INT)next - CMOCK_MEM_INDEX_SIZE); + CMOCK_MEMCPY(&index, (unsigned char*)next - CMOCK_MEM_INDEX_SIZE, sizeof(index)); if (index >= CMock_Guts_FreePtr) { return CMOCK_GUTS_NONE; @@ -119,7 +119,10 @@ CMOCK_MEM_INDEX_TYPE CMock_Guts_MemChain(CMOCK_MEM_INDEX_TYPE root_index, CMOCK_ } } while (index > 0); - *(CMOCK_MEM_INDEX_TYPE*)((CMOCK_MEM_PTR_AS_INT)next - CMOCK_MEM_INDEX_SIZE) = (CMOCK_MEM_INDEX_TYPE)((CMOCK_MEM_PTR_AS_INT)obj - (CMOCK_MEM_PTR_AS_INT)CMock_Guts_Buffer); + { + CMOCK_MEM_INDEX_TYPE tmp = (CMOCK_MEM_INDEX_TYPE)((unsigned char*)obj - CMock_Guts_Buffer); + CMOCK_MEMCPY((unsigned char*)next - CMOCK_MEM_INDEX_SIZE, &tmp, sizeof(tmp)); + } return root_index; } } @@ -141,7 +144,7 @@ CMOCK_MEM_INDEX_TYPE CMock_Guts_MemNext(CMOCK_MEM_INDEX_TYPE previous_item_index /* if the pointer is good, then use it to look up the next index * (we know the first element always goes in zero, so NEXT must always be > 1) */ - index = *(CMOCK_MEM_INDEX_TYPE*)((CMOCK_MEM_PTR_AS_INT)previous_item - CMOCK_MEM_INDEX_SIZE); + CMOCK_MEMCPY(&index, (unsigned char*)previous_item - CMOCK_MEM_INDEX_SIZE, sizeof(index)); if ((index > 1) && (index < CMock_Guts_FreePtr)) { return index; diff --git a/src/cmock_internals.h b/src/cmock_internals.h index 3877296..b3d23f5 100644 --- a/src/cmock_internals.h +++ b/src/cmock_internals.h @@ -83,6 +83,18 @@ extern const char* CMockStringMismatch; #define CMOCK_MEM_SIZE (32768) #endif +/* memory copy/set functions used by CMock internals and generated mocks. + * Override to use custom implementations on targets without standard libc. */ +#if !defined(CMOCK_MEMCPY) || !defined(CMOCK_MEMSET) + #include + #ifndef CMOCK_MEMCPY + #define CMOCK_MEMCPY(a, b, c) memcpy(a, b, c) + #endif + #ifndef CMOCK_MEMSET + #define CMOCK_MEMSET(a, b, c) memset(a, b, c) + #endif +#endif + /* automatically calculated defs for easier reading */ #define CMOCK_MEM_ALIGN_SIZE (CMOCK_MEM_INDEX_TYPE)(1u << CMOCK_MEM_ALIGN) #define CMOCK_MEM_ALIGN_MASK (CMOCK_MEM_INDEX_TYPE)(CMOCK_MEM_ALIGN_SIZE - 1) diff --git a/test/unit/cmock_generator_plugin_return_thru_ptr_test.rb b/test/unit/cmock_generator_plugin_return_thru_ptr_test.rb index 021eb5c..d38cde2 100644 --- a/test/unit/cmock_generator_plugin_return_thru_ptr_test.rb +++ b/test/unit/cmock_generator_plugin_return_thru_ptr_test.rb @@ -193,13 +193,13 @@ describe CMockGeneratorPluginReturnThruPtr, "Verify CMockGeneratorPluginReturnTh " if (cmock_call_instance->ReturnThruPtr_tofu_Used)\n" + " {\n" + " UNITY_TEST_ASSERT_NOT_NULL(tofu, cmock_line, CMockStringPtrIsNULL);\n" + - " memcpy((void*)tofu, (const void*)cmock_call_instance->ReturnThruPtr_tofu_Val,\n" + + " CMOCK_MEMCPY((void*)tofu, (const void*)cmock_call_instance->ReturnThruPtr_tofu_Val,\n" + " cmock_call_instance->ReturnThruPtr_tofu_Size);\n" + " }\n" + " if (cmock_call_instance->ReturnThruPtr_bean_buffer_Used)\n" + " {\n" + " UNITY_TEST_ASSERT_NOT_NULL(bean_buffer, cmock_line, CMockStringPtrIsNULL);\n" + - " memcpy((void*)bean_buffer, (const void*)cmock_call_instance->ReturnThruPtr_bean_buffer_Val,\n" + + " CMOCK_MEMCPY((void*)bean_buffer, (const void*)cmock_call_instance->ReturnThruPtr_bean_buffer_Val,\n" + " cmock_call_instance->ReturnThruPtr_bean_buffer_Size);\n" + " }\n"