cybersecurity · intermediate · ~20 min
Defensive string scanning for a well-defined set of malicious sub-patterns.
Reject an untrusted path that tries to climb out of its directory (../../../etc/passwd) before any file is opened.
Implement int has_path_traversal(const char *path) that returns 1 if path contains an obvious traversal pattern, else 0.
Treat these as traversal:
.. segment delimited by /, \, or a string boundary (e.g. .., a/.., ../b, a/../b, a\..\b).%2e%2e in any letter-case combination (%2E%2E, %2e%2E, ...).A plain .. inside a name (foo..bar) is NOT traversal, and a leading / by itself (/etc/passwd) is NOT traversal — only .. segments count.
path: a NUL-terminated path candidate the grader passes.Returns int: 1 if any traversal pattern matches, else 0.
has_path_traversal("foo/bar") -> 0
has_path_traversal("..") -> 1
has_path_traversal("foo/../bar") -> 1
has_path_traversal("foo..bar") -> 0 (".." inside a name)
has_path_traversal("..\Windows") -> 1
has_path_traversal("%2e%2e/foo") -> 1
has_path_traversal("/etc/passwd") -> 0
has_path_traversal("") -> 0
a/./b) is not traversal... must form a complete segment — a lone strstr for ".." wrongly flags foo..bar.realpath and confirm the result stays under an allowed root.Web servers and file-API gateways must reject paths like ../../../etc/passwd before opening anything. The check looks simple but has subtle traps — URL-encoded %2e%2e, mid-string .., and Windows ..\ are all real-world bypasses.
A NUL-terminated path candidate path.
An int: 1 if any traversal pattern matches, else 0.
O(strlen(path)); no allocations; string check only (does not open files).
int has_path_traversal(const char *path) { /* TODO */ return 0; }
Using a single strstr for ".." — that catches "foo..bar" too. The dots must form a complete segment.
Empty input; literal ".." alone; double-dot inside a word ('foo..bar'); URL-encoded form.
O(n).
Solve this exercise in the browser editor — compile and run against the test harness, no setup required.