neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

commit da650de277b0ce3e3901e847c489ef0e2b419d13
parent 5377cd34a963fa5dedb609d67a7ab17e2e8704ef
Author: James McCoy <jamessan@jamessan.com>
Date:   Wed, 10 Sep 2025 23:46:08 -0400

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`.
Diffstat:
Msrc/cjson/lua_cjson.c | 10+++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/src/cjson/lua_cjson.c b/src/cjson/lua_cjson.c @@ -1359,7 +1359,7 @@ static void json_next_number_token(json_parse_t *json, json_token_t *token) { 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' || *endptr == 'E' || *endptr == 'x') { 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"); 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 { token->type = T_INTEGER; + token->value.integer = tmpval; } json->ptr = endptr; /* Skip the processed number */