diff --git a/be/src/exec/hdfs-scanner.cc b/be/src/exec/hdfs-scanner.cc index f934f790d..d62ccc7ed 100644 --- a/be/src/exec/hdfs-scanner.cc +++ b/be/src/exec/hdfs-scanner.cc @@ -220,11 +220,13 @@ int HdfsScanner::WriteTemplateTuples(TupleRow* row, int num_tuples) { if (EvalConjuncts(&template_tuple_row)) ++num_to_commit; } } + Tuple** row_tuple = reinterpret_cast(row); if (template_tuple_ != nullptr) { - Tuple** row_tuple = reinterpret_cast(row); for (int i = 0; i < num_to_commit; ++i) row_tuple[i] = template_tuple_; } else { DCHECK_EQ(scan_node_->tuple_desc()->byte_size(), 0); + // IMPALA-6258: Initialize tuple ptrs to non-null value + for (int i = 0; i < num_to_commit; ++i) row_tuple[i] = Tuple::POISON; } return num_to_commit; } diff --git a/be/src/exec/kudu-scanner.cc b/be/src/exec/kudu-scanner.cc index a9b56feaa..909567c8d 100644 --- a/be/src/exec/kudu-scanner.cc +++ b/be/src/exec/kudu-scanner.cc @@ -255,8 +255,13 @@ Status KuduScanner::HandleEmptyProjection(RowBatch* row_batch) { } } } + for (int i = 0; i < num_to_commit; ++i) { + // IMPALA-6258: Initialize tuple ptrs to non-null value + TupleRow* row = row_batch->GetRow(row_batch->AddRow()); + row->SetTuple(0, Tuple::POISON); + row_batch->CommitLastRow(); + } cur_kudu_batch_num_read_ += rows_to_add; - row_batch->CommitRows(num_to_commit); return Status::OK(); } diff --git a/be/src/runtime/tuple.cc b/be/src/runtime/tuple.cc index cab7686ff..787c3a4d4 100644 --- a/be/src/runtime/tuple.cc +++ b/be/src/runtime/tuple.cc @@ -46,6 +46,8 @@ const char* SlotOffsets::LLVM_CLASS_NAME = "struct.impala::SlotOffsets"; const char* Tuple::MATERIALIZE_EXPRS_SYMBOL = "MaterializeExprsILb0ELb0"; const char* Tuple::MATERIALIZE_EXPRS_NULL_POOL_SYMBOL = "MaterializeExprsILb0ELb1"; +Tuple* const Tuple::POISON = reinterpret_cast(42L); + int64_t Tuple::TotalByteSize(const TupleDescriptor& desc) const { int64_t result = desc.byte_size(); if (!desc.HasVarlenSlots()) return result; diff --git a/be/src/runtime/tuple.h b/be/src/runtime/tuple.h index 3286f1003..ae9be3205 100644 --- a/be/src/runtime/tuple.h +++ b/be/src/runtime/tuple.h @@ -84,6 +84,10 @@ class Tuple { return result; } + /// Pointer that marks an invalid Tuple address. Rather than leaving Tuple + /// pointers uninitialized, they should point to the value of POISON. + static Tuple* const POISON; + void Init(int size) { memset(this, 0, size); } void ClearNullBits(const TupleDescriptor& tuple_desc) { diff --git a/testdata/workloads/functional-query/queries/QueryTest/scanners.test b/testdata/workloads/functional-query/queries/QueryTest/scanners.test index 99ec5c5f0..bd5f49685 100644 --- a/testdata/workloads/functional-query/queries/QueryTest/scanners.test +++ b/testdata/workloads/functional-query/queries/QueryTest/scanners.test @@ -98,3 +98,15 @@ select count(*) from alltypes where rand() - year > month; ---- TYPES BIGINT ==== +---- QUERY +# IMPALA-6258: Uninitialized tuple pointers in row batch for empty rows +# The following query was non-deterministic because of this bug +select count(v.x) from alltypestiny t3 left outer join ( + select true as x from alltypestiny t1 left outer join + alltypestiny t2 on (true)) v +on (v.x = t3.bool_col) where t3.bool_col = true +---- RESULTS +256 +---- TYPES +BIGINT +====