Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prevent integer overflow in NodeManager and LeafManager #1794

Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
4c3a5af
Prevents integer overflow
ghurstunither Apr 16, 2024
d57fae3
Merge remote-tracking branch 'upstream/master' into bugfix/NodeManage…
ghurstunither Oct 22, 2024
187cb1a
leafCount and friends work with Index64
ghurstunither Oct 24, 2024
a24c863
Update Tree.h
ghurstunither Oct 24, 2024
1f7798d
Update CMakeLists.txt
ghurstunither Oct 24, 2024
f13a0a8
Index64 leafCount in AX tests
ghurstunither Oct 24, 2024
fcff364
Update TestNodeVisitor.cc
ghurstunither Oct 24, 2024
3813556
More 64 bit return for TreeBase
ghurstunither Oct 30, 2024
a478a0e
Merge remote-tracking branch 'upstream/master' into bugfix/NodeManage…
ghurstunither Oct 30, 2024
135f41d
Merge remote-tracking branch 'upstream/master' into bugfix/NodeManage…
ghurstunither Oct 30, 2024
d126436
compile for versions below 12
ghurstunither Oct 30, 2024
907afa0
Update Tree.h
ghurstunither Oct 30, 2024
b1d114a
Backward compatibility for unit tests.
ghurstunither Oct 30, 2024
afbd819
Update TestNodeVisitor.cc
ghurstunither Oct 30, 2024
a76faad
Update TestVolumeExecutable.cc
ghurstunither Oct 30, 2024
97d6750
Update TestVolumeExecutable.cc
ghurstunither Oct 30, 2024
607db98
Update TestPointExecutable.cc
ghurstunither Oct 30, 2024
26f0ad1
deprecation suppression
ghurstunither Oct 30, 2024
aba7d2d
define deprecated nodeCount for all versions.
ghurstunither Oct 30, 2024
52d61fd
treeDepth stays Index
ghurstunither Oct 30, 2024
4853738
Avoid ABI conditionals in Root/Internal/Leaf
ghurstunither Oct 30, 2024
11686a8
Update TestTree.cc
ghurstunither Oct 30, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions openvdb/openvdb/io/Archive.cc
Original file line number Diff line number Diff line change
Expand Up @@ -357,10 +357,10 @@ struct PopulateDelayedLoadMetadataOp
using MaskT = typename LeafT::NodeMaskType;

const TreeT& tree = grid.constTree();
const Index32 leafCount = tree.leafCount();
const Index64 leafCount = tree.leafCount();

// early exit if not leaf nodes
if (leafCount == Index32(0)) return;
if (leafCount == Index64(0)) return;

metadata.resizeMask(leafCount);

Expand Down
2 changes: 1 addition & 1 deletion openvdb/openvdb/points/IndexFilter.h
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ class RandomLeafFilter
std::mt19937 generator(seed);
std::uniform_int_distribution<unsigned int> dist(0, std::numeric_limits<unsigned int>::max() - 1);

