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 diff --git a/plugins/autochop.cpp b/plugins/autochop.cpp index bf7540e29..3a433f7a9 100644 --- a/plugins/autochop.cpp +++ b/plugins/autochop.cpp @@ -803,6 +803,30 @@ 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 +842,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 +858,16 @@ 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); + 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 e8001c48b..0cd9e8131 100644 --- a/plugins/automelt.cpp +++ b/plugins/automelt.cpp @@ -567,6 +567,20 @@ static void push_stockpile_config(lua_State *L, PersistentDataItem &c) { 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); + + 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) { DEBUG(status, out).print("entering automelt designate\n"); out.print("designated %d item(s) for melting\n", do_cycle(out)); @@ -762,24 +776,28 @@ 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_config(L, watched_stockpiles[id], stockpile_config_map); + } else { - push_stockpile_config(L, id, false); + emplace_bulk_stockpile_config(L, id, false, stockpile_config_map); } } + + Lua::Push(L, stockpile_config_map); + + DEBUG(perf, *out).print("exit automelt_getItemCountsAndStockpileConfigs\n"); - return 4+bldg_count; + return 5; } DFHACK_PLUGIN_LUA_FUNCTIONS{ 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 b49a434a1..cbd1bd538 100644 --- a/plugins/lua/automelt.lua +++ b/plugins/lua/automelt.lua @@ -64,8 +64,10 @@ 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 if not c.id or c.id == -1 then c.name = "ERROR" c.monitored = false @@ -76,6 +78,7 @@ function getItemCountsAndStockpileConfigs() end c.monitored = c.monitored ~= 0 end + table.insert(ret.stockpile_configs, c) end return ret