Fix whitespace in number parsing (#3195)

* Handle input errors for --indent

Handle malformed and overflowing arguments. Also, forbid leading and
trailing spaces to match the behavior of tonumber from commit ce0e788
(improve tonumber/0 performance by parsing input as number literal,
2024-03-02).

* Do not skip leading whitespace in jvp_strtod

`jvp_strtod` skips leading whitespace, but its decnum counterpart
`decNumberFromString` (called within `jv_number_with_literal`) does not.
Those two are called interchangeably, so it leads to inconsistent
behavior depending on whether the decnum feature is enabled.
Additionally, `classify`, used in the token scanner, only considers
[ \t\n\r] to be whitespace, but `jvp_strtod` consumes the larger set
[ \t\n\v\f\r], so those extra characters are considered literals.

Changing this deviates from the behavior of `strdod` from <stdlib.h> and
is technically a breaking API change, since it is a public symbol.
This commit is contained in:
Thalia Archibald
2025-05-29 04:11:00 +09:00
committed by GitHub
parent aaace5432a
commit 9ac6ddae22
3 changed files with 11 additions and 16 deletions
+3 -11
View File
@@ -2368,29 +2368,21 @@ jvp_strtod
sign = nz0 = nz1 = nz = bc.dplen = bc.uflchk = 0;
dval(&rv) = 0.;
for(s = s00;;s++) switch(*s) {
switch(*(s = s00)) {
case '-':
sign = 1;
/* no break */
JQ_FALLTHROUGH;
case '+':
if (*++s)
goto break2;
break;
/* no break */
JQ_FALLTHROUGH;
case 0:
goto ret0;
case '\t':
case '\n':
case '\v':
case '\f':
case '\r':
case ' ':
continue;
default:
goto break2;
break;
}
break2:
if (*s == '0') {
#ifndef NO_HEX_FP /*{*/
switch(s[1]) {
+6 -3
View File
@@ -422,12 +422,15 @@ int main(int argc, char* argv[]) {
fprintf(stderr, "jq: --indent takes one parameter\n");
die();
}
dumpopts &= ~(JV_PRINT_TAB | JV_PRINT_INDENT_FLAGS(7));
int indent = atoi(argv[i+1]);
if (indent < -1 || indent > 7) {
char* end = NULL;
errno = 0;
long indent = strtol(argv[i+1], &end, 10);
if (errno || indent < -1 || indent > 7 ||
isspace(*argv[i+1]) || end == argv[i+1] || *end) {
fprintf(stderr, "jq: --indent takes a number between -1 and 7\n");
die();
}
dumpopts &= ~(JV_PRINT_TAB | JV_PRINT_INDENT_FLAGS(7));
dumpopts |= JV_PRINT_INDENT_FLAGS(indent);
i++;
} else if (isoption(&text, 0, "seq", is_short)) {
+2 -2
View File
@@ -2342,8 +2342,8 @@ null
2
.[] |= try tonumber
["1", "2a", "3", " 4 ", "5.67", ".89", "-876", "+5.43", 21]
[1, 3, 5.67, 0.89, -876, 5.43, 21]
["1", "2a", "3", " 4", "5 ", "6.7", ".89", "-876", "+5.43", 21]
[1, 3, 6.7, 0.89, -876, 5.43, 21]
# Also 1859, but from 2073
any(keys[]|tostring?;true)