Skip to content

Commit 9ac6dda

Browse files
authored
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.
1 parent aaace54 commit 9ac6dda

File tree

3 files changed

+11
-16
lines changed

3 files changed

+11
-16
lines changed

src/jv_dtoa.c

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2368,29 +2368,21 @@ jvp_strtod
23682368

23692369
sign = nz0 = nz1 = nz = bc.dplen = bc.uflchk = 0;
23702370
dval(&rv) = 0.;
2371-
for(s = s00;;s++) switch(*s) {
2371+
switch(*(s = s00)) {
23722372
case '-':
23732373
sign = 1;
23742374
/* no break */
23752375
JQ_FALLTHROUGH;
23762376
case '+':
23772377
if (*++s)
2378-
goto break2;
2378+
break;
23792379
/* no break */
23802380
JQ_FALLTHROUGH;
23812381
case 0:
23822382
goto ret0;
2383-
case '\t':
2384-
case '\n':
2385-
case '\v':
2386-
case '\f':
2387-
case '\r':
2388-
case ' ':
2389-
continue;
23902383
default:
2391-
goto break2;
2384+
break;
23922385
}
2393-
break2:
23942386
if (*s == '0') {
23952387
#ifndef NO_HEX_FP /*{*/
23962388
switch(s[1]) {

src/main.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -422,12 +422,15 @@ int main(int argc, char* argv[]) {
422422
fprintf(stderr, "jq: --indent takes one parameter\n");
423423
die();
424424
}
425-
dumpopts &= ~(JV_PRINT_TAB | JV_PRINT_INDENT_FLAGS(7));
426-
int indent = atoi(argv[i+1]);
427-
if (indent < -1 || indent > 7) {
425+
char* end = NULL;
426+
errno = 0;
427+
long indent = strtol(argv[i+1], &end, 10);
428+
if (errno || indent < -1 || indent > 7 ||
429+
isspace(*argv[i+1]) || end == argv[i+1] || *end) {
428430
fprintf(stderr, "jq: --indent takes a number between -1 and 7\n");
429431
die();
430432
}
433+
dumpopts &= ~(JV_PRINT_TAB | JV_PRINT_INDENT_FLAGS(7));
431434
dumpopts |= JV_PRINT_INDENT_FLAGS(indent);
432435
i++;
433436
} else if (isoption(&text, 0, "seq", is_short)) {

tests/jq.test

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2342,8 +2342,8 @@ null
23422342
2
23432343

23442344
.[] |= try tonumber
2345-
["1", "2a", "3", " 4 ", "5.67", ".89", "-876", "+5.43", 21]
2346-
[1, 3, 5.67, 0.89, -876, 5.43, 21]
2345+
["1", "2a", "3", " 4", "5 ", "6.7", ".89", "-876", "+5.43", 21]
2346+
[1, 3, 6.7, 0.89, -876, 5.43, 21]
23472347

23482348
# Also 1859, but from 2073
23492349
any(keys[]|tostring?;true)

0 commit comments

Comments
 (0)