pointers-memory · intermediate · ~25 min
The mechanism behind GCC's -fstack-protector.
Implement two functions over this struct:
typedef struct { uint32_t canary_lo; char buf[16]; uint32_t canary_hi; } guarded_t;
void guarded_init(guarded_t *g);
int guarded_check(const guarded_t *g); /* 1 if both canaries intact, 0 otherwise */
After guarded_init, both canaries hold the magic value 0xDEADBEEFu. guarded_check reports whether either has since been overwritten.
(In a real program the canary would sit between a local buffer and the saved return address. To keep this exercise safe to run under -fstack-protector we simulate corruption by writing to g->canary_hi directly from the test code — no actual overflow.)
Stack canaries are the cheap, ubiquitous defense against buffer overflows — every modern compiler emits them. Implementing the concept yourself in pure C makes the mechanism obvious.
Pointer to a guarded_t.
0 or 1 from guarded_check.
No allocations; just set / compare fields.
#include <stdint.h>
#ifndef GUARDED_T_DEFINED
#define GUARDED_T_DEFINED
typedef struct { uint32_t canary_lo; char buf[16]; uint32_t canary_hi; } guarded_t;
#endif
void guarded_init(guarded_t *g);
int guarded_check(const guarded_t *g);
Setting the canary to 0 (any uninitialized memory looks like a corrupted canary); checking only one canary (real overflows can come from either side via under/over-runs); using == against the wrong magic word.
Both canaries intact — return 1. Either canary changed — return 0.
O(1).
Solve this exercise in the browser editor — compile and run against the test harness, no setup required.