๐ WAYPOINT LESSON
Buffers, Bounds, and the Attacker's Model
โญโญโญ advancedโณ 20 min read๐ Lesson 220 of 225
Every `strcpy` is a promise that you checked a length somewhere else. Security is that check, made systematic.
The corruption family
All of these are memory-safety failures the compiler will not stop:
- Buffer overflow โ writing past an array's end. A fixed
char buf[64]fed 65 attacker-controlled bytes writes into whatever lives next (return address, heap metadata, another object). C23 Annex K offersstrcpy_s-style bounds-checked APIs, but portable practice is: never copy without a length:snprintf,memcpywith a computed, checked bound. - Format-string injection โ
printf(user_input)treats%s/%nin the input as directives: leaks memory (%sfrom a garbage pointer), writes memory (%n). The fix is one character:printf("%s", user_input). - Integer overflow โ
(size_t)len + 1whenlenis near SIZE_MAX wraps to 0 and the subsequentmalloc(len+1)hands out a tiny buffer for a huge copy. Check the addition, or use__builtin_add_overflow-style checks where available. - TOCTOU โ check-then-use across a system boundary:
access(path, R_OK)says yes, the file is swapped,open(path)opens something else. The durable fix: open first (get an fd), thenfstatthe fd, and work through the fd โ the check and the use reference the same object. - Use-after-free / double free โ ownership discipline from module 6 is the prevention; a deliberate
free(NULL)-safe, single-owner, null-on-free pattern (free(p); p = NULL;) kills the double-free class.
Uninitialized reads
Reading a local before writing it is undefined behavior โ and in practice hands the attacker whatever was in that stack slot (old pointers, keys). Rule: initialize at declaration (int x = 0;) or structure code so every path writes before any read. Zero-cost discipline, whole bug-class removed.
The defender's checklist
- Every copy carries an explicit, checked length.
- Every format string is a literal.
- Every size arithmetic is checked before allocation.
- Every file interaction goes through one descriptor, checked at use time.
- Every free leaves NULL behind.
- Every uninitialized variable is a compile-error in review.
None of this requires attacker creativity to justify โ only ordinary input.
โก Now practice
Ready to CodeHardening DrillsSafe copies, refusal paths, checked arithmetic, and fd-based TOCTOU elimination โ every guard tested by feeding it exactly the input it exists for.
3 challenges ยท ยท ~26 min