Skip to content
Permalink
Browse files

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
  • Loading branch information
bagder committed Nov 28, 2019
1 parent bc64377 commit 0044443a020d15c262e9f6c724b29365a8148437
Showing with 36 additions and 9 deletions.
  1. +1 −1 lib/altsvc.c
  2. +2 −1 lib/cookie.c
  3. +1 −3 lib/ftp.c
  4. +2 −4 lib/http.c
  5. +24 −0 lib/parsedate.c
  6. +6 −0 lib/parsedate.h
@@ -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;
@@ -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
@@ -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
@@ -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;
}
@@ -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.
@@ -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 */

4 comments on commit 0044443

@icing

This comment has been minimized.

Copy link

icing replied Nov 29, 2019

Seems wise not to look too far into the future.

@bagder

This comment has been minimized.

Copy link
Member Author

bagder replied Nov 29, 2019

A sort of band-aid for the hopefully shrinking user base with 32 bit time_t ...

@icing

This comment has been minimized.

Copy link

icing replied Nov 29, 2019

Death of IoT devices predicted for 2038?

@ClaymorePT

This comment has been minimized.

Copy link

ClaymorePT replied Nov 29, 2019

(Kudos for the 25Kth commit!)

Please sign in to comment.
You can’t perform that action at this time.