Skip to content

Commit a438d73

Browse files
Merge pull request #12 from dreamer-coding/main
Memory extend patch
2 parents 8df7914 + 96ac3cb commit a438d73

File tree

4 files changed

+373
-6
lines changed

4 files changed

+373
-6
lines changed

code/logic/fossil/sys/memory.h

Lines changed: 141 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,79 @@ fossil_sys_memory_t fossil_sys_memory_resize(fossil_sys_memory_t ptr, size_t old
154154
*/
155155
bool fossil_sys_memory_is_valid(const fossil_sys_memory_t ptr);
156156

157+
/**
158+
* @brief Fill memory with a repeating pattern.
159+
*
160+
* Useful for debugging or initializing buffers to known patterns.
161+
*
162+
* @param ptr A pointer to the memory to fill.
163+
* @param pattern Pointer to the pattern to repeat.
164+
* @param pattern_size Size of the pattern in bytes.
165+
* @param total_size Total number of bytes to fill.
166+
* @return A pointer to the memory.
167+
*/
168+
fossil_sys_memory_t fossil_sys_memory_fill(fossil_sys_memory_t ptr,
169+
const void *pattern,
170+
size_t pattern_size,
171+
size_t total_size);
172+
173+
/**
174+
* @brief Securely zero memory.
175+
*
176+
* Unlike fossil_sys_memory_zero, this function prevents
177+
* the compiler from optimizing out the zeroing operation.
178+
*
179+
* @param ptr A pointer to the memory to zero.
180+
* @param size The size of the memory to zero.
181+
*/
182+
void fossil_sys_memory_secure_zero(fossil_sys_memory_t ptr, size_t size);
183+
184+
/**
185+
* @brief Swap contents of two memory regions.
186+
*
187+
* Swaps memory between two buffers of the same size.
188+
*
189+
* @param a Pointer to the first buffer.
190+
* @param b Pointer to the second buffer.
191+
* @param size Number of bytes to swap.
192+
* @throws Error message and exits if pointers are NULL or sizes are zero.
193+
*/
194+
void fossil_sys_memory_swap(fossil_sys_memory_t a, fossil_sys_memory_t b, size_t size);
195+
196+
/**
197+
* @brief Search memory for a byte value.
198+
*
199+
* Scans memory for the first occurrence of the given byte.
200+
*
201+
* @param ptr Pointer to the memory to search.
202+
* @param value Byte value to search for.
203+
* @param size Size of the memory to search.
204+
* @return Pointer to the first occurrence of the value, or NULL if not found.
205+
*/
206+
void *fossil_sys_memory_find(const fossil_sys_memory_t ptr, uint8_t value, size_t size);
207+
208+
/**
209+
* @brief Duplicate a NULL-terminated string using memory API.
210+
*
211+
* Similar to strdup, but uses fossil_sys_memory_alloc under the hood.
212+
*
213+
* @param str The string to duplicate.
214+
* @return A pointer to the duplicated string.
215+
* @throws Error message and exits if allocation fails or str is NULL.
216+
*/
217+
char *fossil_sys_memory_strdup(const char *str);
218+
219+
/**
220+
* @brief Get memory usage statistics.
221+
*
222+
* Returns current allocation count and optionally total allocated bytes.
223+
* (Useful for leak detection in debug builds.)
224+
*
225+
* @param out_allocs Pointer to receive allocation count (can be NULL).
226+
* @param out_bytes Pointer to receive total allocated bytes (can be NULL).
227+
*/
228+
void fossil_sys_memory_stats(size_t *out_allocs, size_t *out_bytes);
229+
157230
#ifdef __cplusplus
158231
}
159232

