From b1ee42821426f2a76785c630d38d27d444d77ca9 Mon Sep 17 00:00:00 2001 From: Ryan Young Date: Wed, 31 Aug 2022 06:37:03 +0000 Subject: [PATCH 1/6] fix(5.0): prevent the string passed to luaL_loadbuffer from being truncated --- src/binding-factory.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/binding-factory.ts b/src/binding-factory.ts index 1c99f5f..c1e9834 100644 --- a/src/binding-factory.ts +++ b/src/binding-factory.ts @@ -167,12 +167,18 @@ const lauxBindings: Record = { luaL_loadstring: function(L: LuaState, s: string) { return (this as LauxLib).luaL_loadbuffer(L, s, s.length, s); }, + luaL_loadbuffer: function(L: LuaState, s: string, slen: number, name: string) { + // Terrible, awful hack to prevent the end of the string from being mangled by the C wrapper + const pad = " "; + const loadbuffer = luaGlue.cwrap("luaL_loadbuffer", "number", ["number", "string", "number", "string"]); + return loadbuffer(L, s + pad, slen + pad.length, name); + }, luaL_newstate: luaGlue.cwrap("lua_open", "number", []), } }, - "<=5.1.x": function(luaGlue: LuaEmscriptenModule, _lua: Lua) { + "5.1.x": function(luaGlue: LuaEmscriptenModule, _lua: Lua) { return { - luaL_loadbuffer: luaGlue.cwrap("luaL_loadbuffer", "number", ["number", "string", "number", "string"]), + luaL_loadbuffer: luaGlue.cwrap("luaL_loadbuffer", "number", ["number", "string", "number", "string"]) } }, ">=5.1.0": function(luaGlue: LuaEmscriptenModule, lua: Lua) { From a8a35cb73f588e622d8e93c490555395105a1987 Mon Sep 17 00:00:00 2001 From: Ryan Young Date: Wed, 31 Aug 2022 07:35:23 +0000 Subject: [PATCH 2/6] Revert "fix(5.0): prevent the string passed to luaL_loadbuffer from being truncated" This reverts commit b1ee42821426f2a76785c630d38d27d444d77ca9. --- src/binding-factory.ts | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/binding-factory.ts b/src/binding-factory.ts index c1e9834..1c99f5f 100644 --- a/src/binding-factory.ts +++ b/src/binding-factory.ts @@ -167,18 +167,12 @@ const lauxBindings: Record = { luaL_loadstring: function(L: LuaState, s: string) { return (this as LauxLib).luaL_loadbuffer(L, s, s.length, s); }, - luaL_loadbuffer: function(L: LuaState, s: string, slen: number, name: string) { - // Terrible, awful hack to prevent the end of the string from being mangled by the C wrapper - const pad = " "; - const loadbuffer = luaGlue.cwrap("luaL_loadbuffer", "number", ["number", "string", "number", "string"]); - return loadbuffer(L, s + pad, slen + pad.length, name); - }, luaL_newstate: luaGlue.cwrap("lua_open", "number", []), } }, - "5.1.x": function(luaGlue: LuaEmscriptenModule, _lua: Lua) { + "<=5.1.x": function(luaGlue: LuaEmscriptenModule, _lua: Lua) { return { - luaL_loadbuffer: luaGlue.cwrap("luaL_loadbuffer", "number", ["number", "string", "number", "string"]) + luaL_loadbuffer: luaGlue.cwrap("luaL_loadbuffer", "number", ["number", "string", "number", "string"]), } }, ">=5.1.0": function(luaGlue: LuaEmscriptenModule, lua: Lua) { From dd116a8fb435dfe921ea50aa8c109eb0c62aff83 Mon Sep 17 00:00:00 2001 From: Ryan Young Date: Wed, 31 Aug 2022 08:11:57 +0000 Subject: [PATCH 3/6] fix(5.0): handle the utf-8 conversion correctly for loadstring --- scripts/build.sh | 2 +- src/binding-factory.ts | 6 ++++-- src/glue/glue.ts | 2 ++ 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/scripts/build.sh b/scripts/build.sh index b98acc6..2426955 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -20,7 +20,7 @@ cd ../.. if [[ "$1" == "lua-5.0.3" ]]; then emcc -Ithirdparty/$1 thirdparty/$1/lib/liblua.a thirdparty/$1/lib/liblualib.a \ -s WASM=1 -O3 -o dist/glue/glue-$1.js \ - -s EXPORTED_RUNTIME_METHODS="['cwrap']" \ + -s EXPORTED_RUNTIME_METHODS="['cwrap', 'allocateUTF8', 'lengthBytesUTF8']" \ -s MODULARIZE=1 \ -s ALLOW_TABLE_GROWTH \ -s EXPORT_NAME="glue" \ diff --git a/src/binding-factory.ts b/src/binding-factory.ts index 1c99f5f..901cf03 100644 --- a/src/binding-factory.ts +++ b/src/binding-factory.ts @@ -165,12 +165,14 @@ const lauxBindings: Record = { return (this as LauxLib).luaL_loadstring(L, s) || lua.lua_pcall(L, 0, LUA_MULTRET, 0); }, luaL_loadstring: function(L: LuaState, s: string) { - return (this as LauxLib).luaL_loadbuffer(L, s, s.length, s); + const ptr = luaGlue.allocateUTF8(s) as unknown; + return (this as LauxLib).luaL_loadbuffer(L, ptr as string, luaGlue.lengthBytesUTF8(s), s); }, + luaL_loadbuffer: luaGlue.cwrap("luaL_loadbuffer", "number", ["number", "number", "number", "string"]), luaL_newstate: luaGlue.cwrap("lua_open", "number", []), } }, - "<=5.1.x": function(luaGlue: LuaEmscriptenModule, _lua: Lua) { + "5.1.x": function(luaGlue: LuaEmscriptenModule, _lua: Lua) { return { luaL_loadbuffer: luaGlue.cwrap("luaL_loadbuffer", "number", ["number", "string", "number", "string"]), } diff --git a/src/glue/glue.ts b/src/glue/glue.ts index a16d5b6..db88b34 100644 --- a/src/glue/glue.ts +++ b/src/glue/glue.ts @@ -1,4 +1,6 @@ export interface LuaEmscriptenModule extends EmscriptenModule { + allocateUTF8: typeof allocateUTF8; + lengthBytesUTF8: typeof lengthBytesUTF8; cwrap: typeof cwrap; } From d4a5d7b0ea13f22522a437256ac67aae66c407f6 Mon Sep 17 00:00:00 2001 From: Ryan Young Date: Wed, 31 Aug 2022 08:20:18 +0000 Subject: [PATCH 4/6] style: document use of number argument for 5.0's loadbuffer --- src/binding-factory.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/binding-factory.ts b/src/binding-factory.ts index 901cf03..4ff5d0a 100644 --- a/src/binding-factory.ts +++ b/src/binding-factory.ts @@ -168,6 +168,7 @@ const lauxBindings: Record = { const ptr = luaGlue.allocateUTF8(s) as unknown; return (this as LauxLib).luaL_loadbuffer(L, ptr as string, luaGlue.lengthBytesUTF8(s), s); }, + // Note that s has a "number" type, so we can pass a raw pointer luaL_loadbuffer: luaGlue.cwrap("luaL_loadbuffer", "number", ["number", "number", "number", "string"]), luaL_newstate: luaGlue.cwrap("lua_open", "number", []), } From cf13fffe62e5bcb9d56b465da81679fe2b2d4c55 Mon Sep 17 00:00:00 2001 From: Ryan Young Date: Thu, 1 Sep 2022 04:07:02 +0000 Subject: [PATCH 5/6] refactor: put the loadstring cstring on the stack, so it can be easily reclaimed --- scripts/build.sh | 2 +- src/binding-factory.ts | 7 +++++-- src/glue/glue.ts | 6 ++++-- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/scripts/build.sh b/scripts/build.sh index 2426955..5f26957 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -20,7 +20,7 @@ cd ../.. if [[ "$1" == "lua-5.0.3" ]]; then emcc -Ithirdparty/$1 thirdparty/$1/lib/liblua.a thirdparty/$1/lib/liblualib.a \ -s WASM=1 -O3 -o dist/glue/glue-$1.js \ - -s EXPORTED_RUNTIME_METHODS="['cwrap', 'allocateUTF8', 'lengthBytesUTF8']" \ + -s EXPORTED_RUNTIME_METHODS="['cwrap', 'stackSave', 'stackRestore', 'lengthBytesUTF8', 'allocateUTF8OnStack']" \ -s MODULARIZE=1 \ -s ALLOW_TABLE_GROWTH \ -s EXPORT_NAME="glue" \ diff --git a/src/binding-factory.ts b/src/binding-factory.ts index 4ff5d0a..543a847 100644 --- a/src/binding-factory.ts +++ b/src/binding-factory.ts @@ -165,8 +165,11 @@ const lauxBindings: Record = { return (this as LauxLib).luaL_loadstring(L, s) || lua.lua_pcall(L, 0, LUA_MULTRET, 0); }, luaL_loadstring: function(L: LuaState, s: string) { - const ptr = luaGlue.allocateUTF8(s) as unknown; - return (this as LauxLib).luaL_loadbuffer(L, ptr as string, luaGlue.lengthBytesUTF8(s), s); + const lastStack = luaGlue.stackSave(); + const cstr = luaGlue.allocateUTF8OnStack(s) as unknown; + const result = (this as LauxLib).luaL_loadbuffer(L, cstr as string, luaGlue.lengthBytesUTF8(s), s); + luaGlue.stackRestore(lastStack); + return result; }, // Note that s has a "number" type, so we can pass a raw pointer luaL_loadbuffer: luaGlue.cwrap("luaL_loadbuffer", "number", ["number", "number", "number", "string"]), diff --git a/src/glue/glue.ts b/src/glue/glue.ts index db88b34..651d77f 100644 --- a/src/glue/glue.ts +++ b/src/glue/glue.ts @@ -1,7 +1,9 @@ export interface LuaEmscriptenModule extends EmscriptenModule { - allocateUTF8: typeof allocateUTF8; - lengthBytesUTF8: typeof lengthBytesUTF8; cwrap: typeof cwrap; + stackSave: typeof stackSave; + stackRestore: typeof stackRestore; + lengthBytesUTF8: typeof lengthBytesUTF8; + allocateUTF8OnStack: typeof allocateUTF8; } export type EmscriptenModuleFactorySync = ( From c3662a5769673eccda2ae8426f6f0dc4ec19c601 Mon Sep 17 00:00:00 2001 From: Ryan Young Date: Thu, 1 Sep 2022 04:25:18 +0000 Subject: [PATCH 6/6] refactor: further simplification using utf-8 autoconversion Thanks, Pyry! --- scripts/build.sh | 2 +- src/binding-factory.ts | 10 ++-------- src/glue/glue.ts | 3 --- 3 files changed, 3 insertions(+), 12 deletions(-) diff --git a/scripts/build.sh b/scripts/build.sh index 5f26957..edfb87b 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -20,7 +20,7 @@ cd ../.. if [[ "$1" == "lua-5.0.3" ]]; then emcc -Ithirdparty/$1 thirdparty/$1/lib/liblua.a thirdparty/$1/lib/liblualib.a \ -s WASM=1 -O3 -o dist/glue/glue-$1.js \ - -s EXPORTED_RUNTIME_METHODS="['cwrap', 'stackSave', 'stackRestore', 'lengthBytesUTF8', 'allocateUTF8OnStack']" \ + -s EXPORTED_RUNTIME_METHODS="['cwrap', 'lengthBytesUTF8']" \ -s MODULARIZE=1 \ -s ALLOW_TABLE_GROWTH \ -s EXPORT_NAME="glue" \ diff --git a/src/binding-factory.ts b/src/binding-factory.ts index 543a847..930c777 100644 --- a/src/binding-factory.ts +++ b/src/binding-factory.ts @@ -165,18 +165,12 @@ const lauxBindings: Record = { return (this as LauxLib).luaL_loadstring(L, s) || lua.lua_pcall(L, 0, LUA_MULTRET, 0); }, luaL_loadstring: function(L: LuaState, s: string) { - const lastStack = luaGlue.stackSave(); - const cstr = luaGlue.allocateUTF8OnStack(s) as unknown; - const result = (this as LauxLib).luaL_loadbuffer(L, cstr as string, luaGlue.lengthBytesUTF8(s), s); - luaGlue.stackRestore(lastStack); - return result; + return (this as LauxLib).luaL_loadbuffer(L, s, luaGlue.lengthBytesUTF8(s), s); }, - // Note that s has a "number" type, so we can pass a raw pointer - luaL_loadbuffer: luaGlue.cwrap("luaL_loadbuffer", "number", ["number", "number", "number", "string"]), luaL_newstate: luaGlue.cwrap("lua_open", "number", []), } }, - "5.1.x": function(luaGlue: LuaEmscriptenModule, _lua: Lua) { + "<=5.1.x": function(luaGlue: LuaEmscriptenModule, _lua: Lua) { return { luaL_loadbuffer: luaGlue.cwrap("luaL_loadbuffer", "number", ["number", "string", "number", "string"]), } diff --git a/src/glue/glue.ts b/src/glue/glue.ts index 651d77f..21c4b09 100644 --- a/src/glue/glue.ts +++ b/src/glue/glue.ts @@ -1,9 +1,6 @@ export interface LuaEmscriptenModule extends EmscriptenModule { cwrap: typeof cwrap; - stackSave: typeof stackSave; - stackRestore: typeof stackRestore; lengthBytesUTF8: typeof lengthBytesUTF8; - allocateUTF8OnStack: typeof allocateUTF8; } export type EmscriptenModuleFactorySync = (