Skip to content

Commit a001ebe

Browse files
authored
Merge pull request #511 from SavicStefan/tuple_fix
Bounds-check per-entry key read in compact_tuple_sketch::deserialize
2 parents c228885 + 944aed1 commit a001ebe

2 files changed

Lines changed: 16 additions & 0 deletions

File tree

tuple/include/tuple_sketch_impl.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -583,6 +583,7 @@ compact_tuple_sketch<S, A> compact_tuple_sketch<S, A>::deserialize(const void* b
583583
std::unique_ptr<S, deleter_of_summaries> summary(alloc.allocate(1), deleter_of_summaries(1, false, allocator));
584584
for (size_t i = 0; i < num_entries; ++i) {
585585
uint64_t key;
586+
ensure_minimum_memory(base + size - ptr, sizeof(uint64_t));
586587
ptr += copy_from_mem(ptr, key);
587588
ptr += sd.deserialize(ptr, base + size - ptr, summary.get(), 1);
588589
entries.emplace_back(key, std::move(*summary));

tuple/test/tuple_sketch_test.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,4 +371,19 @@ TEST_CASE("filter", "[tuple_sketch]") {
371371
}
372372
}
373373

374+
TEST_CASE("tuple sketch: deserialize bounds-checks each entry key", "[tuple_sketch]") {
375+
// A compact sketch serialized with a narrower summary (float, 4 bytes) and then
376+
// deserialized as a wider summary (double, 8 bytes). The per-entry stride the reader
377+
// assumes (8-byte key + 8-byte summary) is larger than the entries actually occupy
378+
// (8-byte key + 4-byte summary), so the read cursor advances past the end of the buffer.
379+
// num_entries is read from the preamble and is unaffected, so the entry loop still runs
380+
// the full count and the per-entry key read walks off the end. This must throw rather
381+
// than read out of bounds (a heap-buffer-overflow under AddressSanitizer).
382+
auto update_sketch = update_tuple_sketch<float>::builder().build();
383+
for (int i = 0; i < 100; ++i) update_sketch.update(i, 1.0f);
384+
auto bytes = update_sketch.compact().serialize();
385+
REQUIRE_THROWS_AS(compact_tuple_sketch<double>::deserialize(bytes.data(), bytes.size()),
386+
std::out_of_range);
387+
}
388+
374389
} /* namespace datasketches */

0 commit comments

Comments
 (0)