@@ -313,9 +386,76 @@ namespace fossil {
313386
* @param ptr A pointer to the memory.
314387
* @return true if the memory is valid, false otherwise.
315388
*/
316-
static bool isValid(const fossil_sys_memory_t ptr) {
389+
static bool is_valid(const fossil_sys_memory_t ptr) {
317390
return fossil_sys_memory_is_valid(ptr);
318391
}
392+
393+
/**
394+
* Fill memory with a repeating pattern.
395+
*
396+
* @param ptr A pointer to the memory to fill.
397+
* @param pattern Pointer to the pattern to repeat.
398+
* @param pattern_size Size of the pattern in bytes.
399+
* @param total_size Total number of bytes to fill.
400+
* @return A pointer to the memory.
401+
*/
402+
static fossil_sys_memory_t fill(fossil_sys_memory_t ptr, const void *pattern, size_t pattern_size, size_t total_size) {
403+
return fossil_sys_memory_fill(ptr, pattern, pattern_size, total_size);
404+
}
405+
406+
/**
407+
* Securely zero memory.
408+
*
409+
* @param ptr A pointer to the memory to zero.
410+
* @param size The size of the memory to zero.
411+
*/
412+
static void secure_zero(fossil_sys_memory_t ptr, size_t size) {
413+
fossil_sys_memory_secure_zero(ptr, size);
414+
}
415+
416+
/**
417+
* Swap contents of two memory regions.
418+
*
419+
* @param a Pointer to the first buffer.
420+
* @param b Pointer to the second buffer.
421+
* @param size Number of bytes to swap.
422+
*/
423+
static void swap(fossil_sys_memory_t a, fossil_sys_memory_t b, size_t size) {
424+
fossil_sys_memory_swap(a, b, size);
425+
}
426+
427+
/**
428+
* Search memory for a byte value.
429+
*
430+
* @param ptr Pointer to the memory to search.
431+
* @param value Byte value to search for.
432+
* @param size Size of the memory to search.
433+
* @return Pointer to the first occurrence of the value, or NULL if not found.
434+
*/
435+
static void *find(const fossil_sys_memory_t ptr, uint8_t value, size_t size) {
436+
return fossil_sys_memory_find(ptr, value, size);
437+
}
438+
439+
/**
440+
* Duplicate a NULL-terminated string using memory API.
441+
*
442+
* @param str The string to duplicate.
443+
* @return A pointer to the duplicated string.
444+
*/
445+
static char *strdup(const char *str) {
446+
return fossil_sys_memory_strdup(str);
447+
}
448+
449+
/**
450+
* Get memory usage statistics.
451+
*
452+
* @param out_allocs Pointer to receive allocation count (can be NULL).
453+
* @param out_bytes Pointer to receive total allocated bytes (can be NULL).
454+
*/
455+
static void stats(size_t *out_allocs, size_t *out_bytes) {
456+
fossil_sys_memory_stats(out_allocs, out_bytes);
457+
}
458+
319459
};
320460

321461
}

code/logic/memory.c

Lines changed: 96 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,20 @@
1212
* -----------------------------------------------------------------------------
1313
*/
1414
#include "fossil/sys/memory.h"
15-
#include <stdlib.h>
15+
#include <stdlib.h> // Needed for posix_memalign
1616
#include <string.h>
1717
#include <stdio.h>
1818

19+
// Internal counters for memory stats (optional, for debug)
20+
static size_t g_alloc_count = 0;
21+
static size_t g_alloc_bytes = 0;
22+
23+
24+
// ----------------------- Aligned Memory -----------------------
1925

