Fixed writing out of bounds when the whole buffer is copied
parent
f5ecd42057
commit
228e41b71e
|
@ -44,6 +44,8 @@ Ongoing development - `master`
|
|||
- Fixes
|
||||
- `VoxelGeneratorGraph`: changes to node properties are now saved properly
|
||||
- `VoxelBuffer`: `copy_voxel_metadata_in_area` was checking the source box incorrectly
|
||||
- `VoxelBuffer`: multiple calls to `create()` with different sizes could lead to heap corruption if a channel was not uniform
|
||||
- `VoxelBuffer`: `copy_channel_from_area` could lead to heap corruption if the source and destination had the same size and were copied entirely
|
||||
- `VoxelMesherTransvoxel`: no longer crashes when the input buffer is not cubic
|
||||
- `VoxelLodTerrain`: fixed errors and crashes when editing voxels near loading borders
|
||||
- `VoxelLodTerrain`: fixed crash occurring after a few edits when LOD count is set to 1
|
||||
|
|
|
@ -26,7 +26,8 @@ void copy_3d_region_zxy(
|
|||
|
||||
if (area_size == src_size && area_size == dst_size) {
|
||||
// Copy everything
|
||||
memcpy(dst.data(), src.data(), dst.size() * item_size);
|
||||
ERR_FAIL_COND(dst.size() != src.size());
|
||||
memcpy(dst.data(), src.data(), dst.size());
|
||||
|
||||
} else {
|
||||
// Copy area row by row:
|
||||
|
@ -40,6 +41,10 @@ void copy_3d_region_zxy(
|
|||
unsigned int src_ri = Vector3i(src_min + pos).get_zxy_index(src_size) * item_size;
|
||||
unsigned int dst_ri = Vector3i(dst_min + pos).get_zxy_index(dst_size) * item_size;
|
||||
for (; pos.x < area_size.x; ++pos.x) {
|
||||
#ifdef DEBUG_ENABLED
|
||||
ERR_FAIL_COND(dst_ri >= dst.size());
|
||||
ERR_FAIL_COND(dst.size() - dst_ri < area_size.y * item_size);
|
||||
#endif
|
||||
// TODO Cast src and dst to `restrict` so the optimizer can assume adresses don't overlap,
|
||||
// which might allow to write as a for loop (which may compile as a `memcpy`)?
|
||||
memcpy(&dst[dst_ri], &src[src_ri], area_size.y * item_size);
|
||||
|
|
|
@ -238,24 +238,42 @@ void test_encode_weights_packed_u16() {
|
|||
}
|
||||
|
||||
void test_copy_3d_region_zxy() {
|
||||
std::vector<uint16_t> src;
|
||||
std::vector<uint16_t> dst;
|
||||
const Vector3i src_size(8, 8, 8);
|
||||
const Vector3i dst_size(3, 4, 5);
|
||||
src.resize(src_size.volume(), 0);
|
||||
dst.resize(src_size.volume(), 0);
|
||||
for (unsigned int i = 0; i < src.size(); ++i) {
|
||||
src[i] = i;
|
||||
}
|
||||
struct L {
|
||||
static void compare(
|
||||
Span<const uint16_t> srcs, Vector3i src_size, Vector3i src_min, Vector3i src_max,
|
||||
Span<const uint16_t> dsts, Vector3i dst_size, Vector3i dst_min) {
|
||||
Vector3i pos;
|
||||
for (pos.z = src_min.z; pos.z < src_max.z; ++pos.z) {
|
||||
for (pos.x = src_min.x; pos.x < src_max.x; ++pos.x) {
|
||||
for (pos.y = src_min.y; pos.y < src_max.y; ++pos.y) {
|
||||
const uint16_t srcv = srcs[pos.get_zxy_index(src_size)];
|
||||
const uint16_t dstv = dsts[(pos - src_min + dst_min).get_zxy_index(dst_size)];
|
||||
ERR_FAIL_COND(srcv != dstv);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
// Sub-region
|
||||
{
|
||||
std::vector<uint16_t> src;
|
||||
std::vector<uint16_t> dst;
|
||||
const Vector3i src_size(8, 8, 8);
|
||||
const Vector3i dst_size(3, 4, 5);
|
||||
src.resize(src_size.volume(), 0);
|
||||
dst.resize(src_size.volume(), 0);
|
||||
for (unsigned int i = 0; i < src.size(); ++i) {
|
||||
src[i] = i;
|
||||
}
|
||||
|
||||
Span<const uint16_t> srcs = to_span_const(src);
|
||||
Span<uint16_t> dsts = to_span(dst);
|
||||
const Vector3i dst_min(0, 0, 0);
|
||||
const Vector3i src_min(2, 1, 0);
|
||||
const Vector3i src_max(5, 4, 3);
|
||||
copy_3d_region_zxy(dsts, dst_size, dst_min, srcs, src_size, src_min, src_max);
|
||||
Span<const uint16_t> srcs = to_span_const(src);
|
||||
Span<uint16_t> dsts = to_span(dst);
|
||||
const Vector3i dst_min(0, 0, 0);
|
||||
const Vector3i src_min(2, 1, 0);
|
||||
const Vector3i src_max(5, 4, 3);
|
||||
copy_3d_region_zxy(dsts, dst_size, dst_min, srcs, src_size, src_min, src_max);
|
||||
|
||||
/*for (pos.y = src_min.y; pos.y < src_max.y; ++pos.y) {
|
||||
/*for (pos.y = src_min.y; pos.y < src_max.y; ++pos.y) {
|
||||
String s;
|
||||
for (pos.x = src_min.x; pos.x < src_max.x; ++pos.x) {
|
||||
const uint16_t v = srcs[pos.get_zxy_index(src_size)];
|
||||
|
@ -287,15 +305,28 @@ void test_copy_3d_region_zxy() {
|
|||
print_line(s);
|
||||
}*/
|
||||
|
||||
Vector3i pos;
|
||||
for (pos.z = src_min.z; pos.z < src_max.z; ++pos.z) {
|
||||
for (pos.x = src_min.x; pos.x < src_max.x; ++pos.x) {
|
||||
for (pos.y = src_min.y; pos.y < src_max.y; ++pos.y) {
|
||||
const uint16_t srcv = srcs[pos.get_zxy_index(src_size)];
|
||||
const uint16_t dstv = dsts[(pos - src_min + dst_min).get_zxy_index(dst_size)];
|
||||
ERR_FAIL_COND(srcv != dstv);
|
||||
}
|
||||
L::compare(srcs, src_size, src_min, src_max, to_span_const(dsts), dst_size, dst_min);
|
||||
}
|
||||
// Same size, full region
|
||||
{
|
||||
std::vector<uint16_t> src;
|
||||
std::vector<uint16_t> dst;
|
||||
const Vector3i src_size(3, 4, 5);
|
||||
const Vector3i dst_size(3, 4, 5);
|
||||
src.resize(src_size.volume(), 0);
|
||||
dst.resize(src_size.volume(), 0);
|
||||
for (unsigned int i = 0; i < src.size(); ++i) {
|
||||
src[i] = i;
|
||||
}
|
||||
|
||||
Span<const uint16_t> srcs = to_span_const(src);
|
||||
Span<uint16_t> dsts = to_span(dst);
|
||||
const Vector3i dst_min(0, 0, 0);
|
||||
const Vector3i src_min(0, 0, 0);
|
||||
const Vector3i src_max = src_max;
|
||||
copy_3d_region_zxy(dsts, dst_size, dst_min, srcs, src_size, src_min, src_max);
|
||||
|
||||
L::compare(srcs, src_size, src_min, src_max, to_span_const(dsts), dst_size, dst_min);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -150,4 +150,9 @@ Span<const T> to_span_const(const FixedArray<T, N> &a) {
|
|||
return Span<const T>(a.data(), 0, a.size());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Span<const T> to_span_const(const Span<T> &a) {
|
||||
return Span<const T>(a.data(), 0, a.size());
|
||||
}
|
||||
|
||||
#endif // SPAN_H
|
||||
|
|
Loading…
Reference in New Issue