From be0cec95206eb19dca075cbec611a81a9d848bcf Mon Sep 17 00:00:00 2001 From: eamondo2 Date: Wed, 8 Feb 2023 01:59:57 -0500 Subject: [PATCH 1/5] Current attempt to fix lua stack smashing --- plugins/automelt.cpp | 37 ++++++++++++++++++++++++++++++++----- plugins/lua/automelt.lua | 11 ++++++++--- 2 files changed, 40 insertions(+), 8 deletions(-) diff --git a/plugins/automelt.cpp b/plugins/automelt.cpp index e8001c48b..1df7f9a68 100644 --- a/plugins/automelt.cpp +++ b/plugins/automelt.cpp @@ -567,6 +567,25 @@ static void push_stockpile_config(lua_State *L, PersistentDataItem &c) { get_config_bool(c, STOCKPILE_CONFIG_MONITORED)); } +static void emplace_bulk_stockpile_configs(lua_State *L, PersistentDataItem &c, map> &stockpiles) { + int32_t id = get_config_val(c, STOCKPILE_CONFIG_ID); + bool monitored = get_config_bool(c, STOCKPILE_CONFIG_MONITORED); + map stockpile_config; + stockpile_config.emplace("id", id); + stockpile_config.emplace("monitored", monitored); + + stockpiles.emplace(id, stockpile_config); +} + +static void emplace_bulk_stockpile_configs(lua_State *L, int id, bool monitored, map> &stockpiles) { + + map stockpile_config; + stockpile_config.emplace("id", id); + stockpile_config.emplace("monitored", monitored); + + stockpiles.emplace(id, stockpile_config); +} + static void automelt_designate(color_ostream &out) { DEBUG(status, out).print("entering automelt designate\n"); out.print("designated %d item(s) for melting\n", do_cycle(out)); @@ -736,6 +755,8 @@ static int automelt_getSelectedStockpileConfig(lua_State *L){ return 1; } + + static int automelt_getItemCountsAndStockpileConfigs(lua_State *L) { color_ostream *out = Lua::GetOutput(L); if (!out) @@ -762,24 +783,30 @@ static int automelt_getItemCountsAndStockpileConfigs(lua_State *L) { Lua::Push(L, item_count_piles); Lua::Push(L, marked_item_count_piles); Lua::Push(L, premarked_item_count_piles); - int32_t bldg_count = 0; + + map> stockpile_config_map; for (auto pile : world->buildings.other.STOCKPILE) { if (!isStockpile(pile)) continue; - bldg_count++; int id = pile->id; if (watched_stockpiles.count(id)) { DEBUG(cycle,*out).print("indexed_id=%d\n", get_config_val(watched_stockpiles[id], STOCKPILE_CONFIG_ID)); - push_stockpile_config(L, watched_stockpiles[id]); + emplace_bulk_stockpile_configs(L, watched_stockpiles[id], stockpile_config_map); + } else { - push_stockpile_config(L, id, false); + emplace_bulk_stockpile_configs(L, id, false, stockpile_config_map); } } + + Lua::Push(L, stockpile_config_map); + + DEBUG(cycle, *out).print("confmap_length: %d\n", stockpile_config_map.size()); + DEBUG(perf, *out).print("exit automelt_getItemCountsAndStockpileConfigs\n"); - return 4+bldg_count; + return 5; } DFHACK_PLUGIN_LUA_FUNCTIONS{ diff --git a/plugins/lua/automelt.lua b/plugins/lua/automelt.lua index b49a434a1..535c056e6 100644 --- a/plugins/lua/automelt.lua +++ b/plugins/lua/automelt.lua @@ -64,8 +64,12 @@ function getItemCountsAndStockpileConfigs() ret.item_counts = table.remove(data, 1) ret.marked_item_counts = table.remove(data, 1) ret.premarked_item_counts = table.remove(data, 1) - ret.stockpile_configs = data - for _,c in ipairs(ret.stockpile_configs) do + local unparsed_stockpile_configs = table.remove(data, 1) + ret.stockpile_configs = {} + + for idx,c in pairs(unparsed_stockpile_configs) do + print(c.id) + print(c.monitored) if not c.id or c.id == -1 then c.name = "ERROR" c.monitored = false @@ -76,7 +80,8 @@ function getItemCountsAndStockpileConfigs() end c.monitored = c.monitored ~= 0 end - + table.insert(ret.stockpile_configs, c) + end return ret end From 02a249fdee4181318a24672c14b4213ccaec5824 Mon Sep 17 00:00:00 2001 From: eamondo2 Date: Wed, 8 Feb 2023 14:01:32 -0500 Subject: [PATCH 2/5] Fixes the lua stack smashing issue --- plugins/autochop.cpp | 40 +++++++++++++++++++++++++++++++++++++--- plugins/automelt.cpp | 22 ++++++++-------------- plugins/lua/autochop.lua | 7 +++++-- plugins/lua/automelt.lua | 2 -- 4 files changed, 50 insertions(+), 21 deletions(-) diff --git a/plugins/autochop.cpp b/plugins/autochop.cpp index bf7540e29..7a16a79b4 100644 --- a/plugins/autochop.cpp +++ b/plugins/autochop.cpp @@ -803,6 +803,33 @@ static void push_burrow_config(lua_State *L, PersistentDataItem &c) { get_config_bool(c, BURROW_CONFIG_PROTECT_COOKABLE)); } +static void emplace_bulk_burrow_config(lua_State *L, map> &burrows, int id, bool chop = false, + bool clearcut = false, bool protect_brewable = false, + bool protect_edible = false, bool protect_cookable = false) { + + map burrow_config; + burrow_config.emplace("id", id); + burrow_config.emplace("chop", chop); + burrow_config.emplace("clearcut", clearcut); + burrow_config.emplace("protect_brewable", protect_brewable); + burrow_config.emplace("protect_edible", protect_edible); + burrow_config.emplace("protect_cookable", protect_cookable); + + burrows.emplace(id, burrow_config); + +} + +static void emplace_bulk_burrow_config(lua_State *L, map> &burrows, PersistentDataItem &c) { + emplace_bulk_burrow_config(L, burrows, get_config_val(c, BURROW_CONFIG_ID), + get_config_bool(c, BURROW_CONFIG_CHOP), + get_config_bool(c, BURROW_CONFIG_CLEARCUT), + get_config_bool(c, BURROW_CONFIG_PROTECT_BREWABLE), + get_config_bool(c, BURROW_CONFIG_PROTECT_EDIBLE), + get_config_bool(c, BURROW_CONFIG_PROTECT_COOKABLE)); + + +} + static int autochop_getTreeCountsAndBurrowConfigs(lua_State *L) { color_ostream *out = Lua::GetOutput(L); if (!out) @@ -818,6 +845,9 @@ static int autochop_getTreeCountsAndBurrowConfigs(lua_State *L) { &designated_trees, &accessible_yield, &tree_counts, &designated_tree_counts); map summary; + + map> burrow_config_map; + summary.emplace("accessible_trees", accessible_trees); summary.emplace("inaccessible_trees", inaccessible_trees); summary.emplace("designated_trees", designated_trees); @@ -831,13 +861,17 @@ static int autochop_getTreeCountsAndBurrowConfigs(lua_State *L) { for (auto &burrow : plotinfo->burrows.list) { int id = burrow->id; if (watched_burrows_indices.count(id)) { - push_burrow_config(L, watched_burrows[watched_burrows_indices[id]]); + // push_burrow_config(L, watched_burrows[watched_burrows_indices[id]]); + emplace_bulk_burrow_config(L, burrow_config_map, watched_burrows[watched_burrows_indices[id]]); } else { - push_burrow_config(L, id); + // push_burrow_config(L, id); + emplace_bulk_burrow_config(L, burrow_config_map, id); } } - return 3 + plotinfo->burrows.list.size(); + Lua::Push(L, burrow_config_map); + + return 4; } static int autochop_getBurrowConfig(lua_State *L) { diff --git a/plugins/automelt.cpp b/plugins/automelt.cpp index 1df7f9a68..ca0cf1626 100644 --- a/plugins/automelt.cpp +++ b/plugins/automelt.cpp @@ -567,9 +567,8 @@ static void push_stockpile_config(lua_State *L, PersistentDataItem &c) { get_config_bool(c, STOCKPILE_CONFIG_MONITORED)); } -static void emplace_bulk_stockpile_configs(lua_State *L, PersistentDataItem &c, map> &stockpiles) { - int32_t id = get_config_val(c, STOCKPILE_CONFIG_ID); - bool monitored = get_config_bool(c, STOCKPILE_CONFIG_MONITORED); +static void emplace_bulk_stockpile_config(lua_State *L, int id, bool monitored, map> &stockpiles) { + map stockpile_config; stockpile_config.emplace("id", id); stockpile_config.emplace("monitored", monitored); @@ -577,13 +576,10 @@ static void emplace_bulk_stockpile_configs(lua_State *L, PersistentDataItem &c, stockpiles.emplace(id, stockpile_config); } -static void emplace_bulk_stockpile_configs(lua_State *L, int id, bool monitored, map> &stockpiles) { - - map stockpile_config; - stockpile_config.emplace("id", id); - stockpile_config.emplace("monitored", monitored); - - stockpiles.emplace(id, stockpile_config); +static void emplace_bulk_stockpile_config(lua_State *L, PersistentDataItem &c, map> &stockpiles) { + int32_t id = get_config_val(c, STOCKPILE_CONFIG_ID); + bool monitored = get_config_bool(c, STOCKPILE_CONFIG_MONITORED); + emplace_bulk_stockpile_config(L, id, monitored, stockpiles); } static void automelt_designate(color_ostream &out) { @@ -792,17 +788,15 @@ static int automelt_getItemCountsAndStockpileConfigs(lua_State *L) { int id = pile->id; if (watched_stockpiles.count(id)) { - DEBUG(cycle,*out).print("indexed_id=%d\n", get_config_val(watched_stockpiles[id], STOCKPILE_CONFIG_ID)); - emplace_bulk_stockpile_configs(L, watched_stockpiles[id], stockpile_config_map); + emplace_bulk_stockpile_config(L, watched_stockpiles[id], stockpile_config_map); } else { - emplace_bulk_stockpile_configs(L, id, false, stockpile_config_map); + emplace_bulk_stockpile_config(L, id, false, stockpile_config_map); } } Lua::Push(L, stockpile_config_map); - DEBUG(cycle, *out).print("confmap_length: %d\n", stockpile_config_map.size()); DEBUG(perf, *out).print("exit automelt_getItemCountsAndStockpileConfigs\n"); diff --git a/plugins/lua/autochop.lua b/plugins/lua/autochop.lua index 6b8c9f943..e9bad2eef 100644 --- a/plugins/lua/autochop.lua +++ b/plugins/lua/autochop.lua @@ -96,14 +96,17 @@ function getTreeCountsAndBurrowConfigs() ret.summary = table.remove(data, 1) ret.tree_counts = table.remove(data, 1) ret.designated_tree_counts = table.remove(data, 1) - ret.burrow_configs = data - for _,c in ipairs(ret.burrow_configs) do + local unparsed_burrow_configs = table.remove(data, 1) + + ret.burrow_configs = {} + for idx,c in pairs(unparsed_burrow_configs) do c.name = df.burrow.find(c.id).name c.chop = c.chop ~= 0 c.clearcut = c.clearcut ~= 0 c.protect_brewable = c.protect_brewable ~= 0 c.protect_edible = c.protect_edible ~= 0 c.protect_cookable = c.protect_cookable ~= 0 + table.insert(ret.burrow_configs, c) end return ret end diff --git a/plugins/lua/automelt.lua b/plugins/lua/automelt.lua index 535c056e6..395934867 100644 --- a/plugins/lua/automelt.lua +++ b/plugins/lua/automelt.lua @@ -68,8 +68,6 @@ function getItemCountsAndStockpileConfigs() ret.stockpile_configs = {} for idx,c in pairs(unparsed_stockpile_configs) do - print(c.id) - print(c.monitored) if not c.id or c.id == -1 then c.name = "ERROR" c.monitored = false From bf0b3f8845d44f85aa899083d5feb335ac507f7d Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 8 Feb 2023 19:06:33 +0000 Subject: [PATCH 3/5] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- plugins/automelt.cpp | 2 +- plugins/lua/automelt.lua | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/automelt.cpp b/plugins/automelt.cpp index ca0cf1626..862507413 100644 --- a/plugins/automelt.cpp +++ b/plugins/automelt.cpp @@ -568,7 +568,7 @@ static void push_stockpile_config(lua_State *L, PersistentDataItem &c) { } static void emplace_bulk_stockpile_config(lua_State *L, int id, bool monitored, map> &stockpiles) { - + map stockpile_config; stockpile_config.emplace("id", id); stockpile_config.emplace("monitored", monitored); diff --git a/plugins/lua/automelt.lua b/plugins/lua/automelt.lua index 395934867..cbd1bd538 100644 --- a/plugins/lua/automelt.lua +++ b/plugins/lua/automelt.lua @@ -66,7 +66,7 @@ function getItemCountsAndStockpileConfigs() ret.premarked_item_counts = table.remove(data, 1) local unparsed_stockpile_configs = table.remove(data, 1) ret.stockpile_configs = {} - + for idx,c in pairs(unparsed_stockpile_configs) do if not c.id or c.id == -1 then c.name = "ERROR" @@ -79,7 +79,7 @@ function getItemCountsAndStockpileConfigs() c.monitored = c.monitored ~= 0 end table.insert(ret.stockpile_configs, c) - + end return ret end From 1e4a73007ebd68c1fea81b01d90fe2752378c9fe Mon Sep 17 00:00:00 2001 From: Eamon Bode Date: Wed, 8 Feb 2023 15:44:55 -0500 Subject: [PATCH 4/5] Apply suggestions from code review Whitespace fixes Co-authored-by: Myk --- plugins/autochop.cpp | 4 ---- plugins/automelt.cpp | 3 --- 2 files changed, 7 deletions(-) diff --git a/plugins/autochop.cpp b/plugins/autochop.cpp index 7a16a79b4..3a433f7a9 100644 --- a/plugins/autochop.cpp +++ b/plugins/autochop.cpp @@ -816,7 +816,6 @@ static void emplace_bulk_burrow_config(lua_State *L, map> &burrows, PersistentDataItem &c) { @@ -826,8 +825,6 @@ static void emplace_bulk_burrow_config(lua_State *L, map> &stockpiles) { - map stockpile_config; stockpile_config.emplace("id", id); stockpile_config.emplace("monitored", monitored); @@ -751,8 +750,6 @@ static int automelt_getSelectedStockpileConfig(lua_State *L){ return 1; } - - static int automelt_getItemCountsAndStockpileConfigs(lua_State *L) { color_ostream *out = Lua::GetOutput(L); if (!out) From 5a5fcbd1346b49734deecc895b4115d27c23b343 Mon Sep 17 00:00:00 2001 From: eamondo2 Date: Wed, 8 Feb 2023 15:52:58 -0500 Subject: [PATCH 5/5] Add changes to changelog.txt --- docs/changelog.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/changelog.txt b/docs/changelog.txt index daf0e8e1d..18635ca2b 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -40,6 +40,8 @@ changelog.txt uses a syntax similar to RST, with a few special sequences: - Fix right click sometimes closing both a DFHack window and a vanilla panel - Fixed issue with scrollable lists having some data off-screen if they were scrolled before being made visible - `channel-safely`: fixed bug resulting in marker mode never being set for any designation +- `automelt`: fixed bug related to lua stack smashing behavior in returned stockpile configs +- `autochop`: fixed bug related to lua stack smashing behavior in returned stockpile configs ## Misc Improvements - `automelt`: is now more resistent to savegame corruption