Skip to content

Fix parse_ranges UB, serve stat-before-open; add CLAUDE.md and 34 tests#8

Draft
troglodyne-bot wants to merge 1 commit into
Troglodyne-Internet-Widgets:masterfrom
troglodyne-bot:koan/extend-tests-and-fix-ranges
Draft

Fix parse_ranges UB, serve stat-before-open; add CLAUDE.md and 34 tests#8
troglodyne-bot wants to merge 1 commit into
Troglodyne-Internet-Widgets:masterfrom
troglodyne-bot:koan/extend-tests-and-fix-ranges

Conversation

@troglodyne-bot

Copy link
Copy Markdown
Contributor

What

Two bug fixes in lib/TPSGI.pm, project documentation, and 34 new tests across 3 test files.

Why

parse_ranges: my $range = val if cond is Perl undefined behaviour — when the condition is false, $range retains its value from the previous call rather than resetting to undef. On keepalive connections, a non-range request following a range request would silently inherit stale range data. Same pattern as the extract_query fix in PR #7.

serve stat-before-open: stat($path) was called before open(), so nonexistent or unreadable files caused undef warnings from gmtime() and the numeric > comparison. Now stat happens on the filehandle inside the open block.

How

  • parse_ranges: replaced my $range = val if cond with an explicit if/else
  • serve: moved stat + mtime/size variables inside the if (open ...) block; switched from stat($path) to stat($fh) (more reliable: no TOCTOU, uses the already-open descriptor)
  • CLAUDE.md: project orientation doc for agent sessions (arch overview, test instructions, key patterns)
  • t/lib/TPSGITestStubs.pm: stub loader that prefers real modules, falls back to minimal fakes for 9 CPAN deps not installed in the test environment
  • t/04-parse-ranges.t: 8 tests including stale-variable regression (calls parse_ranges twice, verifies second call returns empty)
  • t/05-serve.t: 7 tests covering 200/304/403 responses, MIME types, Accept-Ranges, Server-Timing, streaming
  • t/06-route-and-query.t: 19 tests for HTTP error helpers, route method/content-type dispatch, Server-Timing, extract_query GET params, captures, data injection, and redirect methods

Testing

perl -Ilib -It/lib t/04-parse-ranges.t t/05-serve.t t/06-route-and-query.t
# Files=3, Tests=34 — All tests successful

Two bugs fixed in lib/TPSGI.pm:

1. parse_ranges: `my $range = val if cond` is Perl UB — when the condition
   is false, $range retains the value from the previous call rather than
   being reset to undef. On keepalive connections, a request without Range
   headers after one that had them would incorrectly return stale ranges.
   Fixed with an explicit if/else.

2. serve: stat($path) was called before open(), so when the file doesn't
   exist or can't be opened, $mt and $sz are undef — triggering warnings
   in gmtime() and the numeric comparison. Moved stat inside the open block,
   stat-ing the filehandle ($fh) instead of the path.

Also adds:
- CLAUDE.md: project orientation for agent sessions
- t/lib/TPSGITestStubs.pm: stub loader for missing CPAN deps in test env
- t/04-parse-ranges.t: 8 tests including stale-variable regression
- t/05-serve.t: 7 tests for static file serving (200/304/403/streaming)
- t/06-route-and-query.t: 19 tests for route dispatch, extract_query,
  HTTP error helpers, and redirect methods
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