Skip to content

fix: avoid heap-buffer-overflow in make_sorted_dirlist#98

Open
kugland wants to merge 2 commits into
emikulic:masterfrom
kugland:fix/dirlist-name-overflow
Open

fix: avoid heap-buffer-overflow in make_sorted_dirlist#98
kugland wants to merge 2 commits into
emikulic:masterfrom
kugland:fix/dirlist-name-overflow

Conversation

@kugland
Copy link
Copy Markdown
Contributor

@kugland kugland commented May 14, 2026

Summary

make_sorted_dirlist() sizes its filename buffer as xmalloc(strlen(path) + MAXNAMLEN + 1) and then sprintf("%s%s", path, ent->d_name) into it, guarded only by assert(strlen(ent->d_name) <= MAXNAMLEN). Release builds define NDEBUG (darkhttpd.c near the top), so the assert is stripped. On filesystems whose runtime _PC_NAME_MAX exceeds the compile-time MAXNAMLEN (e.g. some FUSE filesystems, or MAXNAMLEN being smaller than expected on some platforms), readdir() can return a longer name and the sprintf overruns the heap allocation.

Fix: drop the fixed-size buffer and use xasprintf("%s%s", path, ent->d_name). The bound is then unconditional regardless of NDEBUG or _PC_NAME_MAX.

Commits

  • 1st commit adds the regression test (fails on current master).
  • 2nd commit applies the fix (test passes).

This makes the issue easy to reproduce on the test commit alone.

Test plan

The test (devel/test_dirlist_overflow.c) stubs opendir/readdir to feed make_sorted_dirlist() an entry whose d_name is wider than MAXNAMLEN, and uses -Wl,--wrap=malloc,--wrap=realloc,--wrap=free to attach a canary past each allocation. The overflow stamps the canary; the test reports FAIL and exits 1. With the fix, no canary is touched.

  • Builds clean.
  • On the test-only commit: FAIL: heap-buffer-overflow in make_sorted_dirlist (sprintf past xmalloc bound), exit 1.
  • On the fix commit: PASS: no heap-buffer-overflow detected, exit 0.
  • Wired into devel/run-tests so it runs with the rest of the suite.

kugland added 2 commits May 14, 2026 04:29
Demonstrates sprintf overflow when readdir returns names > MAXNAMLEN.
Uses malloc wrapping with canary detection. Fails on current HEAD,
will pass after fix is applied.
The "%s%s" sprintf into a fixed strlen(path) + MAXNAMLEN + 1 buffer
relied on a debug-only assert to bound the directory entry name. In
release builds, and on filesystems whose runtime _PC_NAME_MAX exceeds
the compile-time NAME_MAX, sprintf could overflow the heap allocation.
Use xasprintf so the bound is unconditional.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant