Skip to content

Fix six audit findings; bring tests up to PHP 8.5#85

Merged
ben-xo merged 1 commit into
mainfrom
fix/audit-bugs-2026-04
Apr 28, 2026
Merged

Fix six audit findings; bring tests up to PHP 8.5#85
ben-xo merged 1 commit into
mainfrom
fix/audit-bugs-2026-04

Conversation

@ben-xo
Copy link
Copy Markdown
Owner

@ben-xo ben-xo commented Apr 28, 2026

Summary

Six bug fixes from a code audit, each preceded by a test that fails on the buggy code. Plus prerequisite work to get the test suite running on PHP 8.4/8.5 and to expand the CI matrix.

Bug fixes

  • <itunes:block> only emits for yes/Yes — previously any non-empty value (including the example "no" in dir2cast.ini) was emitted, contradicting Apple's spec and silently blocking feeds from podcast directories.
  • Per-MP3-dir dir2cast.ini mtime now invalidates the cache — new LOCAL_INI_FILE constant tracked alongside INI_FILE. Editing a per-podcast ini no longer silently serves stale cached output.
  • Caching_getID3_Podcast_Helper::addNamespaceTo delegates correctly — was calling the wrapped helper's appendToChannel instead of addNamespaceTo.
  • ?force=… password compare uses hash_equals with explicit string casts — avoids PHP's numeric-string coercion in == ("01" == "1", "0e1234" == "0e5678") and timing leaks.
  • HTTP Last-modified header uses RFC 7231 IMF-fixdate ( GMT) instead of RFC 2822 ( +0000); some intermediaries reject the non-conforming form. RSS <lastBuildDate> still uses RFC 2822 as required.
  • HTTP Last-modified falls back to the cache file's mtime when the cached XML lacks an extractable <lastBuildDate> (avoids emitting an empty header).

Test / CI work

  • bootstrap.php: handle E_STRICT removal in PHP 8.5 (use defined() + runtime constant() lookup so the symbol is never referenced when absent).
  • bootstrap.php: fake_getopt rewritten to pass user argv as real CLI args after --. PHP 8.4+ ignores $GLOBALS['argv'] for getopt(), so the previous injection-based mocking returned an empty array.
  • .github/workflows/testing.yml: matrix now covers PHP 8.3, 8.4, 8.5 (was 7.3–8.2). macos-11macos-latest (the older runner has been retired).

Version bumped to 1.39, CHANGELOG.txt and README.md updated, dir2cast.ini example for ITUNES_BLOCK updated.

Net: 1062 tests pass on PHP 8.5 locally (up from 1041 on main — 21 new tests).

Test plan

  • CI: all 8 PHP versions (7.3, 7.4, 8.0, 8.1, 8.2, 8.3, 8.4, 8.5) × Ubuntu and macOS pass
  • Spot-check: ?force=… still uncaches with a correct password
  • Spot-check: a feed with ITUNES_BLOCK = "yes" emits <itunes:block>yes</itunes:block>; one with "no" or unset omits it
  • Spot-check: editing only a per-podcast dir2cast.ini triggers a cache rebuild on the next request
  • Spot-check: response includes Last-modified: …, … GMT (not +0000)

🤖 Generated with Claude Code

* itunes:block now only emits for "yes"/"Yes" per Apple's spec;
  previously any non-empty value (including the example "no" in
  dir2cast.ini) was emitted, which blocks the feed from directories.
* Per-MP3-dir dir2cast.ini's mtime now invalidates the cache via a
  new LOCAL_INI_FILE constant tracked alongside INI_FILE; editing a
  per-podcast ini no longer silently serves stale cached output.
* Caching_getID3_Podcast_Helper::addNamespaceTo now delegates to the
  wrapped helper's addNamespaceTo (was calling appendToChannel).
* ?force=... password compare now uses hash_equals() with explicit
  string casts: avoids PHP's numeric-string coercion in == ("01" == "1",
  "0e1234" == "0e5678") and timing leaks.
* HTTP Last-modified header now uses RFC 7231 IMF-fixdate (" GMT")
  instead of RFC 2822 (" +0000"); some intermediaries rejected the
  non-conforming form. RSS <lastBuildDate> still uses RFC 2822.
* HTTP Last-modified falls back to the cache file's mtime when the
  cached XML lacks an extractable <lastBuildDate>.

Each fix is preceded by a test that fails on the buggy code.

Also fixes the test suite for newer PHPs and expands CI coverage:
* bootstrap.php: handle E_STRICT removal in PHP 8.5.
* bootstrap.php: fake_getopt rewritten to pass user argv as real CLI
  args; PHP 8.4+ ignores $GLOBALS['argv'] for getopt().
* .github/workflows/testing.yml: matrix now covers 8.3, 8.4, 8.5;
  macos-11 -> macos-latest (older runner retired).

Version bumped to 1.39.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@ben-xo ben-xo merged commit 564c724 into main Apr 28, 2026
32 checks passed
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