cybersecurity · intermediate · ~15 min

Fix the strcpy overflow

Bounded copy with explicit destination size + NUL termination.

Challenge

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
}

Task

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.

Input

  • out / out_sz: the destination buffer and its total size in bytes.
  • src: the NUL-terminated source string.

Output

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.

Example

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)

Edge cases

  • A source needing the full buffer plus terminator is too long: return -1.
  • Always NUL-terminate, even on the error path.

Rules

  • Copy at most out_sz - 1 bytes; never write past out_sz.

Why this matters

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'.

Input format

Destination out with size out_sz and a source string src.

Output format

0 if src fit and was copied, -1 if too long; out is always NUL-terminated.

Constraints

Copy at most out_sz - 1 bytes; never write past out_sz.

Starter code

#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;
}

Common mistakes

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.

Edge cases to handle

Source longer than dst — must truncate AND NUL-terminate. Source equal to dst's capacity — many APIs get this wrong.

Complexity

O(min(strlen(src), cap)).

Background lessons

Up next

Solve this exercise in the browser editor — compile and run against the test harness, no setup required.