fix(vim.json): fix truncation of decoded numbers outside lua_Integer's range #35702

PR #34876 expanded the total range of values that cjson considers
valid. However, it didn't address the bigger problem of storing a
`long long` value in a `lua_Integer` (which is typically a typedef for
`ptrdiff_t`).

On 32-bit platforms, this ends up storing an 8-byte number into a 4-byte
variable, truncating the value.

Store the converted value in a temporary `long long` variable so we can
detect the scenario and decode into a `lua_Number`.

(cherry picked from commit da650de277)
This commit is contained in:
James McCoy
2025-09-10 23:46:08 -04:00
committed by github-actions[bot]
parent 5c6ea43da8
commit 1c8805e3b2

10
src/cjson/lua_cjson.c vendored
View File

@@ -1293,7 +1293,7 @@ static void json_next_number_token(json_parse_t *json, json_token_t *token)
{ {
char *endptr; char *endptr;
token->value.integer = strtoll(json->ptr, &endptr, 10); long long tmpval = strtoll(json->ptr, &endptr, 10);
if (json->ptr == endptr || *endptr == '.' || *endptr == 'e' || if (json->ptr == endptr || *endptr == '.' || *endptr == 'e' ||
*endptr == 'E' || *endptr == 'x') { *endptr == 'E' || *endptr == 'x') {
token->type = T_NUMBER; token->type = T_NUMBER;
@@ -1302,8 +1302,16 @@ static void json_next_number_token(json_parse_t *json, json_token_t *token)
json_set_token_error(token, json, "invalid number"); json_set_token_error(token, json, "invalid number");
return; return;
} }
} else if (tmpval > PTRDIFF_MAX || tmpval < PTRDIFF_MIN) {
/* Typical Lua builds typedef ptrdiff_t to lua_Integer. If tmpval is
* outside the range of that type, we need to use T_NUMBER to avoid
* truncation.
*/
token->type = T_NUMBER;
token->value.number = tmpval;
} else { } else {
token->type = T_INTEGER; token->type = T_INTEGER;
token->value.integer = tmpval;
} }
json->ptr = endptr; /* Skip the processed number */ json->ptr = endptr; /* Skip the processed number */