Skip to content

Commit ca9b9a2

Browse files
committed
refactor: fix safety guards, const correctness, and alignment validation
- Fix potential out-of-bounds memory write in `estack_free_to_marker` under CONTRACT release builds by adding an unconditional guard. - Fix const-correctness of `estack_print` by removing `const` from the parameter since it temporarily mutates the stack. - Add compile-time static assertions to validate custom `ESTACK_MIN_ALIGNMENT` and `ESTACK_DEFAULT_HEADER_ALIGNMENT` (power-of-two and minimum size checks). - Restructure `ESTACK_MIN_ALIGNMENT` preprocessor logic to ensure it behaves correctly when `ESTACK_NO_AUTO_ALIGN` is defined. - Add warnings in configuration comments regarding potential alignment crashes on strict-alignment systems.
1 parent 38ff485 commit ca9b9a2

1 file changed

Lines changed: 17 additions & 6 deletions

File tree

easy_stack.h

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@
5858

5959
#define ESTACK_VERSION_MAJOR 1
6060
#define ESTACK_VERSION_MINOR 2
61-
#define ESTACK_VERSION_PATCH 0
61+
#define ESTACK_VERSION_PATCH 2
6262

6363
#define ESTACK_VERSION (ESTACK_VERSION_MAJOR * 10000 + ESTACK_VERSION_MINOR * 100 + ESTACK_VERSION_PATCH)
6464

@@ -87,8 +87,8 @@
8787
* #define ESTACK_POISON_BYTE 0xDD // Custom byte pattern for freed memory
8888
*
8989
* ALIGNMENT & OPTIMIZATION:
90-
* #define ESTACK_NO_AUTO_ALIGN // Disable user payload alignment (saves MCU RAM)
91-
* #define ESTACK_NO_ALIGN_HEADER // Disable EStack header alignment (saves MCU RAM)
90+
* #define ESTACK_NO_AUTO_ALIGN // Disable user payload alignment (saves MCU RAM) WILL CRASH ON SYSTEMS WITH STRICT ALIGNMENT REQUIREMENTS.
91+
* #define ESTACK_NO_ALIGN_HEADER // Disable EStack header alignment (saves MCU RAM) WILL CRASH ON SYSTEMS WITH STRICT ALIGNMENT REQUIREMENTS.
9292
* #define ESTACK_DEFAULT_HEADER_ALIGNMENT <val> // Override optimal header alignment (defaults to 64/32/word bytes)
9393
*
9494
* SYSTEM & LINKAGE:
@@ -101,6 +101,7 @@
101101
* TUNING:
102102
* #define ESTACK_MAGIC <value> // Custom magic number for stack validation
103103
* #define ESTACK_MIN_BUFFER_SIZE <value> // Override minimum usable payload capacity
104+
* #define ESTACK_MIN_ALIGNMENT <value> // Override minimum payload alignment (must be power of two)
104105
* ============================================================================
105106
*/
106107

@@ -401,6 +402,7 @@ ESTACK_STATIC_ASSERT((ESTACK_POISON_BYTE >= 0x00) && (ESTACK_POISON_BYTE <= 0xFF
401402
# endif
402403
#endif
403404
ESTACK_STATIC_ASSERT((ESTACK_MAGIC != 0), "ESTACK_MAGIC must be a non-zero value to ensure effective validation.");
405+
ESTACK_STATIC_ASSERT(ESTACK_MAGIC <= UINTPTR_MAX, "ESTACK_MAGIC exceeds the maximum value representable by uintptr_t");
404406

405407
/*
406408
* Configuration: Minimum Alignment Limit
@@ -412,8 +414,11 @@ ESTACK_STATIC_ASSERT((ESTACK_MAGIC != 0), "ESTACK_MAGIC must be a non-zero value
412414
#ifdef ESTACK_NO_AUTO_ALIGN
413415
# define ESTACK_MIN_ALIGNMENT ((size_t)1)
414416
#else
415-
# define ESTACK_MIN_ALIGNMENT ((size_t)sizeof(uintptr_t))
417+
# ifndef ESTACK_MIN_ALIGNMENT
418+
# define ESTACK_MIN_ALIGNMENT ((size_t)sizeof(uintptr_t))
419+
# endif
416420
#endif
421+
ESTACK_STATIC_ASSERT((ESTACK_MIN_ALIGNMENT & (ESTACK_MIN_ALIGNMENT - 1)) == 0, "ESTACK_MIN_ALIGNMENT must be a power of two");
417422

418423
/*
419424
* Configuration: Header Alignment Selection
@@ -446,6 +451,8 @@ ESTACK_STATIC_ASSERT((ESTACK_MAGIC != 0), "ESTACK_MAGIC must be a non-zero value
446451
# define ESTACK_DEFAULT_HEADER_ALIGNMENT ((size_t)sizeof(uintptr_t)) // Fallback to word alignment
447452
# endif
448453
# endif
454+
ESTACK_STATIC_ASSERT((ESTACK_DEFAULT_HEADER_ALIGNMENT & (ESTACK_DEFAULT_HEADER_ALIGNMENT - 1)) == 0, "ESTACK_DEFAULT_HEADER_ALIGNMENT must be a power of two");
455+
ESTACK_STATIC_ASSERT(ESTACK_DEFAULT_HEADER_ALIGNMENT >= sizeof(uintptr_t), "ESTACK_DEFAULT_HEADER_ALIGNMENT must be greater than or equal to sizeof(uintptr_t)");
449456
#endif
450457

451458
/*
@@ -568,7 +575,7 @@ typedef struct {
568575
/*
569576
* Diagnostic & Visualization API
570577
*/
571-
ESTACKDEF void estack_print(const EStack *stack);
578+
ESTACKDEF void estack_print(EStack *stack);
572579
#endif // DEBUG
573580

574581
// --- Stack Creation (Dynamic) ---
@@ -1397,6 +1404,10 @@ ESTACKDEF void estack_free_to_marker(EStack *ESTACK_RESTRICT stack, EStackMarker
13971404
ESTACK_CHECK_V((decoded_index <= cur_index),
13981405
"Internal Error: 'estack_free_to_marker' marker index is out of range");
13991406

1407+
if (ESTACK_UNLIKELY(decoded_index > cur_index)) {
1408+
return;
1409+
}
1410+
14001411
if (decoded_index == cur_index) return;
14011412

14021413
#ifdef ESTACK_POISONING
@@ -1624,7 +1635,7 @@ static int estack_compare_sizes(const void *a, const void *b) {
16241635
* Print detailed diagnostic statistics of the EStack allocator.
16251636
* Analyzes the metadata offset array on the fly to compute size metrics.
16261637
*/
1627-
ESTACKDEF void estack_print(const EStack *stack) {
1638+
ESTACKDEF void estack_print(EStack *stack) {
16281639
if (!stack) {
16291640
PRINTF(T("EStack: NULL pointer provided.\n\n"));
16301641
return;

0 commit comments

Comments
 (0)