xaizek / vifm (License: GPLv2+) (since 2018-12-07)
Vifm is a file manager with curses interface, which provides Vi[m]-like environment for managing objects within file systems, extended with some useful ideas from mutt.
Commit c8f9fe6858fd7f8f7d49ea22f24219a54b7e106e

Make safe mode state recursive
Otherwise, we were in trouble at least when handler in a safe
environment called something that caused redrawing which invoked other
safe handlers.
Author: xaizek
Author date (UTC): 2022-03-17 12:37
Committer name: xaizek
Committer date (UTC): 2022-03-17 12:37
Parent(s): 8641868913bcfdf5bb5b96594330eb8087269068
Signing key: 99DC5E4DB05F6BE2
Tree: 21e4de451d9e6a59b579a292e9d5328bb6eccf17
File Lines added Lines deleted
src/lua/vifm_handlers.c 9 9
src/lua/vifm_keys.c 3 2
src/lua/vifm_viewcolumns.c 3 3
src/lua/vlua_state.c 13 4
src/lua/vlua_state.h 8 3
File src/lua/vifm_handlers.c changed (mode: 100644) (index 939ba2755..511d80481)
... ... vifm_handlers_view(vlua_t *vlua, const char viewer[], const char path[],
117 117 lua_setfield(vlua->lua, -2, "height"); lua_setfield(vlua->lua, -2, "height");
118 118 } }
119 119
120 vlua_state_safe_mode_set(vlua->lua, 1);
120 const int sm_cookie = vlua_state_safe_mode_on(vlua->lua);
121 121 if(lua_pcall(vlua->lua, 1, 1, 0) != LUA_OK) if(lua_pcall(vlua->lua, 1, 1, 0) != LUA_OK)
122 122 { {
123 vlua_state_safe_mode_set(vlua->lua, 0);
123 vlua_state_safe_mode_off(vlua->lua, sm_cookie);
124 124
125 125 const char *error = lua_tostring(vlua->lua, -1); const char *error = lua_tostring(vlua->lua, -1);
126 126 ui_sb_err(error); ui_sb_err(error);
 
... ... vifm_handlers_view(vlua_t *vlua, const char viewer[], const char path[],
128 128 return result; return result;
129 129 } }
130 130
131 vlua_state_safe_mode_set(vlua->lua, 0);
131 vlua_state_safe_mode_off(vlua->lua, sm_cookie);
132 132
133 133 if(!lua_istable(vlua->lua, -1)) if(!lua_istable(vlua->lua, -1))
134 134 { {
 
... ... vifm_handlers_open(vlua_t *vlua, const char prog[],
181 181 vifmentry_new(vlua->lua, entry); vifmentry_new(vlua->lua, entry);
182 182 lua_setfield(vlua->lua, -2, "entry"); lua_setfield(vlua->lua, -2, "entry");
183 183
184 vlua_state_safe_mode_set(vlua->lua, 1);
184 const int sm_cookie = vlua_state_safe_mode_on(vlua->lua);
185 185 if(lua_pcall(vlua->lua, 1, 0, 0) != LUA_OK) if(lua_pcall(vlua->lua, 1, 0, 0) != LUA_OK)
186 186 { {
187 vlua_state_safe_mode_set(vlua->lua, 0);
187 vlua_state_safe_mode_off(vlua->lua, sm_cookie);
188 188
189 189 const char *error = lua_tostring(vlua->lua, -1); const char *error = lua_tostring(vlua->lua, -1);
190 190 ui_sb_err(error); ui_sb_err(error);
 
... ... vifm_handlers_open(vlua_t *vlua, const char prog[],
192 192 return; return;
193 193 } }
194 194
195 vlua_state_safe_mode_set(vlua->lua, 0);
195 vlua_state_safe_mode_off(vlua->lua, sm_cookie);
196 196 lua_pop(vlua->lua, 2); lua_pop(vlua->lua, 2);
197 197 } }
198 198
 
... ... vifm_handlers_make_status_line(vlua_t *vlua, const char format[],
223 223 lua_pushinteger(vlua->lua, width); lua_pushinteger(vlua->lua, width);
224 224 lua_setfield(vlua->lua, -2, "width"); lua_setfield(vlua->lua, -2, "width");
225 225
226 vlua_state_safe_mode_set(vlua->lua, 1);
226 const int sm_cookie = vlua_state_safe_mode_on(vlua->lua);
227 227 if(lua_pcall(vlua->lua, 1, 1, 0) != LUA_OK) if(lua_pcall(vlua->lua, 1, 1, 0) != LUA_OK)
228 228 { {
229 vlua_state_safe_mode_set(vlua->lua, 0);
229 vlua_state_safe_mode_off(vlua->lua, sm_cookie);
230 230
231 231 char *error = strdup(lua_tostring(vlua->lua, -1)); char *error = strdup(lua_tostring(vlua->lua, -1));
232 232 lua_pop(vlua->lua, 3); lua_pop(vlua->lua, 3);
233 233 return error; return error;
234 234 } }
235 235
236 vlua_state_safe_mode_set(vlua->lua, 0);
236 vlua_state_safe_mode_off(vlua->lua, sm_cookie);
237 237
238 238 if(!lua_istable(vlua->lua, -1)) if(!lua_istable(vlua->lua, -1))
239 239 { {
File src/lua/vifm_keys.c changed (mode: 100644) (index 8aacb1f09..c49ba3e32)
... ... lua_key_handler(key_info_t key_info, keys_info_t *keys_info)
218 218
219 219 curr_stats.save_msg = 0; curr_stats.save_msg = 0;
220 220
221 int sm_cookie;
221 222 if(is_selector) if(is_selector)
222 223 { {
223 vlua_state_safe_mode_set(lua, 1);
224 sm_cookie = vlua_state_safe_mode_on(lua);
224 225 } }
225 226
226 227 int result = lua_pcall(lua, 1, 1, 0); int result = lua_pcall(lua, 1, 1, 0);
227 228
228 229 if(is_selector) if(is_selector)
229 230 { {
230 vlua_state_safe_mode_set(lua, 0);
231 vlua_state_safe_mode_off(lua, sm_cookie);
231 232 } }
232 233
233 234 if(result != LUA_OK) if(result != LUA_OK)
File src/lua/vifm_viewcolumns.c changed (mode: 100644) (index 77420d0f4..da07e0bd7)
... ... lua_viewcolumn_handler(void *data, size_t buf_len, char buf[],
202 202 cdt->match_from = 0; cdt->match_from = 0;
203 203 cdt->match_to = 0; cdt->match_to = 0;
204 204
205 vlua_state_safe_mode_set(lua, 1);
205 const int sm_cookie = vlua_state_safe_mode_on(lua);
206 206 if(lua_pcall(lua, 1, 1, 0) != LUA_OK) if(lua_pcall(lua, 1, 1, 0) != LUA_OK)
207 207 { {
208 vlua_state_safe_mode_set(lua, 0);
208 vlua_state_safe_mode_off(lua, sm_cookie);
209 209
210 210 const char *error = lua_tostring(lua, -1); const char *error = lua_tostring(lua, -1);
211 211 ui_sb_err(error); ui_sb_err(error);
 
... ... lua_viewcolumn_handler(void *data, size_t buf_len, char buf[],
214 214 return; return;
215 215 } }
216 216
217 vlua_state_safe_mode_set(lua, 0);
217 vlua_state_safe_mode_off(lua, sm_cookie);
218 218
219 219 if(!lua_istable(lua, -1)) if(!lua_istable(lua, -1))
220 220 { {
File src/lua/vlua_state.c changed (mode: 100644) (index e3c0d00e9..7b2ceb1ad)
... ... vlua_state_get_table(vlua_t *vlua, void *key)
144 144 lua_gettable(vlua->lua, LUA_REGISTRYINDEX); lua_gettable(vlua->lua, LUA_REGISTRYINDEX);
145 145 } }
146 146
147 int
148 vlua_state_safe_mode_on(lua_State *lua)
149 {
150 vlua_t *vlua = get_state(lua);
151 return vlua->safe_mode_level++;
152 }
153
147 154 void void
148 vlua_state_safe_mode_set(lua_State *lua, int safe_mode)
155 vlua_state_safe_mode_off(lua_State *lua, int cookie)
149 156 { {
150 157 vlua_t *vlua = get_state(lua); vlua_t *vlua = get_state(lua);
151 assert(vlua->is_safe_mode_on != safe_mode && "Mismatched safe mode change!");
152 vlua->is_safe_mode_on = safe_mode;
158 --vlua->safe_mode_level;
159
160 assert(vlua->safe_mode_level == cookie && "Mismatched safe mode change!");
161 assert(vlua->safe_mode_level >= 0 && "Can't disabled disabled safe mode!");
153 162 } }
154 163
155 164 int int
156 165 vlua_state_proxy_call(lua_State *lua, int (*call)(lua_State *lua)) vlua_state_proxy_call(lua_State *lua, int (*call)(lua_State *lua))
157 166 { {
158 if(get_state(lua)->is_safe_mode_on)
167 if(get_state(lua)->safe_mode_level != 0)
159 168 { {
160 169 return luaL_error(lua, "%s", return luaL_error(lua, "%s",
161 170 "Unsafe functions can't be called in this environment!"); "Unsafe functions can't be called in this environment!");
File src/lua/vlua_state.h changed (mode: 100644) (index 98e9b71c4..9ad145ed8)
... ... struct vlua_t
43 43
44 44 strlist_t strings; /* Interned strings. */ strlist_t strings; /* Interned strings. */
45 45
46 int is_safe_mode_on; /* Whether API must be limited to safe calls. */
46 int safe_mode_level; /* When non-zero, API is limited to safe calls. */
47 47 }; };
48 48
49 49 /* Creates new empty state. Returns the state or NULL. */ /* Creates new empty state. Returns the state or NULL. */
 
... ... void vlua_state_make_table(vlua_t *vlua, void *key);
70 70 * the top of the stack. */ * the top of the stack. */
71 71 void vlua_state_get_table(vlua_t *vlua, void *key); void vlua_state_get_table(vlua_t *vlua, void *key);
72 72
73 /* Enables or disables safe mode. */
74 void vlua_state_safe_mode_set(struct lua_State *lua, int safe_mode);
73 /* Enables safe mode if it's not already on. Returns cookie value to be passed
74 * to vlua_state_safe_mode_off(). */
75 int vlua_state_safe_mode_on(struct lua_State *lua);
76
77 /* Disables safe mode. Accepts cookie from a corresponding call to
78 * vlua_state_safe_mode_on(). */
79 void vlua_state_safe_mode_off(struct lua_State *lua, int cookie);
75 80
76 81 /* Runs a Lua C function if it's allowed to run in current context. */ /* Runs a Lua C function if it's allowed to run in current context. */
77 82 int vlua_state_proxy_call(struct lua_State *lua, int vlua_state_proxy_call(struct lua_State *lua,
Hints

Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://code.reversed.top/user/xaizek/vifm

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@code.reversed.top/user/xaizek/vifm

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a pull request:
... clone the repository ...
... make some changes and some commits ...
git push origin master