mirror of
https://github.com/neovim/neovim.git
synced 2025-12-17 11:55:34 +00:00
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`.
This commit is contained in:
10
src/cjson/lua_cjson.c
vendored
10
src/cjson/lua_cjson.c
vendored
@@ -1359,7 +1359,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;
|
||||||
@@ -1368,8 +1368,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 */
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user