2026
fossil_sys_memory_t fossil_sys_memory_alloc(size_t size) {
2127
if (size == 0) {
22-
fprintf(stderr, "Error: fossil_sys_memory_alloc() - Cannot allocate zero bytes.\n");
28+
fprintf(stderr, "Error: fossil_sys_memory_alloc() - Cannot allocate zero bytes.\n");
2329
return NULL;
2430
}
2531

@@ -185,3 +191,91 @@ bool fossil_sys_memory_is_valid(const fossil_sys_memory_t ptr) {
185191
// Optional: Add more validation logic if needed, but normally you'd rely on the caller to manage validity.
186192
return true;
187193
}
194+
195+
// ----------------------- Memory Fill -----------------------
196+
197+
fossil_sys_memory_t fossil_sys_memory_fill(fossil_sys_memory_t ptr,
198+
const void *pattern,
199+
size_t pattern_size,
200+
size_t total_size) {
201+
if (!ptr || !pattern || pattern_size == 0 || total_size == 0) {
202+
fprintf(stderr, "Error: fossil_sys_memory_fill() - Invalid arguments.\n");
203+
return NULL;
204+
}
205+
206+
uint8_t *dst = (uint8_t *)ptr;
207+
size_t offset = 0;
208+
while (offset + pattern_size <= total_size) {
209+
memcpy(dst + offset, pattern, pattern_size);
210+
offset += pattern_size;
211+
}
212+
// Copy remaining bytes if any
213+
if (offset < total_size) {
214+
memcpy(dst + offset, pattern, total_size - offset);
215+
}
216+
return ptr;
217+
}
218+
219+
// ----------------------- Secure Zero -----------------------
220+
221+
void fossil_sys_memory_secure_zero(fossil_sys_memory_t ptr, size_t size) {
222+
if (!ptr) return;
223+
#if defined(_MSC_VER)
224+
SecureZeroMemory(ptr, size);
225+
#elif defined(__GNUC__) || defined(__clang__)
226+
volatile uint8_t *p = (volatile uint8_t *)ptr;
227+
while (size--) *p++ = 0;
228+
#else
229+
memset(ptr, 0, size); // Fallback (not guaranteed secure)
230+
#endif
231+
}
232+
233+
// ----------------------- Swap Memory -----------------------
234+
235+
void fossil_sys_memory_swap(fossil_sys_memory_t a, fossil_sys_memory_t b, size_t size) {
236+
if (!a || !b || size == 0) {
237+
fprintf(stderr, "Error: fossil_sys_memory_swap() - Invalid arguments.\n");
238+
return;
239+
}
240+
241+
uint8_t *pa = (uint8_t *)a;
242+
uint8_t *pb = (uint8_t *)b;
243+
for (size_t i = 0; i < size; i++) {
244+
uint8_t tmp = pa[i];
245+
pa[i] = pb[i];
246+
pb[i] = tmp;
247+
}
248+
}
249+
250+
// ----------------------- Find Memory -----------------------
251+
252+
void *fossil_sys_memory_find(const fossil_sys_memory_t ptr, uint8_t value, size_t size) {
253+
if (!ptr || size == 0) return NULL;
254+
255+
uint8_t *p = (uint8_t *)ptr;
256+
for (size_t i = 0; i < size; i++) {
257+
if (p[i] == value) return p + i;
258+
}
259+
return NULL;
260+
}
261+
262+
// ----------------------- strdup -----------------------
263+
264+
char *fossil_sys_memory_strdup(const char *str) {
265+
if (!str) {
266+
fprintf(stderr, "Error: fossil_sys_memory_strdup() - NULL pointer passed.\n");
267+
return NULL;
268+
}
269+
270+
size_t len = strlen(str) + 1;
271+
char *copy = (char *)fossil_sys_memory_alloc(len);
272+
memcpy(copy, str, len);
273+
return copy;
274+
}
275+
276+
// ----------------------- Memory Stats -----------------------
277+
278+
void fossil_sys_memory_stats(size_t *out_allocs, size_t *out_bytes) {
279+
if (out_allocs) *out_allocs = g_alloc_count;
280+
if (out_bytes) *out_bytes = g_alloc_bytes;
281+
}

code/tests/cases/test_memory.c

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,57 @@ FOSSIL_TEST(c_test_memory_init) {
168168
fossil_sys_memory_free(ptr); // Cleanup
169169
}
170170

171+
FOSSIL_TEST(c_test_memory_fill_pattern) {
172+
size_t size = 16;
173+
uint8_t pattern[2] = {0xAB, 0xCD};
174+
fossil_sys_memory_t ptr = fossil_sys_memory_alloc(size);
175+
ASSUME_NOT_CNULL(ptr);
176+
177+
fossil_sys_memory_fill(ptr, pattern, sizeof(pattern), size);
178+
for (size_t i = 0; i < size; i += 2) {
179+
ASSUME_ITS_TRUE(((uint8_t*)ptr)[i] == 0xAB);
180+
ASSUME_ITS_TRUE(((uint8_t*)ptr)[i+1] == 0xCD);
181+
}
182+
fossil_sys_memory_free(ptr);
183+
}
184+
185+
FOSSIL_TEST(c_test_memory_secure_zero) {
186+
size_t size = 8;
187+
fossil_sys_memory_t ptr = fossil_sys_memory_alloc(size);
188+
ASSUME_NOT_CNULL(ptr);
189+
fossil_sys_memory_set(ptr, 0xFF, size);
190+
fossil_sys_memory_secure_zero(ptr, size);
191+
for (size_t i = 0; i < size; ++i) {
192+
ASSUME_ITS_TRUE(((uint8_t*)ptr)[i] == 0);
193+
}
194+
fossil_sys_memory_free(ptr);
195+
}
196+
197+
FOSSIL_TEST(c_test_memory_swap) {
198+
size_t size = 4;
199+
uint8_t a[4] = {1, 2, 3, 4};
200+
uint8_t b[4] = {5, 6, 7, 8};
201+
fossil_sys_memory_swap(a, b, size);
202+
ASSUME_ITS_TRUE(a[0] == 5 && a[1] == 6 && a[2] == 7 && a[3] == 8);
203+
ASSUME_ITS_TRUE(b[0] == 1 && b[1] == 2 && b[2] == 3 && b[3] == 4);
204+
}
205+
206+
FOSSIL_TEST(c_test_memory_find) {
207+
uint8_t buf[8] = {0, 1, 2, 3, 4, 5, 6, 7};
208+
void *found = fossil_sys_memory_find(buf, 4, 8);
209+
ASSUME_ITS_TRUE(found == &buf[4]);
210+
found = fossil_sys_memory_find(buf, 9, 8);
211+
ASSUME_ITS_TRUE(found == NULL);
212+
}
213+
214+
FOSSIL_TEST(c_test_memory_strdup) {
215+
const char *src = "fossil";
216+
char *dup = fossil_sys_memory_strdup(src);
217+
ASSUME_NOT_CNULL(dup);
218+
ASSUME_ITS_TRUE(strcmp(src, dup) == 0);
219+
fossil_sys_memory_free(dup);
220+
}
221+
171222
// * * * * * * * * * * * * * * * * * * * * * * * *
172223
// * Fossil Logic Test Pool
173224
// * * * * * * * * * * * * * * * * * * * * * * * *
@@ -183,6 +234,11 @@ FOSSIL_TEST_GROUP(c_memory_tests) {
183234
FOSSIL_TEST_ADD(c_memory_suite, c_test_memory_is_valid);
184235
FOSSIL_TEST_ADD(c_memory_suite, c_test_memory_calloc);
185236
FOSSIL_TEST_ADD(c_memory_suite, c_test_memory_init);
237+
FOSSIL_TEST_ADD(c_memory_suite, c_test_memory_fill_pattern);
238+
FOSSIL_TEST_ADD(c_memory_suite, c_test_memory_secure_zero);
239+
FOSSIL_TEST_ADD(c_memory_suite, c_test_memory_swap);
240+
FOSSIL_TEST_ADD(c_memory_suite, c_test_memory_find);
241+
FOSSIL_TEST_ADD(c_memory_suite, c_test_memory_strdup);
186242

187243
FOSSIL_TEST_REGISTER(c_memory_suite);
188244
}

0 commit comments

Comments
 (0)