mirror of
https://github.com/minetest/minetest.git
synced 2025-03-06 20:48:40 +01:00
Prevent VoxelManipulator size overflow
This commit is contained in:
parent
2cdf3af1b8
commit
9dd09d1056
4 changed files with 33 additions and 31 deletions
|
@ -5044,7 +5044,7 @@ inside the VoxelManip.
|
||||||
can use `core.emerge_area` to make sure that the area you want to
|
can use `core.emerge_area` to make sure that the area you want to
|
||||||
read/write is already generated.
|
read/write is already generated.
|
||||||
|
|
||||||
* Other mods, or the core itself, could possibly modify the area of the map
|
* Other mods, or the engine itself, could possibly modify the area of the map
|
||||||
currently loaded into a VoxelManip object. With the exception of Mapgen
|
currently loaded into a VoxelManip object. With the exception of Mapgen
|
||||||
VoxelManips (see above section), the internal buffers are not updated. For
|
VoxelManips (see above section), the internal buffers are not updated. For
|
||||||
this reason, it is strongly encouraged to complete the usage of a particular
|
this reason, it is strongly encouraged to complete the usage of a particular
|
||||||
|
@ -5059,9 +5059,11 @@ inside the VoxelManip.
|
||||||
Methods
|
Methods
|
||||||
-------
|
-------
|
||||||
|
|
||||||
* `read_from_map(p1, p2)`: Loads a chunk of map into the VoxelManip object
|
* `read_from_map(p1, p2)`: Loads a chunk of map into the VoxelManip object
|
||||||
containing the region formed by `p1` and `p2`.
|
containing the region formed by `p1` and `p2`.
|
||||||
* returns actual emerged `pmin`, actual emerged `pmax`
|
* returns actual emerged `pmin`, actual emerged `pmax`
|
||||||
|
* Note that calling this multiple times will *add* to the area loaded in the
|
||||||
|
VoxelManip, and not reset it.
|
||||||
* `write_to_map([light])`: Writes the data loaded from the `VoxelManip` back to
|
* `write_to_map([light])`: Writes the data loaded from the `VoxelManip` back to
|
||||||
the map.
|
the map.
|
||||||
* **important**: data must be set using `VoxelManip:set_data()` before
|
* **important**: data must be set using `VoxelManip:set_data()` before
|
||||||
|
@ -5120,8 +5122,8 @@ Methods
|
||||||
generated mapchunk above are propagated down into the mapchunk, defaults
|
generated mapchunk above are propagated down into the mapchunk, defaults
|
||||||
to `true` if left out.
|
to `true` if left out.
|
||||||
* `update_liquids()`: Update liquid flow
|
* `update_liquids()`: Update liquid flow
|
||||||
* `was_modified()`: Returns `true` if the data in the voxel manipulator has been modified
|
* `was_modified()`: Returns `true` if the data in the VoxelManip has been modified
|
||||||
since it was last read from the map. This means you have to call `get_data` again.
|
since it was last read from the map. This means you have to call `get_data()` again.
|
||||||
This only applies to a `VoxelManip` object from `core.get_mapgen_object`,
|
This only applies to a `VoxelManip` object from `core.get_mapgen_object`,
|
||||||
where the engine will keep the map and the VM in sync automatically.
|
where the engine will keep the map and the VM in sync automatically.
|
||||||
* Note: this doesn't do what you think it does and is subject to removal. Don't use it!
|
* Note: this doesn't do what you think it does and is subject to removal. Don't use it!
|
||||||
|
|
17
src/map.cpp
17
src/map.cpp
|
@ -752,17 +752,12 @@ MMVManip::MMVManip(Map *map):
|
||||||
assert(map);
|
assert(map);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MMVManip::initialEmerge(v3s16 blockpos_min, v3s16 blockpos_max,
|
void MMVManip::initialEmerge(v3s16 p_min, v3s16 p_max, bool load_if_inexistent)
|
||||||
bool load_if_inexistent)
|
|
||||||
{
|
{
|
||||||
TimeTaker timer1("initialEmerge", &emerge_time);
|
TimeTaker timer1("initialEmerge", &emerge_time);
|
||||||
|
|
||||||
assert(m_map);
|
assert(m_map);
|
||||||
|
|
||||||
// Units of these are MapBlocks
|
|
||||||
v3s16 p_min = blockpos_min;
|
|
||||||
v3s16 p_max = blockpos_max;
|
|
||||||
|
|
||||||
VoxelArea block_area_nodes
|
VoxelArea block_area_nodes
|
||||||
(p_min*MAP_BLOCKSIZE, (p_max+1)*MAP_BLOCKSIZE-v3s16(1,1,1));
|
(p_min*MAP_BLOCKSIZE, (p_max+1)*MAP_BLOCKSIZE-v3s16(1,1,1));
|
||||||
|
|
||||||
|
@ -775,6 +770,7 @@ void MMVManip::initialEmerge(v3s16 blockpos_min, v3s16 blockpos_max,
|
||||||
infostream<<std::endl;
|
infostream<<std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const bool all_new = m_area.hasEmptyExtent() || block_area_nodes.contains(m_area);
|
||||||
addArea(block_area_nodes);
|
addArea(block_area_nodes);
|
||||||
|
|
||||||
for(s32 z=p_min.Z; z<=p_max.Z; z++)
|
for(s32 z=p_min.Z; z<=p_max.Z; z++)
|
||||||
|
@ -812,16 +808,12 @@ void MMVManip::initialEmerge(v3s16 blockpos_min, v3s16 blockpos_max,
|
||||||
setFlags(a, VOXELFLAG_NO_DATA);
|
setFlags(a, VOXELFLAG_NO_DATA);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*else if (block->getNode(0, 0, 0).getContent() == CONTENT_IGNORE)
|
|
||||||
{
|
|
||||||
// Mark that block was loaded as blank
|
|
||||||
flags |= VMANIP_BLOCK_CONTAINS_CIGNORE;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
m_loaded_blocks[p] = flags;
|
m_loaded_blocks[p] = flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_is_dirty = false;
|
if (all_new)
|
||||||
|
m_is_dirty = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MMVManip::blitBackAll(std::map<v3s16, MapBlock*> *modified_blocks,
|
void MMVManip::blitBackAll(std::map<v3s16, MapBlock*> *modified_blocks,
|
||||||
|
@ -834,6 +826,7 @@ void MMVManip::blitBackAll(std::map<v3s16, MapBlock*> *modified_blocks,
|
||||||
/*
|
/*
|
||||||
Copy data of all blocks
|
Copy data of all blocks
|
||||||
*/
|
*/
|
||||||
|
assert(!m_loaded_blocks.empty());
|
||||||
for (auto &loaded_block : m_loaded_blocks) {
|
for (auto &loaded_block : m_loaded_blocks) {
|
||||||
v3s16 p = loaded_block.first;
|
v3s16 p = loaded_block.first;
|
||||||
MapBlock *block = m_map->getBlockNoCreateNoEx(p);
|
MapBlock *block = m_map->getBlockNoCreateNoEx(p);
|
||||||
|
|
|
@ -298,9 +298,6 @@ protected:
|
||||||
u32 needed_count);
|
u32 needed_count);
|
||||||
};
|
};
|
||||||
|
|
||||||
#define VMANIP_BLOCK_DATA_INEXIST 1
|
|
||||||
#define VMANIP_BLOCK_CONTAINS_CIGNORE 2
|
|
||||||
|
|
||||||
class MMVManip : public VoxelManipulator
|
class MMVManip : public VoxelManipulator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -344,4 +341,8 @@ protected:
|
||||||
value = flags describing the block
|
value = flags describing the block
|
||||||
*/
|
*/
|
||||||
std::map<v3s16, u8> m_loaded_blocks;
|
std::map<v3s16, u8> m_loaded_blocks;
|
||||||
|
|
||||||
|
enum : u8 {
|
||||||
|
VMANIP_BLOCK_DATA_INEXIST = 1 << 0,
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -113,6 +113,20 @@ void VoxelManipulator::print(std::ostream &o, const NodeDefManager *ndef,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void checkArea(const VoxelArea &a)
|
||||||
|
{
|
||||||
|
// won't overflow since cbrt(2^64) > 2^16
|
||||||
|
u64 real_volume = static_cast<u64>(a.getExtent().X) * a.getExtent().Y * a.getExtent().Z;
|
||||||
|
|
||||||
|
// Volume limit equal to 8 default mapchunks, (80 * 2) ^ 3 = 4,096,000
|
||||||
|
// Note: the hard limit is somewhere around 2^31 due to s32 type
|
||||||
|
constexpr u64 MAX_ALLOWED = 4096000;
|
||||||
|
if (real_volume > MAX_ALLOWED) {
|
||||||
|
throw BaseException("VoxelManipulator: "
|
||||||
|
"Area volume exceeds allowed value of " + std::to_string(MAX_ALLOWED));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void VoxelManipulator::addArea(const VoxelArea &area)
|
void VoxelManipulator::addArea(const VoxelArea &area)
|
||||||
{
|
{
|
||||||
// Cancel if requested area has zero volume
|
// Cancel if requested area has zero volume
|
||||||
|
@ -124,18 +138,10 @@ void VoxelManipulator::addArea(const VoxelArea &area)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Calculate new area
|
// Calculate new area
|
||||||
VoxelArea new_area;
|
VoxelArea new_area = m_area;
|
||||||
// New area is the requested area if m_area has zero volume
|
new_area.addArea(area);
|
||||||
if(m_area.hasEmptyExtent())
|
|
||||||
{
|
checkArea(new_area);
|
||||||
new_area = area;
|
|
||||||
}
|
|
||||||
// Else add requested area to m_area
|
|
||||||
else
|
|
||||||
{
|
|
||||||
new_area = m_area;
|
|
||||||
new_area.addArea(area);
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 new_size = new_area.getVolume();
|
u32 new_size = new_area.getVolume();
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue