From fc0bfce6d2b6a7253f6462347fbbbce0825d1ebd Mon Sep 17 00:00:00 2001 From: xaizek Date: Thu, 9 May 2024 00:21:56 +0300 Subject: Fix formatting in vlua_cmn_check_opt_field() Missing space after a comma. --- src/lua/common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lua/common.c b/src/lua/common.c index 51d169d6c..9b36d5c0b 100644 --- a/src/lua/common.c +++ b/src/lua/common.c @@ -76,7 +76,7 @@ vlua_cmn_check_opt_field(lua_State *lua, int table_idx, const char name[], if(type != lua_type) { - return luaL_error(lua, "`%s` value must be a %s",name, + return luaL_error(lua, "`%s` value must be a %s", name, lua_typename(lua, lua_type)); } return 1; -- cgit v1.2.3 From 73fcadbdf42bba19f6c3486b7c44c9124dcf0e84 Mon Sep 17 00:00:00 2001 From: xaizek Date: Thu, 9 May 2024 00:22:30 +0300 Subject: Explain what jobs_key is used for in detail Otherwise one has to deduce it from code. --- src/lua/vifmjob.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/lua/vifmjob.c b/src/lua/vifmjob.c index aa3b7dedf..18bf7d8d3 100644 --- a/src/lua/vifmjob.c +++ b/src/lua/vifmjob.c @@ -81,7 +81,12 @@ static const luaL_Reg vifmjob_methods[] = { { NULL, NULL } }; -/* Address of this variable serves as a key in Lua table. */ +/* + * Address of this variable serves as a key in Lua table which maps VifmJob + * instances onto dictionary with such fields: + * - "obj" - vifm_job_t user data + * - "on_exit" - Lua callback to invoke when the job is done + */ static char jobs_key; void -- cgit v1.2.3 From 83d1c89dfd26decc037331ecafe7349e315e0c7f Mon Sep 17 00:00:00 2001 From: xaizek Date: Thu, 9 May 2024 00:24:43 +0300 Subject: Introduce vlua_cmn_check_this() A wrapper for lua_touserdata() to not blindly assume the value isn't NULL. Unlikely to be very useful, but might catch a mistake during development. Thanks to ZhipengXue97. See #979 on GitHub. --- src/lua/common.c | 12 ++++++++++++ src/lua/common.h | 5 +++++ src/lua/vifmentry.c | 4 ++-- src/lua/vifmview.c | 16 ++++++++-------- 4 files changed, 27 insertions(+), 10 deletions(-) diff --git a/src/lua/common.c b/src/lua/common.c index 9b36d5c0b..553aaea75 100644 --- a/src/lua/common.c +++ b/src/lua/common.c @@ -82,6 +82,18 @@ vlua_cmn_check_opt_field(lua_State *lua, int table_idx, const char name[], return 1; } +void * +vlua_cmn_check_this(lua_State *lua, int idx) +{ + void *udata = lua_touserdata(lua, idx); + if(udata == NULL) + { + const char *type = lua_typename(lua, lua_type(lua, idx)); + luaL_error(lua, "Value at %d must be user data, got %s", idx, type); + } + return udata; +} + void * vlua_cmn_to_pointer(lua_State *lua) { diff --git a/src/lua/common.h b/src/lua/common.h index bfd7e9f5a..acd6a2219 100644 --- a/src/lua/common.h +++ b/src/lua/common.h @@ -39,6 +39,11 @@ void vlua_cmn_check_field(struct lua_State *lua, int table_idx, int vlua_cmn_check_opt_field(struct lua_State *lua, int table_idx, const char name[], int lua_type); +/* Retrieves user data from a specified stack index aborting (Lua does + * longjmp()) if it's missing or isn't user data. Returns user data pointer, + * never NULL. */ +void * vlua_cmn_check_this(struct lua_State *lua, int idx); + /* Converts Lua value at the top of the stack into a C pointer without popping * it. Returns the pointer. */ void * vlua_cmn_to_pointer(struct lua_State *lua); diff --git a/src/lua/vifmentry.c b/src/lua/vifmentry.c index e50fe5bcb..1263c8e8f 100644 --- a/src/lua/vifmentry.c +++ b/src/lua/vifmentry.c @@ -137,7 +137,7 @@ VLUA_API(vifmentry_gc)(lua_State *lua) static int VLUA_API(vifmentry_gettarget)(lua_State *lua) { - vifm_entry_t *vifm_entry = lua_touserdata(lua, lua_upvalueindex(1)); + vifm_entry_t *vifm_entry = vlua_cmn_check_this(lua, lua_upvalueindex(1)); if(vifm_entry->type != FT_LINK) { @@ -158,7 +158,7 @@ VLUA_API(vifmentry_gettarget)(lua_State *lua) static int VLUA_API(vifmentry_mimetype)(lua_State *lua) { - vifm_entry_t *vifm_entry = lua_touserdata(lua, lua_upvalueindex(1)); + vifm_entry_t *vifm_entry = vlua_cmn_check_this(lua, lua_upvalueindex(1)); const char *mimetype = get_mimetype(vifm_entry->full_path, /*resolve_symlinks=*/1); diff --git a/src/lua/vifmview.c b/src/lua/vifmview.c index 4ee77bd9e..8a174ff18 100644 --- a/src/lua/vifmview.c +++ b/src/lua/vifmview.c @@ -198,14 +198,14 @@ VLUA_API(cursor_index)(lua_State *lua) const char *key = luaL_checkstring(lua, 2); if(strcmp(key, "pos") == 0) { - const unsigned int *id = lua_touserdata(lua, 1); + const unsigned int *id = vlua_cmn_check_this(lua, 1); view_t *view = find_view(lua, *id); lua_pushinteger(lua, view->list_pos + 1); return 1; } else if(strcmp(key, "entry") == 0) { - unsigned int *id = lua_touserdata(lua, 1); + unsigned int *id = vlua_cmn_check_this(lua, 1); lua_pushlightuserdata(lua, id); lua_pushcclosure(lua, VLUA_REF(cursor_entry), 1); return 1; @@ -225,7 +225,7 @@ VLUA_API(cursor_newindex)(lua_State *lua) { return 0; } - const unsigned int *id = lua_touserdata(lua, 1); + const unsigned int *id = vlua_cmn_check_this(lua, 1); view_t *view = find_view(lua, *id); const int pos = luaL_checkinteger(lua, 3) - 1; fpos_set_pos(view, pos); @@ -253,7 +253,7 @@ VLUA_API(cursor_newindex)(lua_State *lua) static int VLUA_API(cursor_entry)(lua_State *lua) { - const unsigned int *id = lua_touserdata(lua, lua_upvalueindex(1)); + const unsigned int *id = vlua_cmn_check_this(lua, lua_upvalueindex(1)); view_t *view = find_view(lua, *id); vifmentry_new(lua, &view->dir_entry[view->list_pos]); return 1; @@ -340,7 +340,7 @@ VLUA_API(locopts_newindex)(lua_State *lua) static int do_opt(lua_State *lua, opt_t *opt, int set) { - const unsigned int *id = lua_touserdata(lua, 1); + const unsigned int *id = vlua_cmn_check_this(lua, 1); view_t *view = find_view(lua, *id); if(view == curr_view) @@ -379,7 +379,7 @@ do_opt(lua_State *lua, opt_t *opt, int set) static int VLUA_IMPL(restore_curr_view)(lua_State *lua) { - view_t *curr = lua_touserdata(lua, lua_upvalueindex(1)); + view_t *curr = vlua_cmn_check_this(lua, lua_upvalueindex(1)); curr_view = curr; load_view_options(curr_view); return 1; @@ -389,7 +389,7 @@ VLUA_IMPL(restore_curr_view)(lua_State *lua) static int VLUA_IMPL(get_opt_wrapper)(lua_State *lua) { - opt_t *opt = lua_touserdata(lua, 1); + opt_t *opt = vlua_cmn_check_this(lua, 1); return vlua_cmn_get_opt(lua, opt); } @@ -397,7 +397,7 @@ VLUA_IMPL(get_opt_wrapper)(lua_State *lua) static int VLUA_IMPL(set_opt_wrapper)(lua_State *lua) { - opt_t *opt = lua_touserdata(lua, 1); + opt_t *opt = vlua_cmn_check_this(lua, 1); return vlua_cmn_set_opt(lua, opt); } -- cgit v1.2.3 From ee3a265673f20f574a3b9e66e3a45272a747b91c Mon Sep 17 00:00:00 2001 From: xaizek Date: Thu, 9 May 2024 00:27:11 +0300 Subject: Add some asserts after lua_touserdata() To not blindly assume the value isn't NULL. Unlikely to be very useful, but might catch a mistake during development. Thanks to ZhipengXue97. See #979 on GitHub. --- src/lua/vifmjob.c | 2 ++ src/lua/vlua_state.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/lua/vifmjob.c b/src/lua/vifmjob.c index 18bf7d8d3..47a465e97 100644 --- a/src/lua/vifmjob.c +++ b/src/lua/vifmjob.c @@ -109,6 +109,7 @@ vifmjob_finish(lua_State *lua) lua_pop(lua, 1); bg_job_t *job = lua_touserdata(lua, -1); + assert(job != NULL && "List of Lua jobs includes a bad key!"); bg_job_set_exit_cb(job, NULL, NULL); } @@ -215,6 +216,7 @@ job_exit_cb(struct bg_job_t *job, void *arg) lua_getfield(vlua->lua, -2, "obj"); vifm_job_t *vifm_job = lua_touserdata(vlua->lua, -1); + assert(vifm_job != NULL && "List of Lua jobs is includes bad element!"); /* Remove the table entry we've just used. */ lua_pushlightuserdata(vlua->lua, job); diff --git a/src/lua/vlua_state.c b/src/lua/vlua_state.c index 07015c860..1f44f5ba8 100644 --- a/src/lua/vlua_state.c +++ b/src/lua/vlua_state.c @@ -126,6 +126,8 @@ vlua_state_get(lua_State *lua) lua_gettable(lua, LUA_REGISTRYINDEX); vlua_t *vlua = lua_touserdata(lua, -1); lua_pop(lua, 1); + + assert(vlua != NULL && "Failed to obtain vlua state!"); return vlua; } -- cgit v1.2.3 From a95454562e181ee71c1944b026c60320bed774e2 Mon Sep 17 00:00:00 2001 From: xaizek Date: Thu, 9 May 2024 18:58:37 +0300 Subject: Document error handling of transform_wide_str() Not that it wasn't documented, but it was lacking in clarity and completeness. --- src/utils/str.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/utils/str.c b/src/utils/str.c index 9f951ca75..68522aadc 100644 --- a/src/utils/str.c +++ b/src/utils/str.c @@ -291,8 +291,9 @@ transform_ascii_str(const char str[], int (*f)(int), char buf[], size_t buf_len) } /* Transforms characters of the string to while they fit in the buffer by - * calling specified function on them. Returns zero on success or non-zero if - * output buffer is too small. */ + * calling specified function on them. Returns zero on success or non-zero on + * error (output buffer is too small or out of memory) in which case buffer is + * filled with full UTF-8 characters from input. */ static int transform_wide_str(const char str[], wint_t (*f)(wint_t), char buf[], size_t buf_len) -- cgit v1.2.3 From c7dd6d816e59e522e10133b67c1af2b053c83f39 Mon Sep 17 00:00:00 2001 From: xaizek Date: Thu, 9 May 2024 19:00:09 +0300 Subject: Handle one more NULL in transform_wide_str() Only one of two possible memory allocation errors were handled. Thanks to ZhipengXue97. See #979 on GitHub. --- src/utils/str.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/utils/str.c b/src/utils/str.c index 68522aadc..a18ab62d7 100644 --- a/src/utils/str.c +++ b/src/utils/str.c @@ -319,6 +319,13 @@ transform_wide_str(const char str[], wint_t (*f)(wint_t), char buf[], } narrow = to_multibyte(wstring); + if(narrow == NULL) + { + free(wstring); + (void)utf8_strcpy(buf, str, buf_len); + return 1; + } + copied = utf8_strcpy(buf, narrow, buf_len); error = copied == 0U || narrow[copied - 1U] != '\0'; -- cgit v1.2.3 From 26f0ea71bde7d3e5f66a36e25532ad301fd1dabc Mon Sep 17 00:00:00 2001 From: xaizek Date: Thu, 9 May 2024 19:02:42 +0300 Subject: Improve body of utils/str.c:transform_wide_str() Variable declarations and when memory is freed. --- src/utils/str.c | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/src/utils/str.c b/src/utils/str.c index a18ab62d7..d85e36df3 100644 --- a/src/utils/str.c +++ b/src/utils/str.c @@ -298,38 +298,31 @@ static int transform_wide_str(const char str[], wint_t (*f)(wint_t), char buf[], size_t buf_len) { - size_t copied; - int error; - wchar_t *wstring; - wchar_t *p; - char *narrow; - - wstring = to_wide(str); + wchar_t *wstring = to_wide(str); if(wstring == NULL) { (void)utf8_strcpy(buf, str, buf_len); return 1; } - p = wstring; + wchar_t *p = wstring; while(*p != L'\0') { *p = f(*p); ++p; } - narrow = to_multibyte(wstring); + char *narrow = to_multibyte(wstring); + free(wstring); + if(narrow == NULL) { - free(wstring); (void)utf8_strcpy(buf, str, buf_len); return 1; } - copied = utf8_strcpy(buf, narrow, buf_len); - error = copied == 0U || narrow[copied - 1U] != '\0'; - - free(wstring); + size_t copied = utf8_strcpy(buf, narrow, buf_len); + int error = (copied == 0U || narrow[copied - 1U] != '\0'); free(narrow); return error; -- cgit v1.2.3 From 19e177315cab99f0a58b7b0f21acd2e155b03e64 Mon Sep 17 00:00:00 2001 From: xaizek Date: Thu, 9 May 2024 19:06:22 +0300 Subject: Handle OOM error in cmd_handlers.c:mark_cmd() Thanks to ZhipengXue97. See #979 on GitHub. --- src/cmd_handlers.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/cmd_handlers.c b/src/cmd_handlers.c index 79df65ef0..ea32df303 100644 --- a/src/cmd_handlers.c +++ b/src/cmd_handlers.c @@ -3701,6 +3701,11 @@ mark_cmd(const cmd_info_t *cmd_info) } expanded_path = expand_tilde(cmd_info->argv[1]); + if(expanded_path == NULL) + { + return CMDS_ERR_NO_MEM; + } + if(!is_path_absolute(expanded_path)) { free(expanded_path); -- cgit v1.2.3 From 1da93d1236c8652bfd40c8a2ff61068d8e15150e Mon Sep 17 00:00:00 2001 From: xaizek Date: Thu, 9 May 2024 19:06:56 +0300 Subject: Handle OOM error in escape_cmd_for_pasting() Thanks to ZhipengXue97. See #979 on GitHub. --- src/modes/cmdline.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/modes/cmdline.c b/src/modes/cmdline.c index ca003a0d5..819556bb4 100644 --- a/src/modes/cmdline.c +++ b/src/modes/cmdline.c @@ -2368,6 +2368,11 @@ escape_cmd_for_pasting(const char str[]) char *mb_input; char *escaped; + if(wide_input == NULL) + { + return NULL; + } + wide_input[input_stat.index] = L'\0'; mb_input = to_multibyte(wide_input); -- cgit v1.2.3 From c1cc08111402542ee920c20f517e3438475daaf0 Mon Sep 17 00:00:00 2001 From: xaizek Date: Thu, 9 May 2024 19:08:26 +0300 Subject: Improve body of cmdline.c:escape_cmd_for_pasting() Variable declarations and when memory is freed. --- src/modes/cmdline.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/modes/cmdline.c b/src/modes/cmdline.c index 819556bb4..718222e75 100644 --- a/src/modes/cmdline.c +++ b/src/modes/cmdline.c @@ -2365,21 +2365,17 @@ static char * escape_cmd_for_pasting(const char str[]) { wchar_t *const wide_input = vifm_wcsdup(input_stat.line); - char *mb_input; - char *escaped; - if(wide_input == NULL) { return NULL; } wide_input[input_stat.index] = L'\0'; - mb_input = to_multibyte(wide_input); - - escaped = cmds_insertion_escape(mb_input, strlen(mb_input), str); + char *mb_input = to_multibyte(wide_input); + free(wide_input); + char *escaped = cmds_insertion_escape(mb_input, strlen(mb_input), str); free(mb_input); - free(wide_input); return escaped; } -- cgit v1.2.3