From ef6641ba6952fd868d3efafb2a23234ac9bd0d3f Mon Sep 17 00:00:00 2001 From: ZyX Date: Tue, 15 Aug 2017 16:30:32 +0300 Subject: lua/executor: Make stricmp function work with strings with NULs --- src/nvim/lua/executor.c | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c index eb821f7831..4ed477ea36 100644 --- a/src/nvim/lua/executor.c +++ b/src/nvim/lua/executor.c @@ -124,9 +124,36 @@ static void nlua_error(lua_State *const lstate, const char *const msg) /// omitted. static int nlua_stricmp(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL { - const char *s1 = luaL_checklstring(lstate, 1, NULL); - const char *s2 = luaL_checklstring(lstate, 2, NULL); - const int ret = STRICMP(s1, s2); + size_t s1_len; + size_t s2_len; + const char *s1 = luaL_checklstring(lstate, 1, &s1_len); + const char *s2 = luaL_checklstring(lstate, 2, &s2_len); + char *nul1; + char *nul2; + int ret = 0; + assert(s1[s1_len] == NUL); + assert(s2[s2_len] == NUL); + do { + nul1 = memchr(s1, NUL, s1_len); + nul2 = memchr(s2, NUL, s2_len); + ret = STRICMP(s1, s2); + // Compare "a\0" greater then "a". + if (ret == 0 && (nul1 == NULL) != (nul2 == NULL)) { + ret = ((nul1 != NULL) - (nul2 != NULL)); + break; + } + if (nul1 != NULL) { + assert(nul2 != NULL); + // Due to lowercase letter having possibly different byte length then + // uppercase letter can’t shift both strings by the same amount of bytes. + s1_len -= (size_t)(nul1 - s1) + 1; + s2_len -= (size_t)(nul2 - s2) + 1; + s1 = nul1 + 1; + s2 = nul2 + 1; + } else { + break; + } + } while (ret == 0); lua_pop(lstate, 2); lua_pushnumber(lstate, (lua_Number)((ret > 0) - (ret < 0))); return 1; -- cgit From 93ef823f5e5347e685b4a69fff487278d0b4ed87 Mon Sep 17 00:00:00 2001 From: ZyX Date: Tue, 15 Aug 2017 16:32:06 +0300 Subject: lua/executor: Move stricmp to vim “module” and document it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/nvim/lua/executor.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c index 4ed477ea36..90333be541 100644 --- a/src/nvim/lua/executor.c +++ b/src/nvim/lua/executor.c @@ -281,10 +281,6 @@ static int nlua_exec_lua_file(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL /// Called by lua interpreter itself to initialize state. static int nlua_state_init(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL { - // stricmp - lua_pushcfunction(lstate, &nlua_stricmp); - lua_setglobal(lstate, "stricmp"); - // print lua_pushcfunction(lstate, &nlua_print); lua_setglobal(lstate, "print"); @@ -304,6 +300,10 @@ static int nlua_state_init(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL nlua_add_api_functions(lstate); // vim.types, vim.type_idx, vim.val_idx nlua_init_types(lstate); + // stricmp + lua_pushcfunction(lstate, &nlua_stricmp); + lua_setfield(lstate, -2, "stricmp"); + lua_setglobal(lstate, "vim"); return 0; } -- cgit From b1a8dcefeee0bb999a350de2cc38fc08df679bf6 Mon Sep 17 00:00:00 2001 From: ZyX Date: Tue, 15 Aug 2017 16:41:43 +0300 Subject: lua/executor: Fix crash when first string contains NUL and second not --- src/nvim/lua/executor.c | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c index 90333be541..54973a6e94 100644 --- a/src/nvim/lua/executor.c +++ b/src/nvim/lua/executor.c @@ -137,23 +137,28 @@ static int nlua_stricmp(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL nul1 = memchr(s1, NUL, s1_len); nul2 = memchr(s2, NUL, s2_len); ret = STRICMP(s1, s2); - // Compare "a\0" greater then "a". - if (ret == 0 && (nul1 == NULL) != (nul2 == NULL)) { - ret = ((nul1 != NULL) - (nul2 != NULL)); - break; - } - if (nul1 != NULL) { - assert(nul2 != NULL); - // Due to lowercase letter having possibly different byte length then - // uppercase letter can’t shift both strings by the same amount of bytes. - s1_len -= (size_t)(nul1 - s1) + 1; - s2_len -= (size_t)(nul2 - s2) + 1; - s1 = nul1 + 1; - s2 = nul2 + 1; + if (ret == 0) { + // Compare "a\0" greater then "a". + if ((nul1 == NULL) != (nul2 == NULL)) { + ret = ((nul1 != NULL) - (nul2 != NULL)); + break; + } + if (nul1 != NULL) { + assert(nul2 != NULL); + // Due to lowercase letter having possibly different byte length then + // uppercase letter can’t shift both strings by the same amount of + // bytes. + s1_len -= (size_t)(nul1 - s1) + 1; + s2_len -= (size_t)(nul2 - s2) + 1; + s1 = nul1 + 1; + s2 = nul2 + 1; + } else { + break; + } } else { break; } - } while (ret == 0); + } while (true); lua_pop(lstate, 2); lua_pushnumber(lstate, (lua_Number)((ret > 0) - (ret < 0))); return 1; -- cgit