summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2019-11-28 15:27:58 +0100
committerDaniel Stenberg <daniel@haxx.se>2019-11-29 11:01:24 +0100
commit0044443a020d15c262e9f6c724b29365a8148437 (patch)
treef345ffb8bf4a275caa823b758ccac35bbf6f3526
parentbc64377ff8386d4f809806b6286f43e5aff19922 (diff)
downloadcurl-0044443a020d15c262e9f6c724b29365a8148437.tar.gz
parsedate: offer a getdate_capped() alternative
... and use internally. This function will return TIME_T_MAX instead of failure if the parsed data is found to be larger than what can be represented. TIME_T_MAX being the largest value curl can represent. Reviewed-by: Daniel Gustafsson Reported-by: JanB on github Fixes #4152 Closes #4651
-rw-r--r--lib/altsvc.c2
-rw-r--r--lib/cookie.c3
-rw-r--r--lib/ftp.c4
-rw-r--r--lib/http.c6
-rw-r--r--lib/parsedate.c24
-rw-r--r--lib/parsedate.h6
6 files changed, 36 insertions, 9 deletions
diff --git a/lib/altsvc.c b/lib/altsvc.c
index c3dbb708a..28c9276b1 100644
--- a/lib/altsvc.c
+++ b/lib/altsvc.c
@@ -161,7 +161,7 @@ static CURLcode altsvc_add(struct altsvcinfo *asi, char *line)
date, &persist, &prio);
if(9 == rc) {
struct altsvc *as;
- time_t expires = curl_getdate(date, NULL);
+ time_t expires = Curl_getdate_capped(date);
as = altsvc_create(srchost, dsthost, srcalpn, dstalpn, srcport, dstport);
if(as) {
as->expires = expires;
diff --git a/lib/cookie.c b/lib/cookie.c
index 7e68b0785..c9e420ad4 100644
--- a/lib/cookie.c
+++ b/lib/cookie.c
@@ -96,6 +96,7 @@ Example set of cookies:
#include "curl_get_line.h"
#include "curl_memrchr.h"
#include "inet_pton.h"
+#include "parsedate.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -715,7 +716,7 @@ Curl_cookie_add(struct Curl_easy *data,
else if(co->expirestr) {
/* Note that if the date couldn't get parsed for whatever reason,
the cookie will be treated as a session cookie */
- co->expires = curl_getdate(co->expirestr, NULL);
+ co->expires = Curl_getdate_capped(co->expirestr);
/* Session cookies have expires set to 0 so if we get that back
from the date parser let's add a second to make it a
diff --git a/lib/ftp.c b/lib/ftp.c
index 8072a33d5..469096f0f 100644
--- a/lib/ftp.c
+++ b/lib/ftp.c
@@ -2039,13 +2039,11 @@ static CURLcode ftp_state_mdtm_resp(struct connectdata *conn,
&year, &month, &day, &hour, &minute, &second)) {
/* we have a time, reformat it */
char timebuf[24];
- time_t secs = time(NULL);
-
msnprintf(timebuf, sizeof(timebuf),
"%04d%02d%02d %02d:%02d:%02d GMT",
year, month, day, hour, minute, second);
/* now, convert this into a time() value: */
- data->info.filetime = curl_getdate(timebuf, &secs);
+ data->info.filetime = Curl_getdate_capped(timebuf);
}
#ifdef CURL_FTP_HTTPSTYLE_HEAD
diff --git a/lib/http.c b/lib/http.c
index e344663d0..885704560 100644
--- a/lib/http.c
+++ b/lib/http.c
@@ -3974,7 +3974,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
else if(checkprefix("Retry-After:", k->p)) {
/* Retry-After = HTTP-date / delay-seconds */
curl_off_t retry_after = 0; /* zero for unknown or "now" */
- time_t date = curl_getdate(&k->p[12], NULL);
+ time_t date = Curl_getdate_capped(&k->p[12]);
if(-1 == date) {
/* not a date, try it as a decimal number */
(void)curlx_strtoofft(&k->p[12], NULL, 10, &retry_after);
@@ -4032,9 +4032,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
#endif
else if(!k->http_bodyless && checkprefix("Last-Modified:", k->p) &&
(data->set.timecondition || data->set.get_filetime) ) {
- time_t secs = time(NULL);
- k->timeofdoc = curl_getdate(k->p + strlen("Last-Modified:"),
- &secs);
+ k->timeofdoc = Curl_getdate_capped(k->p + strlen("Last-Modified:"));
if(data->set.get_filetime)
data->info.filetime = k->timeofdoc;
}
diff --git a/lib/parsedate.c b/lib/parsedate.c
index f4b18d091..585d7ea40 100644
--- a/lib/parsedate.c
+++ b/lib/parsedate.c
@@ -587,6 +587,30 @@ time_t curl_getdate(const char *p, const time_t *now)
return -1;
}
+/* Curl_getdate_capped() differs from curl_getdate() in that this will return
+ TIME_T_MAX in case the parsed time value was too big, instead of an
+ error. */
+
+time_t Curl_getdate_capped(const char *p)
+{
+ time_t parsed = -1;
+ int rc = parsedate(p, &parsed);
+
+ switch(rc) {
+ case PARSEDATE_OK:
+ if(parsed == -1)
+ /* avoid returning -1 for a working scenario */
+ parsed++;
+ return parsed;
+ case PARSEDATE_LATER:
+ /* this returns the maximum time value */
+ return parsed;
+ default:
+ return -1; /* everything else is fail */
+ }
+ /* UNREACHABLE */
+}
+
/*
* Curl_gmtime() is a gmtime() replacement for portability. Do not use the
* gmtime_r() or gmtime() functions anywhere else but here.
diff --git a/lib/parsedate.h b/lib/parsedate.h
index 83d4c1f24..8c7ae94e4 100644
--- a/lib/parsedate.h
+++ b/lib/parsedate.h
@@ -27,4 +27,10 @@ extern const char * const Curl_month[12];
CURLcode Curl_gmtime(time_t intime, struct tm *store);
+/* Curl_getdate_capped() differs from curl_getdate() in that this will return
+ TIME_T_MAX in case the parsed time value was too big, instead of an
+ error. */
+
+time_t Curl_getdate_capped(const char *p);
+
#endif /* HEADER_CURL_PARSEDATE_H */