Skip to content

Commit 12213f9

Browse files
committed
flann: fix out of buffer access
1 parent caa5e3b commit 12213f9

File tree

1 file changed

+20
-5
lines changed

1 file changed

+20
-5
lines changed

modules/flann/include/opencv2/flann/lsh_table.h

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ class LshTable
147147
LshTable()
148148
{
149149
key_size_ = 0;
150+
feature_size_ = 0;
150151
speed_level_ = kArray;
151152
}
152153

@@ -157,7 +158,7 @@ class LshTable
157158
*/
158159
LshTable(unsigned int feature_size, unsigned int key_size)
159160
{
160-
(void)feature_size;
161+
feature_size_ = feature_size;
161162
(void)key_size;
162163
std::cerr << "LSH is not implemented for that type" << std::endl;
163164
assert(0);
@@ -332,6 +333,8 @@ class LshTable
332333
*/
333334
unsigned int key_size_;
334335

336+
unsigned int feature_size_;
337+
335338
// Members only used for the unsigned char specialization
336339
/** The mask to apply to a feature to get the hash key
337340
* Only used in the unsigned char case
@@ -345,9 +348,10 @@ class LshTable
345348
template<>
346349
inline LshTable<unsigned char>::LshTable(unsigned int feature_size, unsigned int subsignature_size)
347350
{
351+
feature_size_ = feature_size;
348352
initialize(subsignature_size);
349353
// Allocate the mask
350-
mask_ = std::vector<size_t>((size_t)ceil((float)(feature_size * sizeof(char)) / (float)sizeof(size_t)), 0);
354+
mask_ = std::vector<size_t>((feature_size * sizeof(char) + sizeof(size_t) - 1) / sizeof(size_t), 0);
351355

352356
// A bit brutal but fast to code
353357
std::vector<size_t> indices(feature_size * CHAR_BIT);
@@ -392,6 +396,7 @@ inline size_t LshTable<unsigned char>::getKey(const unsigned char* feature) cons
392396
{
393397
// no need to check if T is dividable by sizeof(size_t) like in the Hamming
394398
// distance computation as we have a mask
399+
// FIXIT: This is bad assumption, because we reading tail bytes after of the allocated features buffer
395400
const size_t* feature_block_ptr = reinterpret_cast<const size_t*> ((const void*)feature);
396401

397402
// Figure out the subsignature of the feature
@@ -400,10 +405,20 @@ inline size_t LshTable<unsigned char>::getKey(const unsigned char* feature) cons
400405
size_t subsignature = 0;
401406
size_t bit_index = 1;
402407

403-
for (std::vector<size_t>::const_iterator pmask_block = mask_.begin(); pmask_block != mask_.end(); ++pmask_block) {
408+
for (unsigned i = 0; i < feature_size_; i += sizeof(size_t)) {
404409
// get the mask and signature blocks
405-
size_t feature_block = *feature_block_ptr;
406-
size_t mask_block = *pmask_block;
410+
size_t feature_block;
411+
if (i <= feature_size_ - sizeof(size_t))
412+
{
413+
feature_block = *feature_block_ptr;
414+
}
415+
else
416+
{
417+
size_t tmp = 0;
418+
memcpy(&tmp, feature_block_ptr, feature_size_ - i); // preserve bytes order
419+
feature_block = tmp;
420+
}
421+
size_t mask_block = mask_[i / sizeof(size_t)];
407422
while (mask_block) {
408423
// Get the lowest set bit in the mask block
409424
size_t lowest_bit = mask_block & (-(ptrdiff_t)mask_block);

0 commit comments

Comments
 (0)