Skip to content

Commit bc6d2f7

Browse files
committed
harden against wrong data length entries
1 parent d091777 commit bc6d2f7

File tree

2 files changed

+14
-11
lines changed

2 files changed

+14
-11
lines changed

hekatoolslib/hkTree.cpp

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -62,28 +62,28 @@ namespace hkLib {
6262
/// header of tree as stored in file
6363
/// </summary>
6464
struct TreeRoot {
65-
uint32_t Magic, //!< magic nummber MagicNumber or SwappedMagicNumber
65+
std::uint32_t Magic, //!< magic nummber MagicNumber or SwappedMagicNumber
6666
nLevels, //!< number of tree levels
6767
LevelSizes[1]; //!< variable length array (nLevels entries with size of level data in bytes)
6868
};
6969

70-
void hkTree::LoadToNode(hkTreeNode* parent, hkTreeNode& node, char** pdata, int level)
70+
void hkLib::hkTree::LoadToNode(hkTreeNode* parent, hkTreeNode& node, char** pdata, char* data_end, int level)
7171
{
7272
node.tree = this;
7373
auto size = static_cast<std::size_t>(LevelSizes.at(level));
7474
node.level = level;
75-
//node.len = size;
7675
node.isSwapped = isSwapped;
7776
node.Parent = parent;
78-
node.Data = std::span( *pdata, size );
77+
node.Data = std::span(*pdata, size);
7978
*pdata += size;
80-
uint32_t nchildren;
81-
std::memcpy(&nchildren, *pdata, sizeof(uint32_t));
79+
std::uint32_t nchildren;
80+
if (*pdata + sizeof(std::uint32_t) >= data_end) throw std::runtime_error("not enough data");
81+
std::memcpy(&nchildren, *pdata, sizeof(std::uint32_t));
8282
if (isSwapped) { swapInPlace(nchildren); }
83-
*pdata += sizeof(uint32_t);
83+
*pdata += sizeof(std::uint32_t);
8484
node.Children.resize(nchildren);
8585
for (auto& child : node.Children) {
86-
LoadToNode(&node, child, pdata, level + 1);
86+
LoadToNode(&node, child, pdata, data_end, level + 1);
8787
}
8888
}
8989

@@ -103,6 +103,7 @@ namespace hkLib {
103103

104104
bool hkTree::InitFromBuffer(const std::string_view& id, char* buffer, std::size_t len)
105105
{
106+
if (len < sizeof(TreeRoot)) throw std::runtime_error("invalid TreeRoot (too few bytes in file)");
106107
ID = id;
107108
TreeRoot* root = reinterpret_cast<TreeRoot*>(buffer); // we assume buffer is correctly aligned
108109
isSwapped = false;
@@ -116,12 +117,14 @@ namespace hkLib {
116117
if (isSwapped) {
117118
swapInPlace(root->nLevels);
118119
}
120+
const auto root_bytes = offsetof(TreeRoot, LevelSizes) + sizeof(std::uint32_t) * root->nLevels;
121+
if (len < root_bytes) throw std::runtime_error("invalid TreeRoot (too few bytes in file)");
119122
for (std::size_t i = 0; i < root->nLevels; ++i) {
120123
if (isSwapped) { swapInPlace(root->LevelSizes[i]); }
121124
LevelSizes.push_back(root->LevelSizes[i]);
122125
}
123-
char* data = buffer + offsetof(TreeRoot, LevelSizes) + sizeof(uint32_t) * root->nLevels; // start of first tree node
124-
LoadToNode(nullptr, RootNode, &data, 0);
126+
char* data = buffer + root_bytes; // start of first tree node
127+
LoadToNode(nullptr, RootNode, &data, data + len, 0);
125128
if (data - buffer != static_cast<std::ptrdiff_t>(len)) {
126129
throw std::runtime_error("bytes read != bytes in buffer");
127130
}

hekatoolslib/hkTree.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,7 @@ namespace hkLib {
336336
std::unique_ptr<char[]> Data{};
337337
double time0{};
338338
bool isSwapped;
339-
void LoadToNode(hkTreeNode* parent, hkTreeNode& node, char** pdata, int level);
339+
void LoadToNode(hkTreeNode* parent, hkTreeNode& node, char** pdata, char* data_end, int level);
340340
public:
341341
hkTree() : LevelSizes{}, RootNode{}, isSwapped{ false } {};
342342
std::string getID() {

0 commit comments

Comments
 (0)