cybersecurity · intermediate · ~25 min
Pattern-based string rewriting in place; respecting buffer bounds.
Implement void redact_emails(char *line) that mutates line in place, replacing every email-like substring with the literal text [redacted].
An email-like substring is a maximal run matching this loose pattern:
[A-Za-z0-9._+-]@[A-Za-z0-9.-].[A-Za-z]The function uses the same buffer (no allocations). The line is null-terminated and writable; the replacement is shorter than or equal to most addresses so this fits without growth — but we cap the output at the original buffer length.
For practical purposes you may assume strlen(line) < 2048 and you are given the same buffer to mutate.
"alice@example.com signed in"
-> "[redacted] signed in"
"User bob.smith+spam@example.co.uk forgot password"
-> "User [redacted] forgot password"
"no email here"
-> "no email here"
"two: a@b.com and c@d.io"
-> "two: [redacted] and [redacted]"
Shipping logs to a centralised analytics service often runs afoul of privacy laws (GDPR, CCPA) unless personally identifiable information is stripped first. Email redaction is the smallest example of the kind of pipeline-stage redaction that every production logger eventually needs.
Null-terminated mutable line, max length ~2 KB.
line mutated; every email replaced with [redacted].
In-place rewriting. Assume buffer length is enough for the resulting line (replacements are no longer than the originals for short addresses; we still cap at the buffer's original size to be safe).
void redact_emails(char *line) { /* TODO */ }
Replacing only the first match. Allocating a new buffer (the contract is in-place).
No email; multiple emails; email at the very start or end; pathological-looking strings that aren't actually emails (@, a@, @b).
O(strlen(line)).
Solve this exercise in the browser editor — compile and run against the test harness, no setup required.