From 0c116f551747293795336350e0d137e12fd633bb Mon Sep 17 00:00:00 2001 From: Jean-Michel Picod Date: Fri, 20 Sep 2024 17:14:52 +0200 Subject: [PATCH] Add the old bit32 LUA module as a compatiblity shim. Many exisiting LUA scripts are using bit32 which has been removed in LUA5.4 in favor of native language support of bitwise operations. Yet, it's easier to backport this module rather than patching all the existing LUA scripts because most of them can't be tested. --- client/CMakeLists.txt | 1 + client/Makefile | 5 +- client/src/lua_bitlib.c | 205 ++++++++++++++++++++++++++++++++++++++++ client/src/lua_bitlib.h | 25 +++++ client/src/scripting.c | 4 + 5 files changed, 238 insertions(+), 2 deletions(-) create mode 100644 client/src/lua_bitlib.c create mode 100644 client/src/lua_bitlib.h diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index a383c62a3..766014bc9 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -411,6 +411,7 @@ set (TARGET_SOURCES ${PM3_ROOT}/client/src/graph.c ${PM3_ROOT}/client/src/iso4217.c ${PM3_ROOT}/client/src/jansson_path.c + ${PM3_ROOT}/client/src/lua_bitlib.c ${PM3_ROOT}/client/src/preferences.c ${PM3_ROOT}/client/src/pm3.c ${PM3_ROOT}/client/src/pm3_binlib.c diff --git a/client/Makefile b/client/Makefile index d977ff522..71f4220ed 100644 --- a/client/Makefile +++ b/client/Makefile @@ -730,11 +730,12 @@ SRCS = mifare/aiddesfire.c \ loclass/cipherutils.c \ loclass/elite_crack.c \ loclass/ikeys.c \ + lua_bitlib.c \ mifare/lrpcrypto.c \ mifare/desfirecrypto.c \ mifare/desfirecore.c \ - mifare/desfiresecurechan.c \ - mifare/desfiretest.c \ + mifare/desfiresecurechan.c \ + mifare/desfiretest.c \ mifare/gallaghercore.c \ mifare/mad.c \ mifare/mfkey.c \ diff --git a/client/src/lua_bitlib.c b/client/src/lua_bitlib.c new file mode 100644 index 000000000..c37ec7035 --- /dev/null +++ b/client/src/lua_bitlib.c @@ -0,0 +1,205 @@ +/* +** $Id: lbitlib.c,v 1.18 2013/03/19 13:19:12 roberto Exp $ +** Standard library for bitwise operations +** See Copyright Notice in lua.h +** +** Patched to provide a compatibility layer with Lua5.3+ where +** bit32 library was removed. +*/ + +#include "lua_bitlib.h" + +#include "lauxlib.h" + +/* number of bits to consider in a number */ +#define LUA_BITLIB_NBITS 32 + + +#define ALLONES (~(((~(lua_Unsigned)0) << (LUA_BITLIB_NBITS - 1)) << 1)) + +/* macro to trim extra bits */ +#define trim(x) ((x) & ALLONES) + + +/* builds a number with 'n' ones (1 <= n <= LUA_BITLIB_NBITS) */ +#define mask(n) (~((ALLONES << 1) << ((n) - 1))) + + +typedef lua_Unsigned b_uint; + + +static b_uint andaux(lua_State *L) { + int i, n = lua_gettop(L); + b_uint r = ~(b_uint)0; + for (i = 1; i <= n; i++) + r &= (b_uint)luaL_checkinteger(L, i); + return trim(r); +} + + +static int b_and(lua_State *L) { + b_uint r = andaux(L); + lua_pushinteger(L, r); + return 1; +} + + +static int b_test(lua_State *L) { + b_uint r = andaux(L); + lua_pushboolean(L, r != 0); + return 1; +} + + +static int b_or(lua_State *L) { + int i, n = lua_gettop(L); + b_uint r = 0; + for (i = 1; i <= n; i++) + r |= (b_uint) luaL_checkinteger(L, i); + lua_pushinteger(L, trim(r)); + return 1; +} + + +static int b_xor(lua_State *L) { + int i, n = lua_gettop(L); + b_uint r = 0; + for (i = 1; i <= n; i++) + r ^= (b_uint) luaL_checkinteger(L, i); + lua_pushinteger(L, trim(r)); + return 1; +} + + +static int b_not(lua_State *L) { + b_uint r = ~((b_uint)luaL_checkinteger(L, 1)); + lua_pushinteger(L, trim(r)); + return 1; +} + + +static int b_shift(lua_State *L, b_uint r, int i) { + if (i < 0) { /* shift right? */ + i = -i; + r = trim(r); + if (i >= LUA_BITLIB_NBITS) r = 0; + else r >>= i; + } else { /* shift left */ + if (i >= LUA_BITLIB_NBITS) r = 0; + else r <<= i; + r = trim(r); + } + lua_pushinteger(L, r); + return 1; +} + + +static int b_lshift(lua_State *L) { + return b_shift(L, (b_uint)luaL_checkinteger(L, 1), luaL_checkinteger(L, 2)); +} + + +static int b_rshift(lua_State *L) { + return b_shift(L, (b_uint)luaL_checkinteger(L, 1), -luaL_checkinteger(L, 2)); +} + + +static int b_arshift(lua_State *L) { + b_uint r = (b_uint)luaL_checkinteger(L, 1); + int i = luaL_checkinteger(L, 2); + if (i < 0 || !(r & ((b_uint)1 << (LUA_BITLIB_NBITS - 1)))) + return b_shift(L, r, -i); + else { /* arithmetic shift for 'negative' number */ + if (i >= LUA_BITLIB_NBITS) r = ALLONES; + else + r = trim((r >> i) | ~(~(b_uint)0 >> i)); /* add signal bit */ + lua_pushinteger(L, r); + return 1; + } +} + + +static int b_rot(lua_State *L, int i) { + b_uint r = (b_uint)luaL_checkinteger(L, 1); + i &= (LUA_BITLIB_NBITS - 1); /* i = i % NBITS */ + r = trim(r); + if (i != 0) /* avoid undefined shift of LUA_BITLIB_NBITS when i == 0 */ + r = (r << i) | (r >> (LUA_BITLIB_NBITS - i)); + + lua_pushinteger(L, trim(r)); + return 1; +} + + +static int b_lrot(lua_State *L) { + return b_rot(L, luaL_checkinteger(L, 2)); +} + + +static int b_rrot(lua_State *L) { + return b_rot(L, -luaL_checkinteger(L, 2)); +} + + +/* +** get field and width arguments for field-manipulation functions, +** checking whether they are valid. +** ('luaL_error' called without 'return' to avoid later warnings about +** 'width' being used uninitialized.) +*/ +static int fieldargs(lua_State *L, int farg, int *width) { + int f = luaL_checkinteger(L, farg); + int w = luaL_optinteger(L, farg + 1, 1); + luaL_argcheck(L, 0 <= f, farg, "field cannot be negative"); + luaL_argcheck(L, 0 < w, farg + 1, "width must be positive"); + if (f + w > LUA_BITLIB_NBITS) + luaL_error(L, "trying to access non-existent bits"); + *width = w; + return f; +} + + +static int b_extract(lua_State *L) { + int w; + b_uint r = (b_uint)luaL_checkinteger(L, 1); + int f = fieldargs(L, 2, &w); + r = (r >> f) & mask(w); + lua_pushinteger(L, r); + return 1; +} + + +static int b_replace(lua_State *L) { + int w; + b_uint r = (b_uint)luaL_checkinteger(L, 1); + b_uint v = (b_uint)luaL_checkinteger(L, 2); + int f = fieldargs(L, 3, &w); + int m = mask(w); + v &= m; /* erase bits outside given width */ + r = (r & ~(m << f)) | (v << f); + lua_pushinteger(L, r); + return 1; +} + + +void register_bit32_lib(lua_State *L) { + static const luaL_Reg bitlib[] = { + {"arshift", b_arshift}, + {"band", b_and}, + {"bnot", b_not}, + {"bor", b_or}, + {"bxor", b_xor}, + {"btest", b_test}, + {"extract", b_extract}, + {"lrotate", b_lrot}, + {"lshift", b_lshift}, + {"replace", b_replace}, + {"rrotate", b_rrot}, + {"rshift", b_rshift}, + {NULL, NULL} + }; + + luaL_newlib(L, bitlib); + lua_setfield(L, -2, "bit32"); +} + diff --git a/client/src/lua_bitlib.h b/client/src/lua_bitlib.h new file mode 100644 index 000000000..59e9c8880 --- /dev/null +++ b/client/src/lua_bitlib.h @@ -0,0 +1,25 @@ +//----------------------------------------------------------------------------- +// Copyright (C) Proxmark3 contributors. See AUTHORS.md for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// See LICENSE.txt for the text of the license. +//----------------------------------------------------------------------------- +// Bitwise manipulation library which got deprecated in lua5.3 +//----------------------------------------------------------------------------- +#ifndef LUA_BITLIB_H__ +#define LUA_BITLIB_H__ + +#include + +void register_bit32_lib(lua_State *L); + +#endif diff --git a/client/src/scripting.c b/client/src/scripting.c index 786037408..93e68d123 100644 --- a/client/src/scripting.c +++ b/client/src/scripting.c @@ -22,6 +22,7 @@ #include #include "lauxlib.h" +#include "lua_bitlib.h" #include "cmdmain.h" #include "proxmark3.h" #include "comms.h" @@ -1437,6 +1438,9 @@ int set_pm3_libraries(lua_State *L) { lua_pushglobaltable(L); + // bit32 compatibility shim + register_bit32_lib(L); + // Core module luaL_newlib(L, libs); lua_setfield(L, -2, "core");