@@ -62,34 +62,35 @@ namespace hkLib {
62
62
// / header of tree as stored in file
63
63
// / </summary>
64
64
struct TreeRoot {
65
- uint32_t Magic, // !< magic nummber MagicNumber or SwappedMagicNumber
65
+ std:: uint32_t Magic, // !< magic nummber MagicNumber or SwappedMagicNumber
66
66
nLevels, // !< number of tree levels
67
67
LevelSizes[1 ]; // !< variable length array (nLevels entries with size of level data in bytes)
68
68
};
69
69
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)
71
71
{
72
72
node.tree = this ;
73
73
auto size = static_cast <std::size_t >(LevelSizes.at (level));
74
74
node.level = level;
75
- // node.len = size;
76
75
node.isSwapped = isSwapped;
77
76
node.Parent = parent;
78
- node.Data = std::span ( *pdata, size );
77
+ node.Data = std::span (*pdata, size);
79
78
*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 ));
82
82
if (isSwapped) { swapInPlace (nchildren); }
83
- *pdata += sizeof (uint32_t );
83
+ *pdata += sizeof (std:: uint32_t );
84
84
node.Children .resize (nchildren);
85
85
for (auto & child : node.Children ) {
86
- LoadToNode (&node, child, pdata, level + 1 );
86
+ LoadToNode (&node, child, pdata, data_end, level + 1 );
87
87
}
88
88
}
89
89
90
90
bool hkTree::InitFromStream (const std::string_view& id, std::istream& infile, int offset, unsigned int len)
91
91
{
92
92
assert (!!infile);
93
+ if (offset <= 0 || len == 0 ) throw std::runtime_error (" invalid tree data offset or length" );
93
94
Data = std::make_unique<char []>(len);
94
95
infile.seekg (offset).read (Data.get (), len);
95
96
if (!infile) {
@@ -102,6 +103,7 @@ namespace hkLib {
102
103
103
104
bool hkTree::InitFromBuffer (const std::string_view& id, char * buffer, std::size_t len)
104
105
{
106
+ if (len < sizeof (TreeRoot)) throw std::runtime_error (" invalid TreeRoot (too few bytes in file)" );
105
107
ID = id;
106
108
TreeRoot* root = reinterpret_cast <TreeRoot*>(buffer); // we assume buffer is correctly aligned
107
109
isSwapped = false ;
@@ -115,18 +117,25 @@ namespace hkLib {
115
117
if (isSwapped) {
116
118
swapInPlace (root->nLevels );
117
119
}
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)" );
118
122
for (std::size_t i = 0 ; i < root->nLevels ; ++i) {
119
123
if (isSwapped) { swapInPlace (root->LevelSizes [i]); }
120
124
LevelSizes.push_back (root->LevelSizes [i]);
121
125
}
122
- char * data = buffer + offsetof (TreeRoot, LevelSizes) + sizeof ( uint32_t ) * root-> nLevels ; // start of first tree node
123
- LoadToNode (nullptr , RootNode, &data, 0 );
126
+ char * data = buffer + root_bytes ; // start of first tree node
127
+ LoadToNode (nullptr , RootNode, &data, data + len, 0 );
124
128
if (data - buffer != static_cast <std::ptrdiff_t >(len)) {
125
129
throw std::runtime_error (" bytes read != bytes in buffer" );
126
130
}
127
131
return true ;
128
132
}
129
133
134
+ bool hkTree::isValid ()
135
+ {
136
+ return LevelSizes.size ()!=0 && !RootNode.Data .empty ();
137
+ }
138
+
130
139
char hkTreeNode::getChar (std::size_t offset) const
131
140
{
132
141
if (Data.size () < offset + sizeof (char )) {
0 commit comments