diff options
author | ZyX <kp-pav@yandex.ru> | 2016-07-12 19:20:57 +0300 |
---|---|---|
committer | ZyX <kp-pav@yandex.ru> | 2017-03-27 00:11:27 +0300 |
commit | 9297d941e2f1576006d77bfd6391cecc3bea37b0 (patch) | |
tree | 362879f3145e47bb3b25234c5b11ce1661c60dc6 /src | |
parent | 3fa4ca81880bc5113c32a89de965ce593e9b001f (diff) | |
download | rneovim-9297d941e2f1576006d77bfd6391cecc3bea37b0.tar.gz rneovim-9297d941e2f1576006d77bfd6391cecc3bea37b0.tar.bz2 rneovim-9297d941e2f1576006d77bfd6391cecc3bea37b0.zip |
executor/converter: Fix how maxidx is determined
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/viml/executor/converter.c | 37 |
1 files changed, 30 insertions, 7 deletions
diff --git a/src/nvim/viml/executor/converter.c b/src/nvim/viml/executor/converter.c index 319e07bdbc..c8d6848006 100644 --- a/src/nvim/viml/executor/converter.c +++ b/src/nvim/viml/executor/converter.c @@ -54,8 +54,8 @@ static LuaTableProps nlua_traverse_table(lua_State *const lstate) int val_type = 0; // If has_val_key: lua type of the value. bool has_val_key = false; // True if val key was found, // @see nlua_push_val_idx(). - bool has_other = false; // True if there are keys that are not strings - // or positive integral values. + size_t other_keys_num = 0; // Number of keys that are not string, integral + // or type keys. LuaTableProps ret; memset(&ret, 0, sizeof(ret)); if (!lua_checkstack(lstate, lua_gettop(lstate) + 2)) { @@ -79,7 +79,7 @@ static LuaTableProps nlua_traverse_table(lua_State *const lstate) const lua_Number n = lua_tonumber(lstate, -2); if (n > (lua_Number)SIZE_MAX || n <= 0 || ((lua_Number)((size_t)n)) != n) { - has_other = true; + other_keys_num++; } else { const size_t idx = (size_t)n; if (idx > ret.maxidx) { @@ -99,10 +99,10 @@ static LuaTableProps nlua_traverse_table(lua_State *const lstate) has_type_key = true; ret.type = (ObjectType)n; } else { - has_other = true; + other_keys_num++; } } else { - has_other = true; + other_keys_num++; } } else { has_val_key = true; @@ -114,7 +114,7 @@ static LuaTableProps nlua_traverse_table(lua_State *const lstate) break; } default: { - has_other = true; + other_keys_num++; break; } } @@ -125,10 +125,33 @@ static LuaTableProps nlua_traverse_table(lua_State *const lstate) if (ret.type == kObjectTypeFloat && (!has_val_key || val_type != LUA_TNUMBER)) { ret.type = kObjectTypeNil; + } else if (ret.type == kObjectTypeArray) { + // Determine what is the last number in a *sequence* of keys. + // This condition makes sure that Neovim will not crash when it gets table + // {[vim.type_idx]=vim.types.array, [SIZE_MAX]=1}: without it maxidx will + // be SIZE_MAX, with this condition it should be zero and [SIZE_MAX] key + // should be ignored. + if (ret.maxidx != 0 + && ret.maxidx != (tsize + - has_type_key + - other_keys_num + - has_val_key + - ret.string_keys_num)) { + for (ret.maxidx = 0;; ret.maxidx++) { + lua_rawgeti(lstate, -1, (int)ret.maxidx + 1); + if (lua_isnil(lstate, -1)) { + lua_pop(lstate, 1); + break; + } + lua_pop(lstate, 1); + } + } } } else { if (tsize == 0 - || (tsize == ret.maxidx && !has_other && ret.string_keys_num == 0)) { + || (tsize == ret.maxidx + && other_keys_num == 0 + && ret.string_keys_num == 0)) { ret.type = kObjectTypeArray; } else if (ret.string_keys_num == tsize) { ret.type = kObjectTypeDictionary; |