From e4e6ed7151ea07d308d46cd72b09641d324e7cbd Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Tue, 23 Sep 2025 11:56:54 +0100 Subject: [PATCH] [Minor] Some tests fixes --- src/lua/lua_archive.c | 28 ++++++++++++++++++++++++++-- test/lua/unit/archive.lua | 15 ++++++++++++++- 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/src/lua/lua_archive.c b/src/lua/lua_archive.c index fa67d60617..7752b549ea 100644 --- a/src/lua/lua_archive.c +++ b/src/lua/lua_archive.c @@ -216,7 +216,15 @@ lua_archive_zip_encrypt(lua_State *L) { LUA_TRACE_POINT; luaL_checktype(L, 1, LUA_TTABLE); - const char *password = luaL_checkstring(L, 2); + const char *password = NULL; + if (lua_gettop(L) >= 2 && !lua_isnil(L, 2)) { + if (lua_type(L, 2) == LUA_TSTRING) { + password = lua_tostring(L, 2); + } + else { + return luaL_error(L, "invalid password (string expected)"); + } + } GArray *specs = g_array_sized_new(FALSE, FALSE, sizeof(struct rspamd_zip_file_spec), 8); GError *err = NULL; @@ -601,10 +609,11 @@ lua_archive_pack(lua_State *L) } /*** - * @function archive.unpack(data[, format]) + * @function archive.unpack(data[, format][, password]) * Unpacks an archive from a Lua string (or rspamd_text) using libarchive. * @param {string|text} data archive contents * @param {string} format optional format name to restrict autodetection (e.g. "zip") + * @param {string} password optional password for encrypted archives (e.g. ZIP AES) * @return {table} array of files: { name = string, content = text } (non-regular entries are skipped) */ static int @@ -613,6 +622,7 @@ lua_archive_unpack(lua_State *L) LUA_TRACE_POINT; struct rspamd_lua_text *t = NULL; const char *format = NULL; + const char *password = NULL; struct archive *a = NULL; t = lua_check_text_or_string(L, 1); @@ -624,6 +634,9 @@ lua_archive_unpack(lua_State *L) if (lua_type(L, 2) == LUA_TSTRING) { format = lua_tostring(L, 2); } + if (lua_type(L, 3) == LUA_TSTRING) { + password = lua_tostring(L, 3); + } a = archive_read_new(); if (a == NULL) { @@ -639,6 +652,17 @@ lua_archive_unpack(lua_State *L) archive_read_support_format_all(a); } + if (password && *password) { + /* supply passphrase for encrypted archives (e.g. zip AES) */ + int pr = archive_read_add_passphrase(a, password); + if (pr != ARCHIVE_OK) { + const char *aerr = archive_error_string(a); + lua_pushfstring(L, "cannot set passphrase: %s", aerr ? aerr : "unknown error"); + archive_read_free(a); + return lua_error(L); + } + } + int r = archive_read_open_memory(a, t->start, t->len); if (r != ARCHIVE_OK) { const char *aerr = archive_error_string(a); diff --git a/test/lua/unit/archive.lua b/test/lua/unit/archive.lua index fe194322c9..d52d14e577 100644 --- a/test/lua/unit/archive.lua +++ b/test/lua/unit/archive.lua @@ -53,7 +53,7 @@ context("Lua archive bindings", function() local blob = archive.zip_encrypt(files, pwd) assert_equal(type(blob), "userdata") -- libarchive can read AE-2, so unpack should succeed and yield the same files - local out = archive.unpack(blob, "zip") + local out = archive.unpack(blob, "zip", pwd) assert_equal(#out, 2) local names = {} for _, f in ipairs(out) do names[f.name] = f.content end @@ -61,6 +61,19 @@ context("Lua archive bindings", function() assert_rspamd_eq({ actual = names["y.bin"], expect = rspamd_text.fromstring("\001\002\003") }) end) + test("zip_encrypt with wrong password fails to unpack", function() + local files = { + { name = "secret.txt", content = "topsecret" }, + } + local pwd = "goodpass" + local blob = archive.zip_encrypt(files, pwd) + assert_equal(type(blob), "userdata") + local ok, err = pcall(function() + archive.unpack(blob, "zip", "badpass") + end) + assert_equal(ok, false) + end) + test("tar/untar helpers roundtrip (no compression)", function() local files = { { name = "x.txt", content = "X" }, -- 2.47.3