From: Jay Satiro Date: Thu, 26 Dec 2024 20:38:39 +0000 (-0500) Subject: http: ignore invalid Retry-After times X-Git-Tag: curl-8_12_0~238 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=6c70ec16c7cb8c86e1bc6e619da51d6a38fd866c;p=thirdparty%2Fcurl.git http: ignore invalid Retry-After times - Treat negative Retry-After date-based times as 0. - Treat Retry-After times greater than 6 hours as 6 hours. Prior to this change Retry-After did not have a limited range and the server could have set a time greater than 6 hours or a date in the past that would result in a negative time, either of which may be unexpected by the user. The 6 hour limit is purposely not documented so that it can be changed in the future if necessary. Closes https://github.com/curl/curl/pull/15833 --- diff --git a/docs/libcurl/opts/CURLINFO_RETRY_AFTER.md b/docs/libcurl/opts/CURLINFO_RETRY_AFTER.md index 0dca2e509d..87700bc331 100644 --- a/docs/libcurl/opts/CURLINFO_RETRY_AFTER.md +++ b/docs/libcurl/opts/CURLINFO_RETRY_AFTER.md @@ -36,6 +36,11 @@ While the HTTP header might contain a fixed date string, the CURLINFO_RETRY_AFTER(3) always returns the number of seconds to wait - or zero if there was no header or the header could not be parsed. +This option used to return a negative wait time if the server provided a date +in the past. Since 8.12.0, a negative wait time is returned as zero. In any +case we recommend checking that the wait time is within an acceptable range for +your circumstance. + # DEFAULT Zero if there was no header. diff --git a/lib/http.c b/lib/http.c index 18eba54d89..e155200a52 100644 --- a/lib/http.c +++ b/lib/http.c @@ -2901,11 +2901,19 @@ static CURLcode http_header(struct Curl_easy *data, (void)curlx_strtoofft(v, NULL, 10, &retry_after); if(!retry_after) { time_t date = Curl_getdate_capped(v); - if((time_t)-1 != date) + time_t current = time(NULL); + if((time_t)-1 != date && date > current) { /* convert date to number of seconds into the future */ - retry_after = date - time(NULL); + retry_after = date - current; + } } - data->info.retry_after = retry_after; /* store it */ + if(retry_after < 0) + retry_after = 0; + /* limit to 6 hours max. this is not documented so that it can be changed + in the future if necessary. */ + if(retry_after > 21600) + retry_after = 21600; + data->info.retry_after = retry_after; return CURLE_OK; } break; diff --git a/tests/data/test1596 b/tests/data/test1596 index f05f0ec146..8b94cd12fa 100644 --- a/tests/data/test1596 +++ b/tests/data/test1596 @@ -13,9 +13,9 @@ If-Modified-Since HTTP/1.1 429 Too Many Requests -Date: Thu, 11 Jul 2019 02:26:59 GMT +Date: Wed, 31 Dec 2036 02:26:59 GMT Server: test-server/swsclose -Retry-After: Thu, 11 Jul 2024 02:26:59 GMT +Retry-After: Wed, 31 Dec 2036 02:26:59 GMT @@ -42,8 +42,9 @@ Host: %HOSTIP:%HTTPPORT Accept: */* +# Retry-After time is limited to 6 hours (21600 seconds) -Retry-After 172066 +Retry-After 21600 diff --git a/tests/libtest/lib1594.c b/tests/libtest/lib1594.c index bf25ffbeb5..2a31a720e4 100644 --- a/tests/libtest/lib1594.c +++ b/tests/libtest/lib1594.c @@ -49,12 +49,6 @@ CURLcode test(char *URL) if(res) goto test_cleanup; -#ifdef LIB1596 - /* we get a relative number of seconds, so add the number of seconds - we're at to make it a somewhat stable number. Then remove accuracy. */ - retry += time(NULL); - retry /= 10000; -#endif printf("Retry-After %" CURL_FORMAT_CURL_OFF_T "\n", retry); test_cleanup: