Merge pull request #2848 from eamondo2/automelt-autochop-lua-stack-fix

`automelt` `autochop` Lua Stack smashing fix
develop
Myk 2023-02-08 13:01:00 -08:00 committed by GitHub
commit 5113823d8c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 69 additions and 13 deletions

@ -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 - 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 - 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 - `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 ## Misc Improvements
- `automelt`: is now more resistent to savegame corruption - `automelt`: is now more resistent to savegame corruption

@ -803,6 +803,30 @@ static void push_burrow_config(lua_State *L, PersistentDataItem &c) {
get_config_bool(c, BURROW_CONFIG_PROTECT_COOKABLE)); get_config_bool(c, BURROW_CONFIG_PROTECT_COOKABLE));
} }
static void emplace_bulk_burrow_config(lua_State *L, map<int32_t, map<string, int32_t>> &burrows, int id, bool chop = false,
bool clearcut = false, bool protect_brewable = false,
bool protect_edible = false, bool protect_cookable = false) {
map<string, int32_t> 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<int32_t, map<string, int32_t>> &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) { static int autochop_getTreeCountsAndBurrowConfigs(lua_State *L) {
color_ostream *out = Lua::GetOutput(L); color_ostream *out = Lua::GetOutput(L);
if (!out) if (!out)
@ -818,6 +842,9 @@ static int autochop_getTreeCountsAndBurrowConfigs(lua_State *L) {
&designated_trees, &accessible_yield, &tree_counts, &designated_tree_counts); &designated_trees, &accessible_yield, &tree_counts, &designated_tree_counts);
map<string, int32_t> summary; map<string, int32_t> summary;
map<int32_t, map<string, int32_t>> burrow_config_map;
summary.emplace("accessible_trees", accessible_trees); summary.emplace("accessible_trees", accessible_trees);
summary.emplace("inaccessible_trees", inaccessible_trees); summary.emplace("inaccessible_trees", inaccessible_trees);
summary.emplace("designated_trees", designated_trees); summary.emplace("designated_trees", designated_trees);
@ -831,13 +858,16 @@ static int autochop_getTreeCountsAndBurrowConfigs(lua_State *L) {
for (auto &burrow : plotinfo->burrows.list) { for (auto &burrow : plotinfo->burrows.list) {
int id = burrow->id; int id = burrow->id;
if (watched_burrows_indices.count(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 { } 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) { static int autochop_getBurrowConfig(lua_State *L) {

@ -567,6 +567,20 @@ static void push_stockpile_config(lua_State *L, PersistentDataItem &c) {
get_config_bool(c, STOCKPILE_CONFIG_MONITORED)); get_config_bool(c, STOCKPILE_CONFIG_MONITORED));
} }
static void emplace_bulk_stockpile_config(lua_State *L, int id, bool monitored, map<int32_t, map<string, int32_t>> &stockpiles) {
map<string, int32_t> 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<int32_t, map<string, int32_t>> &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) { static void automelt_designate(color_ostream &out) {
DEBUG(status, out).print("entering automelt designate\n"); DEBUG(status, out).print("entering automelt designate\n");
out.print("designated %d item(s) for melting\n", do_cycle(out)); 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, item_count_piles);
Lua::Push(L, marked_item_count_piles); Lua::Push(L, marked_item_count_piles);
Lua::Push(L, premarked_item_count_piles); Lua::Push(L, premarked_item_count_piles);
int32_t bldg_count = 0;
map<int32_t, map<string, int32_t>> stockpile_config_map;
for (auto pile : world->buildings.other.STOCKPILE) { for (auto pile : world->buildings.other.STOCKPILE) {
if (!isStockpile(pile)) if (!isStockpile(pile))
continue; continue;
bldg_count++;
int id = pile->id; int id = pile->id;
if (watched_stockpiles.count(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_config(L, watched_stockpiles[id], stockpile_config_map);
push_stockpile_config(L, watched_stockpiles[id]);
} else { } 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"); DEBUG(perf, *out).print("exit automelt_getItemCountsAndStockpileConfigs\n");
return 4+bldg_count; return 5;
} }
DFHACK_PLUGIN_LUA_FUNCTIONS{ DFHACK_PLUGIN_LUA_FUNCTIONS{

@ -96,14 +96,17 @@ function getTreeCountsAndBurrowConfigs()
ret.summary = table.remove(data, 1) ret.summary = table.remove(data, 1)
ret.tree_counts = table.remove(data, 1) ret.tree_counts = table.remove(data, 1)
ret.designated_tree_counts = table.remove(data, 1) ret.designated_tree_counts = table.remove(data, 1)
ret.burrow_configs = data local unparsed_burrow_configs = table.remove(data, 1)
for _,c in ipairs(ret.burrow_configs) do
ret.burrow_configs = {}
for idx,c in pairs(unparsed_burrow_configs) do
c.name = df.burrow.find(c.id).name c.name = df.burrow.find(c.id).name
c.chop = c.chop ~= 0 c.chop = c.chop ~= 0
c.clearcut = c.clearcut ~= 0 c.clearcut = c.clearcut ~= 0
c.protect_brewable = c.protect_brewable ~= 0 c.protect_brewable = c.protect_brewable ~= 0
c.protect_edible = c.protect_edible ~= 0 c.protect_edible = c.protect_edible ~= 0
c.protect_cookable = c.protect_cookable ~= 0 c.protect_cookable = c.protect_cookable ~= 0
table.insert(ret.burrow_configs, c)
end end
return ret return ret
end end

@ -64,8 +64,10 @@ function getItemCountsAndStockpileConfigs()
ret.item_counts = table.remove(data, 1) ret.item_counts = table.remove(data, 1)
ret.marked_item_counts = table.remove(data, 1) ret.marked_item_counts = table.remove(data, 1)
ret.premarked_item_counts = table.remove(data, 1) ret.premarked_item_counts = table.remove(data, 1)
ret.stockpile_configs = data local unparsed_stockpile_configs = table.remove(data, 1)
for _,c in ipairs(ret.stockpile_configs) do ret.stockpile_configs = {}
for idx,c in pairs(unparsed_stockpile_configs) do
if not c.id or c.id == -1 then if not c.id or c.id == -1 then
c.name = "ERROR" c.name = "ERROR"
c.monitored = false c.monitored = false
@ -76,6 +78,7 @@ function getItemCountsAndStockpileConfigs()
end end
c.monitored = c.monitored ~= 0 c.monitored = c.monitored ~= 0
end end
table.insert(ret.stockpile_configs, c)
end end
return ret return ret