Index: modules/metadata/mod_expires.c =================================================================== --- modules/metadata/mod_expires.c (revision 685653) +++ modules/metadata/mod_expires.c (working copy) @@ -395,8 +395,8 @@ apr_table_t *t) { apr_time_t base; - apr_time_t additional; apr_time_t expires; + apr_time_t max_age; int additional_sec; char *timestr; @@ -409,16 +409,12 @@ return DECLINED; } base = r->finfo.mtime; - additional_sec = atoi(&code[1]); - additional = apr_time_from_sec(additional_sec); break; case 'A': /* there's been some discussion and it's possible that * 'access time' will be stored in request structure */ base = r->request_time; - additional_sec = atoi(&code[1]); - additional = apr_time_from_sec(additional_sec); break; default: /* expecting the add_* routines to be case-hardened this @@ -428,11 +424,16 @@ "internal error: bad expires code: %s", r->filename); return HTTP_INTERNAL_SERVER_ERROR; } - - expires = base + additional; + additional_sec = atoi(&code[1]); + /* Do not let max-age be negetive. + */ + max_age = apr_time_sec(base - r->request_time) + additional_sec; + if (max_age < 0) max_age = APR_INT64_MAX; + expires = base + apr_time_from_sec(additional_sec); + if (expires < 0) expires = APR_INT64_MAX; apr_table_mergen(t, "Cache-Control", apr_psprintf(r->pool, "max-age=%" APR_TIME_T_FMT, - apr_time_sec(expires - r->request_time))); + max_age)); timestr = apr_palloc(r->pool, APR_RFC822_DATE_LEN); apr_rfc822_date(timestr, expires); apr_table_setn(t, "Expires", timestr);