java-topology/defects/minetest-0003/patch/minetest-0003.patch
russell@unturf.com a86a765544 minetest (Luanti): 5 CWE-407 defects, all 5 MOADs scanned
minetest-0001: mg_ore.cpp c_wherein vector CONTAINS in voxel inner loop O(V*W) HIGH 3.3x
minetest-0002: mg_decoration.cpp c_place_on/c_spawnby vector CONTAINS O(S*P) MEDIUM 1.8x
minetest-0003: l_env.cpp find_node_near/find_nodes_in_area filter CONTAINS O(V*F) MEDIUM 1.6x
minetest-0004: nodedef.cpp nodeboxConnects sorted vector linear scan O(N) MEDIUM 2.1x
minetest-0005: blockmodifier.cpp ABM neighbor check sorted vector O(N) LOW-MEDIUM 1.5x

MOAD-0002: g_settings global singleton (architectural, not patchable)
MOAD-0003: thread_local log streams (properly scoped, not leaked context)
MOAD-0004: CLEAN (no credential logging found)
MOAD-0005: CLEAN (no unsynchronized cache patterns found)
2026-03-31 10:10:03 -04:00

56 lines
2.2 KiB
Diff

# UNDF: UNDF-2026-000000940
--- a/src/script/lua_api/l_env.cpp
+++ b/src/script/lua_api/l_env.cpp
@@ -809,11 +809,12 @@ template <typename F>
int ModApiEnvBase::findNodeNear(lua_State *L, v3s16 pos, int radius,
- const std::vector<content_t> &filter, int start_radius, F &&getNode)
+ const std::vector<content_t> &filter_vec, int start_radius, F &&getNode)
{
+ std::unordered_set<content_t> filter(filter_vec.begin(), filter_vec.end());
for (int d = start_radius; d <= radius; d++) {
const std::vector<v3s16> &list = FacePositionCache::getFacePositions(d);
for (const v3s16 &i : list) {
v3s16 p = pos + i;
content_t c = getNode(p).getContent();
- if (CONTAINS(filter, c)) {
+ if (filter.count(c) > 0) {
push_v3s16(L, p);
return 1;
@@ -884,7 +885,8 @@ int ModApiEnvBase::findNodesInArea(lua_State *L, const NodeDefManager *ndef,
iterate([&](v3s16 p, MapNode n) -> bool {
content_t c = n.getContent();
-
- auto it = std::find(filter.begin(), filter.end(), c);
- if (it != filter.end()) {
+ // Build a hash map for O(1) lookup; also need index, so use
+ // unordered_map<content_t, u32> built once before the iterate.
+ auto it = filter_map.find(c);
+ if (it != filter_map.end()) {
// Calculate index of the table and append the position
- u32 filt_index = it - filter.begin();
+ u32 filt_index = it->second;
// Similarly for the non-grouped branch:
@@ -918,8 +920,8 @@ int ModApiEnvBase::findNodesInArea(...)
iterate([&](v3s16 p, MapNode n) -> bool {
content_t c = n.getContent();
-
- auto it = std::find(filter.begin(), filter.end(), c);
- if (it != filter.end()) {
+ auto it = filter_map.find(c);
+ if (it != filter_map.end()) {
push_v3s16(L, p);
lua_rawseti(L, -2, ++i);
- u32 filt_index = it - filter.begin();
+ u32 filt_index = it->second;
// findNodesInAreaUnderAir: same pattern
@@ -989,7 +991,7 @@ int ModApiEnvBase::findNodesInAreaUnderAir(...)
+ std::unordered_set<content_t> filter_set(filter.begin(), filter.end());
for (p.X = minp.X; p.X <= maxp.X; p.X++)
for (p.Z = minp.Z; p.Z <= maxp.Z; p.Z++) {
...
if (c != CONTENT_AIR && csurf == CONTENT_AIR &&
- CONTAINS(filter, c)) {
+ filter_set.count(c) > 0) {