A structured lesson workspace with readable content, hands-on examples, and a clean path to completion.
The null-terminated string model has no length information. Every operation must scan for the terminator. If the terminator is missing, the scan overruns. If the buffer is too small, the write overflows. If untrusted input controls the string length, an attacker can trigger both. This is not a theoretical weakness. It is the root cause of thousands of CVEs spanning four decades. The Morris Worm in 1988 exploited a gets-based overflow in fingerd. The same class of bug appears in software shipped last year.
#include <stdio.h>#include <string.h>void process_input(const char *user_data) {char buffer[16];strcpy(buffer, user_data);printf("Processed: %s\n", buffer);}int main(void) {process_input("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");return 0;}
33 bytes (32 A's plus the null) written into a 16-byte buffer. The overflow overwrites the saved frame pointer, the return address, and potentially adjacent stack frames. In a production exploit, the attacker replaces the return address with a pointer to shellcode placed in the overflow data. The function returns to the attacker's code instead of the caller. This is the canonical stack smashing attack.
#include <stdio.h>#include <string.h>int main(void) {char secret[16] = "API_KEY_12345";char output[8];strncpy(output, secret, sizeof(output));printf("Output: ");for (int i = 0; i < 16; i++) {printf("%02x ", (unsigned char)output[i]);}printf("\n");return 0;}
strncpy filled all 8 bytes with no null terminator. If this buffer is sent over a network or written to a log with a length-based API, the receiver reads 8 bytes of the API key. If the buffer had been part of a larger struct, adjacent fields would leak too. The fix: always null-terminate after strncpy, and use length-bounded APIs for transmission.
String safety in C is not a language feature. It is a discipline. The tools exist: bounded functions, sanitizers, static analysis. The language does not force you to use them. That freedom is C's greatest strength and its greatest liability. Next: strnlen, a POSIX function that adds a bounds check to strlen.
Finish the lesson once you have worked through the material. This awards ★ 40 XP.