Index32 leafCounter = 0;
Index64 leafCounter = 0;
float totalPointsFloat = 0.0f;
int totalPoints = 0;
for (auto iter = tree.cbeginLeaf(); iter; ++iter) {
Expand Down
6 changes: 3 additions & 3 deletions openvdb/openvdb/python/pyGrid.h
Original file line number Diff line number Diff line change
Expand Up @@ -210,23 +210,23 @@ getNodeLog2Dims(const GridType& grid)


template<typename GridType>
inline Index
inline Index64
treeDepth(const GridType& grid)
{
return grid.tree().treeDepth();
}


template<typename GridType>
inline Index32
inline Index64
leafCount(const GridType& grid)
{
return grid.tree().leafCount();
}


template<typename GridType>
inline Index32
inline Index64
nonLeafCount(const GridType& grid)
{
return grid.tree().nonLeafCount();
Expand Down
32 changes: 25 additions & 7 deletions openvdb/openvdb/tree/InternalNode.h
Original file line number Diff line number Diff line change
Expand Up @@ -274,9 +274,11 @@ class InternalNode
/// Set the transient data value.
void setTransientData(Index32 transientData) { mTransientData = transientData; }

Index32 leafCount() const;
Index64 leafCount() const;
Index64 nonLeafCount() const;
void nodeCount(std::vector<Index64> &vec) const;
OPENVDB_DEPRECATED_MESSAGE("Use input type std::vector<Index64> for nodeCount.")
void nodeCount(std::vector<Index32> &vec) const;
Index32 nonLeafCount() const;
Index32 childCount() const;
Index64 onVoxelCount() const;
Index64 offVoxelCount() const;
Expand Down Expand Up @@ -1102,11 +1104,11 @@ InternalNode<ChildT, Log2Dim>::~InternalNode()


template<typename ChildT, Index Log2Dim>
inline Index32
inline Index64
InternalNode<ChildT, Log2Dim>::leafCount() const
{
if (ChildNodeType::getLevel() == 0) return mChildMask.countOn();
Index32 sum = 0;
Index64 sum = 0;
for (ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
sum += iter->leafCount();
}
Expand All @@ -1115,7 +1117,7 @@ InternalNode<ChildT, Log2Dim>::leafCount() const

template<typename ChildT, Index Log2Dim>
inline void
InternalNode<ChildT, Log2Dim>::nodeCount(std::vector<Index32> &vec) const
InternalNode<ChildT, Log2Dim>::nodeCount(std::vector<Index64> &vec) const
{
OPENVDB_ASSERT(vec.size() > ChildNodeType::LEVEL);
const auto count = mChildMask.countOn();
Expand All @@ -1125,12 +1127,28 @@ InternalNode<ChildT, Log2Dim>::nodeCount(std::vector<Index32> &vec) const
vec[ChildNodeType::LEVEL] += count;
}

template<typename ChildT, Index Log2Dim>
inline void
InternalNode<ChildT, Log2Dim>::nodeCount(std::vector<Index32> &vec) const
{
OPENVDB_ASSERT(vec.size() > ChildNodeType::LEVEL);
const auto count = mChildMask.countOn();
if (ChildNodeType::LEVEL > 0 && count > 0) {
for (auto iter = this->cbeginChildOn(); iter; ++iter) {
OPENVDB_NO_DEPRECATION_WARNING_BEGIN
iter->nodeCount(vec);
OPENVDB_NO_DEPRECATION_WARNING_END
}
}
vec[ChildNodeType::LEVEL] += count;
}


template<typename ChildT, Index Log2Dim>
inline Index32
inline Index64
InternalNode<ChildT, Log2Dim>::nonLeafCount() const
{
Index32 sum = 1;
Index64 sum = 1;
if (ChildNodeType::getLevel() == 0) return sum;
for (ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
sum += iter->nonLeafCount();
Expand Down
2 changes: 1 addition & 1 deletion openvdb/openvdb/tree/LeafManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -596,7 +596,7 @@ class LeafManager

// Compute the leaf counts for each node

std::vector<Index32> leafCounts;
std::vector<Index64> leafCounts;
if (serial) {
leafCounts.reserve(leafParents.size());
for (LeafParentT* leafParent : leafParents) {
Expand Down
6 changes: 4 additions & 2 deletions openvdb/openvdb/tree/LeafNode.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,11 +129,13 @@ class LeafNode
/// Return the dimension of child nodes of this LeafNode, which is one for voxels.
static Index getChildDim() { return 1; }
/// Return the leaf count for this node, which is one.
static Index32 leafCount() { return 1; }
static Index64 leafCount() { return 1; }
/// no-op
void nodeCount(std::vector<Index64> &) const {}
OPENVDB_DEPRECATED_MESSAGE("Use input type std::vector<Index64> for nodeCount.")
void nodeCount(std::vector<Index32> &) const {}
/// Return the non-leaf count for this node, which is zero.
static Index32 nonLeafCount() { return 0; }
static Index64 nonLeafCount() { return 0; }
/// Return the child count for this node, which is zero.
static Index32 childCount() { return 0; }

Expand Down
6 changes: 4 additions & 2 deletions openvdb/openvdb/tree/LeafNodeBool.h
Original file line number Diff line number Diff line change
Expand Up @@ -131,10 +131,12 @@ class LeafNode<bool, Log2Dim>
static void getNodeLog2Dims(std::vector<Index>& dims) { dims.push_back(Log2Dim); }
static Index getChildDim() { return 1; }

static Index32 leafCount() { return 1; }
static Index64 leafCount() { return 1; }
/// no-op
void nodeCount(std::vector<Index64> &) const {}
OPENVDB_DEPRECATED_MESSAGE("Use input type std::vector<Index64> for nodeCount.")
void nodeCount(std::vector<Index32> &) const {}
static Index32 nonLeafCount() { return 0; }
static Index64 nonLeafCount() { return 0; }

/// Return the number of active voxels.
Index64 onVoxelCount() const { return mValueMask.countOn(); }
Expand Down
6 changes: 4 additions & 2 deletions openvdb/openvdb/tree/LeafNodeMask.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,11 +112,13 @@ class LeafNode<ValueMask, Log2Dim>
/// Return the dimension of child nodes of this LeafNode, which is one for voxels.
static Index getChildDim() { return 1; }
/// Return the leaf count for this node, which is one.
static Index32 leafCount() { return 1; }
static Index64 leafCount() { return 1; }
/// no-op
void nodeCount(std::vector<Index64> &) const {}
OPENVDB_DEPRECATED_MESSAGE("Use input type std::vector<Index64> for nodeCount.")
void nodeCount(std::vector<Index32> &) const {}
/// Return the non-leaf count for this node, which is zero.
static Index32 nonLeafCount() { return 0; }
static Index64 nonLeafCount() { return 0; }

/// Return the number of active voxels.
Index64 onVoxelCount() const { return mBuffer.mData.countOn(); }
Expand Down
2 changes: 1 addition & 1 deletion openvdb/openvdb/tree/NodeManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ class NodeList
{
// Compute the node counts for each node

std::vector<Index32> nodeCounts;
std::vector<Index64> nodeCounts;
if (serial) {
nodeCounts.reserve(parents.nodeCount());
for (size_t i = 0; i < parents.nodeCount(); i++) {
Expand Down
32 changes: 26 additions & 6 deletions openvdb/openvdb/tree/RootNode.h
Original file line number Diff line number Diff line change
Expand Up @@ -484,8 +484,8 @@ class RootNode
template<typename OtherChildType>
static bool hasCompatibleValueType(const RootNode<OtherChildType>& other);

Index32 leafCount() const;
Index32 nonLeafCount() const;
Index64 leafCount() const;
Index64 nonLeafCount() const;
Index32 childCount() const;
Index32 tileCount() const;
Index32 activeTileCount() const;
Expand All @@ -495,6 +495,8 @@ class RootNode
Index64 onLeafVoxelCount() const;
Index64 offLeafVoxelCount() const;
Index64 onTileCount() const;
void nodeCount(std::vector<Index64> &vec) const;
OPENVDB_DEPRECATED_MESSAGE("Use input type std::vector<Index64> for nodeCount.")
void nodeCount(std::vector<Index32> &vec) const;

bool isValueOn(const Coord& xyz) const;
Expand Down Expand Up @@ -1539,10 +1541,10 @@ RootNode<ChildT>::evalActiveBoundingBox(CoordBBox& bbox, bool visitVoxels) const


template<typename ChildT>
inline Index32
inline Index64
RootNode<ChildT>::leafCount() const
{
Index32 sum = 0;
Index64 sum = 0;
for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
if (isChild(i)) sum += getChild(i).leafCount();
}
Expand All @@ -1551,10 +1553,10 @@ RootNode<ChildT>::leafCount() const


template<typename ChildT>
inline Index32
inline Index64
RootNode<ChildT>::nonLeafCount() const
{
Index32 sum = 1;
Index64 sum = 1;
if (ChildT::LEVEL != 0) {
for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
if (isChild(i)) sum += getChild(i).nonLeafCount();
Expand Down Expand Up @@ -1682,6 +1684,22 @@ RootNode<ChildT>::onTileCount() const
return sum;
}

template<typename ChildT>
inline void
RootNode<ChildT>::nodeCount(std::vector<Index64> &vec) const
{
OPENVDB_ASSERT(vec.size() > LEVEL);
Index64 sum = 0;
for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
if (isChild(i)) {
++sum;
getChild(i).nodeCount(vec);
}
}
vec[LEVEL] = 1;// one root node
vec[ChildNodeType::LEVEL] = sum;
}

template<typename ChildT>
inline void
RootNode<ChildT>::nodeCount(std::vector<Index32> &vec) const
Expand All @@ -1691,7 +1709,9 @@ RootNode<ChildT>::nodeCount(std::vector<Index32> &vec) const
for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
if (isChild(i)) {
++sum;
OPENVDB_NO_DEPRECATION_WARNING_BEGIN
getChild(i).nodeCount(vec);
OPENVDB_NO_DEPRECATION_WARNING_END
}
}
vec[LEVEL] = 1;// one root node
Expand Down
56 changes: 53 additions & 3 deletions openvdb/openvdb/tree/Tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,11 @@ class OPENVDB_API TreeBase
/// @sa readNonresidentBuffers, io::File::open
virtual void clipUnallocatedNodes() = 0;
/// Return the total number of unallocated leaf nodes residing in this tree.
#if OPENVDB_ABI_VERSION_NUMBER >= 12
virtual Index64 unallocatedLeafCount() const = 0;
#else
virtual Index32 unallocatedLeafCount() const = 0;
#endif


//
Expand All @@ -113,13 +117,25 @@ class OPENVDB_API TreeBase
/// A tree with only a root node and leaf nodes has depth 2, for example.
virtual Index treeDepth() const = 0;
/// Return the number of leaf nodes.
#if OPENVDB_ABI_VERSION_NUMBER >= 12
virtual Index64 leafCount() const = 0;
#else
virtual Index32 leafCount() const = 0;
danrbailey marked this conversation as resolved.
Show resolved Hide resolved
#endif
/// Return a vector with node counts. The number of nodes of type NodeType
/// is given as element NodeType::LEVEL in the return vector. Thus, the size
/// of this vector corresponds to the height (or depth) of this tree.
#if OPENVDB_ABI_VERSION_NUMBER >= 12
virtual std::vector<Index64> nodeCount() const = 0;
#else
virtual std::vector<Index32> nodeCount() const = 0;
#endif
/// Return the number of non-leaf nodes.
#if OPENVDB_ABI_VERSION_NUMBER >= 12
virtual Index64 nonLeafCount() const = 0;
#else
virtual Index32 nonLeafCount() const = 0;
#endif
/// Return the number of active voxels stored in leaf nodes.
virtual Index64 activeLeafVoxelCount() const = 0;
/// Return the number of inactive voxels stored in leaf nodes.
Expand Down Expand Up @@ -343,18 +359,37 @@ class Tree: public TreeBase
/// A tree with only a root node and leaf nodes has depth 2, for example.
Index treeDepth() const override { return DEPTH; }
/// Return the number of leaf nodes.
Index32 leafCount() const override { return mRoot.leafCount(); }
#if OPENVDB_ABI_VERSION_NUMBER >= 12
Index64 leafCount() const override { return mRoot.leafCount(); }
#else
Index32 leafCount() const override { return static_cast<Index32>(mRoot.leafCount()); }
#endif
/// Return a vector with node counts. The number of nodes of type NodeType
/// is given as element NodeType::LEVEL in the return vector. Thus, the size
/// of this vector corresponds to the height (or depth) of this tree.
#if OPENVDB_ABI_VERSION_NUMBER >= 12
std::vector<Index64> nodeCount() const override
{
std::vector<Index64> vec(DEPTH, 0);
mRoot.nodeCount( vec );
return vec;// Named Return Value Optimization
}
#else
std::vector<Index32> nodeCount() const override
{
std::vector<Index32> vec(DEPTH, 0);
OPENVDB_NO_DEPRECATION_WARNING_BEGIN
mRoot.nodeCount( vec );
OPENVDB_NO_DEPRECATION_WARNING_END
return vec;// Named Return Value Optimization
}
#endif
/// Return the number of non-leaf nodes.
Index32 nonLeafCount() const override { return mRoot.nonLeafCount(); }
#if OPENVDB_ABI_VERSION_NUMBER >= 12
Index64 nonLeafCount() const override { return mRoot.nonLeafCount(); }
#else
Index32 nonLeafCount() const override { return static_cast<Index32>(mRoot.nonLeafCount()); }
#endif
/// Return the number of active voxels stored in leaf nodes.
Index64 activeLeafVoxelCount() const override { return tools::countActiveLeafVoxels(*this); }
/// Return the number of inactive voxels stored in leaf nodes.
Expand Down Expand Up @@ -469,7 +504,11 @@ class Tree: public TreeBase
void clipUnallocatedNodes() override;

/// Return the total number of unallocated leaf nodes residing in this tree.
#if OPENVDB_ABI_VERSION_NUMBER >= 12
Index64 unallocatedLeafCount() const override;
#else
Index32 unallocatedLeafCount() const override;
#endif

//@{
/// @brief Set all voxels within a given axis-aligned box to a constant value.
Expand Down Expand Up @@ -1673,6 +1712,16 @@ Tree<RootNodeType>::clipUnallocatedNodes()
}
}

#if OPENVDB_ABI_VERSION_NUMBER >= 12
template<typename RootNodeType>
inline Index64
Tree<RootNodeType>::unallocatedLeafCount() const
{
Index64 sum = 0;
for (auto it = this->cbeginLeaf(); it; ++it) if (!it->isAllocated()) ++sum;
return sum;
}
#else
template<typename RootNodeType>
inline Index32
Tree<RootNodeType>::unallocatedLeafCount() const
Expand All @@ -1681,6 +1730,7 @@ Tree<RootNodeType>::unallocatedLeafCount() const
for (auto it = this->cbeginLeaf(); it; ++it) if (!it->isAllocated()) ++sum;
return sum;
}
#endif


template<typename RootNodeType>
Expand Down Expand Up @@ -2036,7 +2086,7 @@ Tree<RootNodeType>::print(std::ostream& os, int verboseLevel) const
}

const auto nodeCount = this->nodeCount();//fast
const Index32 leafCount = nodeCount.front();// leaf is the first element
const Index64 leafCount = nodeCount.front();// leaf is the first element
OPENVDB_ASSERT(dims.size() == nodeCount.size());

Index64 totalNodeCount = 0;
Expand Down
2 changes: 1 addition & 1 deletion openvdb/openvdb/unittest/TestFile.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1866,7 +1866,7 @@ TEST_F(TestFile, testMultiPassIO)
file.open();
const auto newGrid = GridBase::grid<MultiPassGrid>(
file.readGrid("test", BBoxd(Vec3d(0), Vec3d(1))));
EXPECT_EQ(Index32(1), newGrid->tree().leafCount());
EXPECT_EQ(Index64(1), newGrid->tree().leafCount());

auto leafIter = newGrid->tree().beginLeaf();
EXPECT_EQ(3, int(leafIter->mReadPasses.size()));
Expand Down
Loading
Loading