cybersecurity · intermediate · ~15 min
Bounded copy with explicit destination size + NUL termination.
Rewrite a classic strcpy buffer overflow into a safe, bounded copy.
You are given a function with a buffer overflow:
void copy_label(char *out, size_t out_sz, const char *src) {
strcpy(out, src); // unsafe: blindly writes past out_sz
}
Implement int copy_label(char *out, size_t out_sz, const char *src) that copies src into out only if it fits, always NUL-terminating. No main — the grader calls it.
out / out_sz: the destination buffer and its total size in bytes.src: the NUL-terminated source string.Returns 0 on success (the full string fit and was copied), or -1 if src is too long (strlen(src) >= out_sz). The buffer is always left NUL-terminated.
copy_label(buf, 8, "hello") -> 0, buf = "hello"
copy_label(buf, 8, "1234567") -> 0, buf = "1234567" (fits exactly)
copy_label(buf, 8, "123456789") -> -1 (too long)
-1.out_sz - 1 bytes; never write past out_sz.Replacing a strcpy with a bounded equivalent is the single most impactful defensive patch in C. This exercise builds the muscle memory of 'see strcpy → replace with snprintf or strlcpy'.
Destination out with size out_sz and a source string src.
0 if src fit and was copied, -1 if too long; out is always NUL-terminated.
Copy at most out_sz - 1 bytes; never write past out_sz.
#include <string.h>
#include <stddef.h>
int copy_label(char *out, size_t out_sz, const char *src) {
/* TODO: copy safely, return 0 on success, -1 if too long */
return -1;
}
Using strncpy(dst, src, n) — it does NOT guarantee NUL-termination if src is exactly n bytes. Use snprintf(dst, n, "%s", src) or strlcpy(dst, src, n) instead.
Source longer than dst — must truncate AND NUL-terminate. Source equal to dst's capacity — many APIs get this wrong.
O(min(strlen(src), cap)).
Solve this exercise in the browser editor — compile and run against the test harness, no setup required.