From f5453290b7742443da98728cacfeeca42aafa7f6 Mon Sep 17 00:00:00 2001 From: Glenn Strauss Date: Sat, 26 Mar 2016 10:58:49 +0000 Subject: [PATCH] validate return values from strtol, strtoul (fixes #2564) From: Glenn Strauss git-svn-id: svn://svn.lighttpd.net/lighttpd/branches/lighttpd-1.4.x@3122 152afb58-edef-0310-8abb-c4023f1b3aa9 --- src/configparser.y | 12 +++++++++++- src/mod_cgi.c | 11 ++++++++--- src/mod_cml_funcs.c | 10 +++++++++- src/mod_fastcgi.c | 11 ++++++++--- src/mod_proxy.c | 4 ++-- src/mod_scgi.c | 11 ++++++++--- src/mod_webdav.c | 12 ++++++++---- 7 files changed, 54 insertions(+), 17 deletions(-) diff --git a/src/configparser.y b/src/configparser.y index 56a4bf9b..12be92ad 100644 --- a/src/configparser.y +++ b/src/configparser.y @@ -9,6 +9,8 @@ #include "array.h" #include +#include +#include #include #include @@ -267,8 +269,16 @@ value(A) ::= STRING(B). { } value(A) ::= INTEGER(B). { + char *endptr; A = (data_unset *)data_integer_init(); - ((data_integer *)(A))->value = strtol(B->ptr, NULL, 10); + errno = 0; + ((data_integer *)(A))->value = strtol(B->ptr, &endptr, 10); + /* skip trailing whitespace */ + if (endptr != B->ptr) while (isspace(*endptr)) endptr++; + if (0 != errno || *endptr != '\0') { + fprintf(stderr, "error parsing number: '%s'\n", B->ptr); + ctx->ok = 0; + } buffer_free(B); B = NULL; } diff --git a/src/mod_cgi.c b/src/mod_cgi.c index da521ba3..26de4f1d 100644 --- a/src/mod_cgi.c +++ b/src/mod_cgi.c @@ -307,8 +307,13 @@ static int cgi_response_parse(server *srv, connection *con, plugin_data *p, buff break; case 6: if (0 == strncasecmp(key, "Status", key_len)) { - con->http_status = strtol(value, NULL, 10); - con->parsed_response |= HTTP_STATUS; + int status = strtol(value, NULL, 10); + if (status >= 100 && status < 1000) { + con->http_status = status; + con->parsed_response |= HTTP_STATUS; + } else { + con->http_status = 502; + } } break; case 8: @@ -324,7 +329,7 @@ static int cgi_response_parse(server *srv, connection *con, plugin_data *p, buff break; case 14: if (0 == strncasecmp(key, "Content-Length", key_len)) { - con->response.content_length = strtol(value, NULL, 10); + con->response.content_length = strtoul(value, NULL, 10); con->parsed_response |= HTTP_CONTENT_LENGTH; } break; diff --git a/src/mod_cml_funcs.c b/src/mod_cml_funcs.c index 1dd0e50b..5625be76 100644 --- a/src/mod_cml_funcs.c +++ b/src/mod_cml_funcs.c @@ -245,6 +245,8 @@ int f_memcache_get_long(lua_State *L) { char *value; const char *key; memcached_st *memc; + char *endptr; + long v; if (!lua_islightuserdata(L, lua_upvalueindex(1))) { lua_pushstring(L, "where is my userdata ?"); @@ -264,7 +266,13 @@ int f_memcache_get_long(lua_State *L) { return 1; } - lua_pushinteger(L, strtol(value, NULL, 10)); + errno = 0; + v = strtol(value, &endptr, 10); + if (0 == errno && *endptr == '\0') { + lua_pushinteger(L, v); + } else { + lua_pushnil(L); + } free(value); diff --git a/src/mod_fastcgi.c b/src/mod_fastcgi.c index 5c630100..e55c06d4 100644 --- a/src/mod_fastcgi.c +++ b/src/mod_fastcgi.c @@ -2133,8 +2133,13 @@ static int fcgi_response_parse(server *srv, connection *con, plugin_data *p, buf break; case 6: if (0 == strncasecmp(key, "Status", key_len)) { - con->http_status = strtol(value, NULL, 10); - con->parsed_response |= HTTP_STATUS; + int status = strtol(value, NULL, 10); + if (status >= 100 && status < 1000) { + con->http_status = status; + con->parsed_response |= HTTP_STATUS; + } else { + con->http_status = 502; + } } break; case 8: @@ -2236,7 +2241,7 @@ range_success: ; break; case 14: if (0 == strncasecmp(key, "Content-Length", key_len)) { - con->response.content_length = strtol(value, NULL, 10); + con->response.content_length = strtoul(value, NULL, 10); con->parsed_response |= HTTP_CONTENT_LENGTH; if (con->response.content_length < 0) con->response.content_length = 0; diff --git a/src/mod_proxy.c b/src/mod_proxy.c index 6c4d2bc5..8f46cf32 100644 --- a/src/mod_proxy.c +++ b/src/mod_proxy.c @@ -552,7 +552,7 @@ static int proxy_response_parse(server *srv, connection *con, plugin_data *p, bu if (*key) { http_response_status = (int) strtol(key, NULL, 10); - if (http_response_status <= 0) http_response_status = 502; + if (http_response_status < 100 || http_response_status >= 1000) http_response_status = 502; } else { http_response_status = 502; } @@ -595,7 +595,7 @@ static int proxy_response_parse(server *srv, connection *con, plugin_data *p, bu break; case 14: if (0 == strncasecmp(key, "Content-Length", key_len)) { - con->response.content_length = strtol(value, NULL, 10); + con->response.content_length = strtoul(value, NULL, 10); con->parsed_response |= HTTP_CONTENT_LENGTH; } break; diff --git a/src/mod_scgi.c b/src/mod_scgi.c index 47aadd35..02c463cd 100644 --- a/src/mod_scgi.c +++ b/src/mod_scgi.c @@ -1713,8 +1713,13 @@ static int scgi_response_parse(server *srv, connection *con, plugin_data *p, buf break; case 6: if (0 == strncasecmp(key, "Status", key_len)) { - con->http_status = strtol(value, NULL, 10); - con->parsed_response |= HTTP_STATUS; + int status = strtol(value, NULL, 10); + if (status >= 100 && status < 1000) { + con->http_status = status; + con->parsed_response |= HTTP_STATUS; + } else { + con->http_status = 502; + } } break; case 8: @@ -1730,7 +1735,7 @@ static int scgi_response_parse(server *srv, connection *con, plugin_data *p, buf break; case 14: if (0 == strncasecmp(key, "Content-Length", key_len)) { - con->response.content_length = strtol(value, NULL, 10); + con->response.content_length = strtoul(value, NULL, 10); con->parsed_response |= HTTP_CONTENT_LENGTH; } break; diff --git a/src/mod_webdav.c b/src/mod_webdav.c index 925a7c86..c9365cd3 100644 --- a/src/mod_webdav.c +++ b/src/mod_webdav.c @@ -1204,7 +1204,7 @@ URIHANDLER_FUNC(mod_webdav_subrequest_handler) { buffer *b; DIR *dir; data_string *ds; - int depth = -1; + int depth = -1; /* (Depth: infinity) */ struct stat st; buffer *prop_200; buffer *prop_404; @@ -1218,9 +1218,13 @@ URIHANDLER_FUNC(mod_webdav_subrequest_handler) { if (buffer_is_empty(con->physical.path)) return HANDLER_GO_ON; /* PROPFIND need them */ - if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Depth"))) { - depth = strtol(ds->value->ptr, NULL, 10); - } + if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Depth")) && 1 == buffer_string_length(ds->value)) { + if ('0' == *ds->value->ptr) { + depth = 0; + } else if ('1' == *ds->value->ptr) { + depth = 1; + } + } /* else treat as Depth: infinity */ switch (con->request.http_method) { case HTTP_METHOD_PROPFIND: