Re-add os.rename and os.remove support
This commit is contained in:
parent
4c31c950c5
commit
54ea61fe58
|
@ -1692,7 +1692,8 @@ title = Save Selection (.msk file)
|
|||
[script_access]
|
||||
title = Security
|
||||
script_label = The following script:
|
||||
file_label = wants to access to this file:
|
||||
file_label = wants to access this file:
|
||||
file_write_label = wants to write to this file:
|
||||
command_label = wants to execute the following command:
|
||||
websocket_label = wants to open a WebSocket connection to this URL:
|
||||
clipboard_label = wants to access the system clipboard
|
||||
|
|
|
@ -40,6 +40,8 @@ int secure_io_lines(lua_State* L);
|
|||
int secure_io_input(lua_State* L);
|
||||
int secure_io_output(lua_State* L);
|
||||
int secure_os_execute(lua_State* L);
|
||||
int secure_os_remove(lua_State* L);
|
||||
int secure_os_rename(lua_State* L);
|
||||
int secure_package_loadlib(lua_State* L);
|
||||
|
||||
enum {
|
||||
|
@ -49,6 +51,8 @@ enum {
|
|||
io_input,
|
||||
io_output,
|
||||
os_execute,
|
||||
os_remove,
|
||||
os_rename,
|
||||
package_loadlib,
|
||||
};
|
||||
|
||||
|
@ -64,6 +68,8 @@ static struct {
|
|||
{ "io", "input", secure_io_input },
|
||||
{ "io", "output", secure_io_output },
|
||||
{ "os", "execute", secure_os_execute },
|
||||
{ "os", "remove", secure_os_remove },
|
||||
{ "os", "rename", secure_os_rename },
|
||||
{ "package", "loadlib", secure_package_loadlib },
|
||||
};
|
||||
|
||||
|
@ -185,6 +191,81 @@ int secure_os_execute(lua_State* L)
|
|||
return replaced_functions[os_execute].origfunc(L);
|
||||
}
|
||||
|
||||
int file_result(lua_State* L, bool result, int errorNo = 0, const std::string& fileName = "")
|
||||
{
|
||||
if (result) {
|
||||
lua_pushboolean(L, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
luaL_pushfail(L);
|
||||
if (fileName.empty())
|
||||
lua_pushstring(L, strerror(errorNo));
|
||||
else
|
||||
lua_pushfstring(L, "%s: %s", fileName.c_str(), strerror(errorNo));
|
||||
lua_pushinteger(L, errorNo);
|
||||
return 3;
|
||||
}
|
||||
|
||||
int secure_os_remove(lua_State* L)
|
||||
{
|
||||
const std::string absFilename = base::get_canonical_path(luaL_checkstring(L, 1));
|
||||
if (absFilename.empty())
|
||||
return file_result(L, false, ENOENT, absFilename);
|
||||
|
||||
if (!ask_access(L, absFilename.data(), FileAccessMode::Write, ResourceType::File))
|
||||
return file_result(L, false, EACCES, absFilename);
|
||||
|
||||
if (base::is_directory(absFilename)) {
|
||||
try {
|
||||
base::remove_directory(absFilename);
|
||||
return file_result(L, true);
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
return file_result(L, false, EIO, absFilename);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
base::delete_file(absFilename);
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
return file_result(L, false, EIO, absFilename);
|
||||
}
|
||||
|
||||
return file_result(L, true);
|
||||
}
|
||||
|
||||
int secure_os_rename(lua_State* L)
|
||||
{
|
||||
const std::string absSourceFilename = base::get_canonical_path(luaL_checkstring(L, 1));
|
||||
const std::string absDestFilename = base::get_absolute_path(luaL_checkstring(L, 2));
|
||||
lua_pop(L, 2);
|
||||
|
||||
if (absSourceFilename.empty())
|
||||
return file_result(L, false, ENOENT, absSourceFilename);
|
||||
|
||||
if (absDestFilename.empty())
|
||||
return file_result(L, false, EINVAL, absDestFilename);
|
||||
|
||||
if (!ask_access(L, absSourceFilename.data(), FileAccessMode::Write, ResourceType::File))
|
||||
return file_result(L, false, EACCES, absSourceFilename);
|
||||
|
||||
try {
|
||||
// If the destination file already exists, we should ask for permission to overwrite it.
|
||||
if (!base::get_canonical_path(absDestFilename).empty() &&
|
||||
!ask_access(L, absDestFilename.data(), FileAccessMode::Write, ResourceType::File)) {
|
||||
return file_result(L, false, EACCES, absDestFilename);
|
||||
}
|
||||
|
||||
base::move_file(absSourceFilename, absDestFilename);
|
||||
return file_result(L, true);
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
return file_result(L, false, EIO, absSourceFilename);
|
||||
}
|
||||
}
|
||||
|
||||
int secure_package_loadlib(lua_State* L)
|
||||
{
|
||||
const char* cmd = luaL_checkstring(L, 1);
|
||||
|
@ -201,7 +282,7 @@ void overwrite_unsecure_functions(lua_State* L)
|
|||
{
|
||||
// Remove unsupported functions
|
||||
lua_getglobal(L, "os");
|
||||
for (const char* name : { "remove", "rename", "exit", "tmpname" }) {
|
||||
for (const char* name : { "exit", "tmpname" }) {
|
||||
lua_pushcfunction(L, unsupported);
|
||||
lua_setfield(L, -2, name);
|
||||
}
|
||||
|
@ -280,7 +361,15 @@ bool ask_access(lua_State* L,
|
|||
{
|
||||
std::string label;
|
||||
switch (resourceType) {
|
||||
case ResourceType::File: label = Strings::script_access_file_label(); break;
|
||||
case ResourceType::File: {
|
||||
if (mode == FileAccessMode::Write) {
|
||||
label = Strings::script_access_file_write_label();
|
||||
}
|
||||
else {
|
||||
label = Strings::script_access_file_label();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ResourceType::Command: label = Strings::script_access_command_label(); break;
|
||||
case ResourceType::WebSocket: label = Strings::script_access_websocket_label(); break;
|
||||
case ResourceType::Clipboard: label = Strings::script_access_clipboard_label(); break;
|
||||
|
|
|
@ -12,3 +12,13 @@ print("Start ", start_clock)
|
|||
local end_clock = os.clock()
|
||||
print("End ", end_clock, " Elapsed ", end_clock - start_clock)
|
||||
assert(start_clock < end_clock)
|
||||
|
||||
-- os.rename & remove
|
||||
assert(app.fs.makeDirectory("_os_tmp"))
|
||||
assert(os.rename("_os_tmp", "_os_tmp_renamed"))
|
||||
assert(not os.rename("_os_tmp", "_os_tmp_shouldfail"))
|
||||
assert(not os.remove("_os_tmp_shouldfail"))
|
||||
assert(not os.rename("_os_tmp_shouldfail", "_test1.png")) -- Should fail, already exists
|
||||
assert(os.remove("_os_tmp_renamed"))
|
||||
assert(not app.fs.isDirectory("_os_tmp"))
|
||||
assert(not app.fs.isDirectory("_os_tmp_renamed"))
|
||||
|
|
Loading…
Reference in New Issue