From d345666ea85184401e9812684f47c67dd5db946a Mon Sep 17 00:00:00 2001 From: Leorize Date: Wed, 17 Jun 2020 23:49:57 -0500 Subject: [PATCH] libnetapi/HttpResult: improve Length() algorithm `atoi()` maximum value is `LONG_MAX` which is smaller than `SIZE_MAX`. This cause any Content-Length > LONG_MAX to be represented in an erroneous value. This will also happen to any invalid Content-Length header. This change uses strtoul() for the extended range (should be the same as size_t range), and combined with proper error checking to determine whether the received Content-Length is a valid and/or representable value. Returns 0 if the data is invalid or can not be represented. Some shortcomings about the current implementation are also noted accordingly. They will be solved in later patches. Change-Id: If28c4c3b8430ed83dd0f600030ec8949cf7e0051 Reviewed-on: https://review.haiku-os.org/c/haiku/+/2927 Reviewed-by: waddlesplash --- src/kits/network/libnetapi/HttpResult.cpp | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/kits/network/libnetapi/HttpResult.cpp b/src/kits/network/libnetapi/HttpResult.cpp index a9013b7064..015f53107d 100644 --- a/src/kits/network/libnetapi/HttpResult.cpp +++ b/src/kits/network/libnetapi/HttpResult.cpp @@ -87,7 +87,27 @@ BHttpResult::Length() const const char* length = Headers()["Content-Length"]; if (length == NULL) return 0; - return atoi(length); + + /* NOTE: Not RFC7230 compliant: + * - If Content-Length is a list, all values must be checked and verified + * to be duplicates of each other, but this is currently not supported. + */ + size_t result = 0; + /* strtoul() will ignore a prefixed sign, so we verify that there aren't + * any before continuing (RFC7230 only permits digits). + * + * We can check length[0] directly because header values are trimmed by + * HttpHeader beforehand. */ + if (length[0] != '-' || length[0] != '+') { + errno = 0; + char *endptr = NULL; + result = strtoul(length, &endptr, 10); + /* ERANGE will be signalled if the result is too large (which can + * happen), in that case, return 0. */ + if (errno != 0 || *endptr != '\0') + result = 0; + } + return result; }