diff options
| author | Hauke Mehrtens | 2026-05-03 22:18:48 +0000 |
|---|---|---|
| committer | Hauke Mehrtens | 2026-05-15 00:29:10 +0000 |
| commit | 8e5b26f93798af44e77d91146d26ae0f95e63006 (patch) | |
| tree | 409373a8f91527314d7b5676d127ef204906601b | |
| parent | 4221eb8b33ea90d6a09a6048e3280907263604a6 (diff) | |
| download | uhttpd-8e5b26f93798af44e77d91146d26ae0f95e63006.tar.gz | |
file: distinguish parse failure from epoch in date precondition checks
uh_file_date2unix returned 0 on strptime() failure, which the
callers could not distinguish from a successfully parsed
1970-01-01 00:00:00 UTC. Two of those callers misbehave:
* uh_file_if_modified_since compared the parsed value against
st_mtime with '>='. For files whose mtime sits at the Unix
epoch (some tmpfs / squashfs entries on OpenWrt initramfs),
any malformed If-Modified-Since header satisfied 0 >= 0 and
a 304 with no body was returned, breaking content delivery.
* uh_file_if_unmodified_since compared with '<='. A malformed
If-Unmodified-Since header always satisfies 0 <= st_mtime
(for any real file with mtime > 0), so the precondition fired
and every request received a 412 Precondition Failed.
Return (time_t)-1 from uh_file_date2unix on parse failure, and
ignore the precondition (treat the header as if absent) in the
two callers when that sentinel is returned.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
| -rw-r--r-- | file.c | 19 |
1 files changed, 16 insertions, 3 deletions
@@ -316,7 +316,7 @@ static time_t uh_file_date2unix(const char *date) if (strptime(date, "%a, %d %b %Y %H:%M:%S %Z", &t) != NULL) return timegm(&t); - return 0; + return (time_t)-1; } static char * uh_file_unix2date(time_t ts, char *buf, int len) @@ -402,11 +402,16 @@ static bool uh_file_if_match(struct client *cl, struct stat *s) static int uh_file_if_modified_since(struct client *cl, struct stat *s) { char *hdr = uh_file_header(cl, HDR_IF_MODIFIED_SINCE); + time_t t; if (!hdr) return true; - if (uh_file_date2unix(hdr) >= s->st_mtime) { + t = uh_file_date2unix(hdr); + if (t == (time_t)-1) + return true; + + if (t >= s->st_mtime) { uh_file_response_304(cl, s); return false; } @@ -461,8 +466,16 @@ static int uh_file_if_range(struct client *cl, struct stat *s) static int uh_file_if_unmodified_since(struct client *cl, struct stat *s) { char *hdr = uh_file_header(cl, HDR_IF_UNMODIFIED_SINCE); + time_t t; + + if (!hdr) + return true; + + t = uh_file_date2unix(hdr); + if (t == (time_t)-1) + return true; - if (hdr && uh_file_date2unix(hdr) <= s->st_mtime) { + if (t <= s->st_mtime) { uh_file_response_412(cl); return false; } |