Skip to content

Commit 408ef04

Browse files
committed
Fix overreading guard comparison
1 parent dd3ec0d commit 408ef04

1 file changed

Lines changed: 11 additions & 3 deletions

File tree

cpp/src/arrow/util/bpacking_dispatch_internal.h

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -188,18 +188,26 @@ void unpack_width(const uint8_t* in, UnpackedUInt* out, int batch_size, int bit_
188188
return unpack_full(in, out, batch_size);
189189
} else {
190190
using UnpackerForWidth = Unpacker<UnpackedUInt, kPackedBitWidth>;
191+
// Number of values extracted by one iteration of the kernel
191192
constexpr auto kValuesUnpacked = UnpackerForWidth::kValuesUnpacked;
193+
// Number of bytes read, but not necessarily unpacked, by one iteration of the
194+
// kernel. This constant prevent reading past buffer end.
192195
constexpr auto kBytesRead = UnpackerForWidth::kBytesRead;
193196

194197
if constexpr (kValuesUnpacked > 0) {
195-
const uint8_t* last_in =
196-
in + bit_util::CeilDiv(batch_size * kPackedBitWidth, 8) - kBytesRead;
198+
const uint8_t* in_end = in + bit_util::CeilDiv(batch_size * kPackedBitWidth, 8);
199+
const uint8_t* in_last = in_end - kBytesRead;
197200
// Running the optimized kernel for batch extraction
198-
while ((batch_size > kValuesUnpacked) && (in <= last_in)) {
201+
while ((batch_size >= kValuesUnpacked) && (in <= in_last)) {
199202
in = UnpackerForWidth::unpack(in, out);
200203
out += kValuesUnpacked;
201204
batch_size -= kValuesUnpacked;
202205
}
206+
207+
// Performance check aking sure we ran the kernel loop as much as possible:
208+
// Either we ran out because we could not pack enough values, or because we would
209+
// overread.
210+
ARROW_DCHECK((batch_size < kValuesUnpacked) || (in_end - in) < kBytesRead);
203211
}
204212

205213
// Running the epilog for the remaining values that don't fit in a kernel

0 commit comments

Comments
 (0)