cybersecurity · beginner · ~15 min
Suffix matching that respects extension boundaries and case.
Validate a filename against an extension allowlist — the classic upload-handler check, done with end-anchored suffix matching so the evil.png.exe trick can't sneak through.
Implement int has_allowed_extension(const char *name, const char *const *exts, size_t n_exts) that returns 1 if name ends with one of the allowed extensions (case-insensitive ASCII), else 0.
name: the filename to check, or NULL.exts: an array of n_exts allowed extensions; each starts with . and contains no path separators (e.g. {".png", ".jpg", ".jpeg"}). The grader passes a fixed list.Returns int: 1 if name ends with any allowed extension (compared case-insensitively), else 0.
exts = {".png", ".jpg", ".jpeg"}
has_allowed_extension("avatar.png", exts, 3) -> 1
has_allowed_extension("AVATAR.PNG", exts, 3) -> 1 (case-insensitive)
has_allowed_extension("doc.PDF", exts, 3) -> 0
has_allowed_extension("noext", exts, 3) -> 0
has_allowed_extension(".png", exts, 3) -> 1 (whole name is the extension)
has_allowed_extension("file.png.exe", exts, 3) -> 0 (double-extension trick)
NULL or empty name returns 0..png inside evil.png.exe does not count.Upload handlers, attachment scanners, and static-file servers all need to reject filenames they shouldn't serve. The classic check is an extension allowlist — short, defensive, and catches a lot of mischief.
A filename name (or NULL), an array exts of allowed extensions, and its count n_exts.
An int: 1 if name ends with an allowed extension (case-insensitive), else 0.
ASCII case-insensitive suffix match anchored at the end of the name.
#include <stddef.h>
int has_allowed_extension(const char *name, const char *const *exts, size_t n_exts) { /* TODO */ return 0; }
Using strstr for the extension — matches .png inside evil.png.exe. Forgetting case-insensitive compare. Trusting the extension as the only check (defence in depth: also check magic bytes).
No dot in name; extension is the entire filename; double extension; uppercase extension.
O(name_len * n_exts).
Solve this exercise in the browser editor — compile and run against the test harness, no setup required.