forked from Mirrorlandia_minetest/minetest
Fix find_nodes_in_area misbehaving with out-of-map coordinates (#11770)
This ensures that no overflows (side-effects) happen within the find_nodes_in_area function by limiting coordinates like done in the map generation code.
This commit is contained in:
parent
b9051386ae
commit
87ab97da2a
@ -880,6 +880,21 @@ int ModApiEnvMod::l_find_node_near(lua_State *L)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void checkArea(v3s16 &minp, v3s16 &maxp)
|
||||||
|
{
|
||||||
|
auto volume = VoxelArea(minp, maxp).getVolume();
|
||||||
|
// Volume limit equal to 8 default mapchunks, (80 * 2) ^ 3 = 4,096,000
|
||||||
|
if (volume > 4096000) {
|
||||||
|
throw LuaError("Area volume exceeds allowed value of 4096000");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clamp to map range to avoid problems
|
||||||
|
#define CLAMP(arg) core::clamp(arg, (s16)-MAX_MAP_GENERATION_LIMIT, (s16)MAX_MAP_GENERATION_LIMIT)
|
||||||
|
minp = v3s16(CLAMP(minp.X), CLAMP(minp.Y), CLAMP(minp.Z));
|
||||||
|
maxp = v3s16(CLAMP(maxp.X), CLAMP(maxp.Y), CLAMP(maxp.Z));
|
||||||
|
#undef CLAMP
|
||||||
|
}
|
||||||
|
|
||||||
// find_nodes_in_area(minp, maxp, nodenames, [grouped])
|
// find_nodes_in_area(minp, maxp, nodenames, [grouped])
|
||||||
int ModApiEnvMod::l_find_nodes_in_area(lua_State *L)
|
int ModApiEnvMod::l_find_nodes_in_area(lua_State *L)
|
||||||
{
|
{
|
||||||
@ -899,13 +914,7 @@ int ModApiEnvMod::l_find_nodes_in_area(lua_State *L)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
v3s16 cube = maxp - minp + 1;
|
checkArea(minp, maxp);
|
||||||
// Volume limit equal to 8 default mapchunks, (80 * 2) ^ 3 = 4,096,000
|
|
||||||
if ((u64)cube.X * (u64)cube.Y * (u64)cube.Z > 4096000) {
|
|
||||||
luaL_error(L, "find_nodes_in_area(): area volume"
|
|
||||||
" exceeds allowed value of 4096000");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<content_t> filter;
|
std::vector<content_t> filter;
|
||||||
collectNodeIds(L, 3, ndef, filter);
|
collectNodeIds(L, 3, ndef, filter);
|
||||||
@ -1010,13 +1019,7 @@ int ModApiEnvMod::l_find_nodes_in_area_under_air(lua_State *L)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
v3s16 cube = maxp - minp + 1;
|
checkArea(minp, maxp);
|
||||||
// Volume limit equal to 8 default mapchunks, (80 * 2) ^ 3 = 4,096,000
|
|
||||||
if ((u64)cube.X * (u64)cube.Y * (u64)cube.Z > 4096000) {
|
|
||||||
luaL_error(L, "find_nodes_in_area_under_air(): area volume"
|
|
||||||
" exceeds allowed value of 4096000");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<content_t> filter;
|
std::vector<content_t> filter;
|
||||||
collectNodeIds(L, 3, ndef, filter);
|
collectNodeIds(L, 3, ndef, filter);
|
||||||
|
@ -30,6 +30,7 @@ public:
|
|||||||
|
|
||||||
void test_addarea();
|
void test_addarea();
|
||||||
void test_pad();
|
void test_pad();
|
||||||
|
void test_extent();
|
||||||
void test_volume();
|
void test_volume();
|
||||||
void test_contains_voxelarea();
|
void test_contains_voxelarea();
|
||||||
void test_contains_point();
|
void test_contains_point();
|
||||||
@ -65,6 +66,7 @@ void TestVoxelArea::runTests(IGameDef *gamedef)
|
|||||||
{
|
{
|
||||||
TEST(test_addarea);
|
TEST(test_addarea);
|
||||||
TEST(test_pad);
|
TEST(test_pad);
|
||||||
|
TEST(test_extent);
|
||||||
TEST(test_volume);
|
TEST(test_volume);
|
||||||
TEST(test_contains_voxelarea);
|
TEST(test_contains_voxelarea);
|
||||||
TEST(test_contains_point);
|
TEST(test_contains_point);
|
||||||
@ -113,10 +115,22 @@ void TestVoxelArea::test_pad()
|
|||||||
UASSERT(v1.MaxEdge == v3s16(-47, -9347, 969));
|
UASSERT(v1.MaxEdge == v3s16(-47, -9347, 969));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TestVoxelArea::test_extent()
|
||||||
|
{
|
||||||
|
VoxelArea v1(v3s16(-1337, -547, -789), v3s16(-147, 447, 669));
|
||||||
|
UASSERT(v1.getExtent() == v3s16(1191, 995, 1459));
|
||||||
|
|
||||||
|
VoxelArea v2(v3s16(32493, -32507, 32753), v3s16(32508, -32492, 32768));
|
||||||
|
UASSERT(v2.getExtent() == v3s16(16, 16, 16));
|
||||||
|
}
|
||||||
|
|
||||||
void TestVoxelArea::test_volume()
|
void TestVoxelArea::test_volume()
|
||||||
{
|
{
|
||||||
VoxelArea v1(v3s16(-1337, 447, -789), v3s16(-147, -9547, 669));
|
VoxelArea v1(v3s16(-1337, -547, -789), v3s16(-147, 447, 669));
|
||||||
UASSERTEQ(s32, v1.getVolume(), -184657133);
|
UASSERTEQ(s32, v1.getVolume(), 1728980655);
|
||||||
|
|
||||||
|
VoxelArea v2(v3s16(32493, -32507, 32753), v3s16(32508, -32492, 32768));
|
||||||
|
UASSERTEQ(s32, v2.getVolume(), 4096);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestVoxelArea::test_contains_voxelarea()
|
void TestVoxelArea::test_contains_voxelarea()
|
||||||
|
Loading…
Reference in New Issue
Block a user