From 7035863f5fa4306e58c8157b2a5893ba5e0f1eaf Mon Sep 17 00:00:00 2001 From: TAKAI Kousuke <62541129+t-a-k@users.noreply.github.com> Date: Fri, 19 Feb 2021 01:11:13 +0900 Subject: Perl_my_atof3: disallow double signs and spaces between a sign and number Perl_my_atof3 used to pass a substring after the first (optional) sign to (S_)strtod, which causes wrong numifications for strings like "-+3" or "+ 0x123" (for the latter case, while Perl_my_atof3 already had the code to block "0x" prefixes, this string will slip through due to the space character in it). For GH #18584. --- numeric.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'numeric.c') diff --git a/numeric.c b/numeric.c index 72130dd9f5..76f7395d58 100644 --- a/numeric.c +++ b/numeric.c @@ -1675,6 +1675,10 @@ Perl_my_atof3(pTHX_ const char* orig, NV* value, const STRLEN len) return (char *)s+1; } + /* strtod will parse a sign (and skip leading whitespaces) by itself, + * so rewind s to the beginning of the string. */ + s = orig; + /* If the length is passed in, the input string isn't NUL-terminated, * and in it turns out the function below assumes it is; therefore we * create a copy and NUL-terminate that */ @@ -1682,7 +1686,7 @@ Perl_my_atof3(pTHX_ const char* orig, NV* value, const STRLEN len) Newx(copy, len + 1, char); Copy(orig, copy, len, char); copy[len] = '\0'; - s = copy + (s - orig); + s = copy; } result[2] = S_strtod(aTHX_ s, &endp); @@ -1696,7 +1700,8 @@ Perl_my_atof3(pTHX_ const char* orig, NV* value, const STRLEN len) } if (s != endp) { - *value = negative ? -result[2] : result[2]; + /* Note that negation is handled by strtod. */ + *value = result[2]; return endp; } return NULL; -- cgit v1.2.1