Skip to content

Commit 705ed5e

Browse files
authored
Merge pull request #61 from csiro-internal/bugfix/check_dims_overflow
Check if voxel count exceeds std::numeric_limits<int>::max()
2 parents f96934c + 90a3aae commit 705ed5e

1 file changed

Lines changed: 38 additions & 15 deletions

File tree

raylib/rayrenderer.h

Lines changed: 38 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
#include "raycuboid.h"
1010
#include "raypose.h"
1111
#include "rayutils.h"
12-
#define FLAT_TOP_COMPENSATION // use a 2-medium model for the top of the cloud, so only the cloud's density is estimated, not the air above it
12+
#define FLAT_TOP_COMPENSATION // use a 2-medium model for the top of the cloud, so only the cloud's density is
13+
// estimated, not the air above it
1314

1415
namespace ray
1516
{
@@ -45,8 +46,8 @@ bool RAYLIB_EXPORT renderCloud(const std::string &cloud_file, const Cuboid &boun
4546
#if RAYLIB_WITH_TIFF
4647
// save to geotif format using floating-point per-channel colour data. This function passes a projection file in order
4748
// to geolocate the image
48-
bool RAYLIB_EXPORT writeGeoTiffFloat(const std::string &filename, int x, int y, const float *data, double pixel_width, bool scalar,
49-
const std::string &projection_file, double origin_x, double origin_y);
49+
bool RAYLIB_EXPORT writeGeoTiffFloat(const std::string &filename, int x, int y, const float *data, double pixel_width,
50+
bool scalar, const std::string &projection_file, double origin_x, double origin_y);
5051
#endif
5152

5253
/// This is used for estimating the per-voxel density of a ray cloud
@@ -65,6 +66,23 @@ struct RAYLIB_EXPORT DensityGrid
6566
, voxel_width_(vox_width)
6667
, voxel_dims_(dims)
6768
{
69+
// 3D dimensions are stored in a vector of 32-bit signed ints. It's fairly
70+
// easy to overflow when calculating voxel counts or 1D indices. Make sure
71+
// this won't happen.
72+
const std::size_t voxel_count =
73+
static_cast<std::size_t>(dims[0]) * static_cast<std::size_t>(dims[1]) * static_cast<std::size_t>(dims[2]);
74+
if (voxel_count > static_cast<std::size_t>(std::numeric_limits<int>::max()))
75+
{
76+
std::cerr << " dims[0]: " << dims[0] << '\n';
77+
std::cerr << " dims[1]: " << dims[1] << '\n';
78+
std::cerr << " dims[2]: " << dims[2] << '\n';
79+
std::cerr << " dims[0] * dims[1] * dims[2]: " << voxel_count << '\n';
80+
std::cerr << "std::numeric_limits<int>::max(): " << std::numeric_limits<int>::max() << '\n';
81+
throw std::runtime_error("Dimensions given to ray::DensityGrid are too large. "
82+
"Their product must be less than std::numeric_limits<int>::max().");
83+
}
84+
85+
// Allocate.
6886
voxels_.resize(dims[0] * dims[1] * dims[2]);
6987
peaks_.resize(dims[0] * dims[1], std::numeric_limits<double>::lowest());
7088
}
@@ -111,13 +129,14 @@ struct RAYLIB_EXPORT DensityGrid
111129
inline int getIndexFromPos(const Eigen::Vector3d &pos) const;
112130
/// Return the vector of density voxels
113131
inline const std::vector<Voxel> &voxels() const { return voxels_; }
114-
inline Eigen::Vector3i dimensions(){ return voxel_dims_; }
115-
inline Cuboid bounds(){ return bounds_; }
132+
inline Eigen::Vector3i dimensions() { return voxel_dims_; }
133+
inline Cuboid bounds() { return bounds_; }
116134
inline double voxelWidth() const { return voxel_width_; }
117135
// used in walking grid only
118-
inline bool operator()(const Eigen::Vector3i &p, const Eigen::Vector3i &target, double in_length, double out_length, double max_length);
136+
inline bool operator()(const Eigen::Vector3i &p, const Eigen::Vector3i &target, double in_length, double out_length,
137+
double max_length);
119138

120-
std::vector<double> peaks_; // highest points
139+
std::vector<double> peaks_; // highest points
121140
private:
122141
Cuboid bounds_;
123142
std::vector<Voxel> voxels_;
@@ -137,7 +156,7 @@ double DensityGrid::Voxel::numerator() const
137156
}
138157
double DensityGrid::Voxel::denominator() const
139158
{
140-
const double eps = 1e-10; // avoid division by 0
159+
const double eps = 1e-10; // avoid division by 0
141160
return eps + num_rays_ * path_length_;
142161
}
143162
double DensityGrid::Voxel::density() const
@@ -146,7 +165,7 @@ double DensityGrid::Voxel::density() const
146165
{
147166
return 0.0;
148167
}
149-
const double eps = 1e-10; // avoid division by 0
168+
const double eps = 1e-10; // avoid division by 0
150169
// below -1.0 should be -2.0 when min length is estimated (e.g. when initially air)
151170
return spherical_distribution_scale * (num_rays_ - 1.0) * num_hits_ / (eps + num_rays_ * path_length_);
152171
}
@@ -184,20 +203,24 @@ int DensityGrid::getIndexFromPos(const Eigen::Vector3d &pos) const
184203
Eigen::Vector3d gridspace = (pos - bounds_.min_bound_) / voxel_width_;
185204
return getIndex(gridspace.cast<int>());
186205
}
187-
inline bool DensityGrid::operator()(const Eigen::Vector3i &p, const Eigen::Vector3i &target, double in_length, double out_length, double max_length)
206+
inline bool DensityGrid::operator()(const Eigen::Vector3i &p, const Eigen::Vector3i &target, double in_length,
207+
double out_length, double max_length)
188208
{
189209
int index = getIndex(p);
190210
double end_length = std::min(out_length, max_length);
191211

192212
#if defined FLAT_TOP_COMPENSATION
193213
int peak_id = p[0] + p[1] * voxel_dims_[0];
194214
double peak = peaks_[peak_id];
195-
double in_height = source_[2] + dir_[2]*in_length;
196-
double end_height = source_[2] + dir_[2]*end_length;
197-
if (dir_[2] < 0.0 && in_height > peak && end_height <= peak) // currently only supported on downwards rays
215+
double in_height = source_[2] + dir_[2] * in_length;
216+
double end_height = source_[2] + dir_[2] * end_length;
217+
if (dir_[2] < 0.0 && in_height > peak && end_height <= peak) // currently only supported on downwards rays
198218
{
199-
double t = (in_height - peak)/(in_height - end_height);
200-
in_length += (end_length - in_length) * std::max(0.0, std::min(t, 0.99)); // 0.99 because 1 can cause very tiny distances, which can give density outliers
219+
double t = (in_height - peak) / (in_height - end_height);
220+
in_length +=
221+
(end_length - in_length) *
222+
std::max(0.0,
223+
std::min(t, 0.99)); // 0.99 because 1 can cause very tiny distances, which can give density outliers
201224
}
202225
#endif
203226

0 commit comments

Comments
 (0)