Add CMOCK_MEMCPY and CMOCK_MEMSET and refactor internal handling of pointer data to fix #11 & #244.

This commit is contained in:
Mark VanderVoord
2026-06-26 11:56:07 -04:00
parent d20d18e75c
commit 92debabbf0
5 changed files with 46 additions and 8 deletions
+23
View File
@@ -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 `<string.h>`. 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 `<string.h>`. 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 `<string.h>` at all.
Other Tips
==========
@@ -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
+7 -4
View File
@@ -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;
+12
View File
@@ -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 <string.h>
#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)
@@ -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"