Skip to content

Commit bed4395

Browse files
banmoyclaude
andauthored
[BugFix] Fix ASAN crash for BOOLEAN nested in Avro complex-type columns (#76041)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent fb3daac commit bed4395

2 files changed

Lines changed: 64 additions & 1 deletion

File tree

be/src/formats/avro/nullable_column.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ static Status add_nullable_column(Column* column, const TypeDescriptor& type_des
235235

236236
switch (type_desc.type) {
237237
case TYPE_BOOLEAN:
238-
return add_nullable_numeric_column<int8_t>(column, type_desc, name, resolved);
238+
return add_nullable_numeric_column<uint8_t>(column, type_desc, name, resolved);
239239
case TYPE_BIGINT:
240240
return add_nullable_numeric_column<int64_t>(column, type_desc, name, resolved);
241241
case TYPE_INT:

be/test/exec/file_scanner/avro_scanner_test.cpp

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1542,6 +1542,69 @@ TEST_F(AvroScannerTest, test_struct_type) {
15421542
}
15431543
}
15441544

1545+
// Regression for issue #11522: a BOOLEAN element nested inside a native ARRAY target column.
1546+
// BooleanColumn is FixedLengthColumn<uint8_t>, but the nested (non-adaptive) add_nullable_column
1547+
// dispatched TYPE_BOOLEAN through add_nullable_numeric_column<int8_t>, so add_numeric_column's
1548+
// down_cast<FixedLengthColumn<int8_t>*> tripped the dynamic_cast assert (casts.h) under ASAN/DEBUG.
1549+
// STRUCT/MAP/ARRAY all funnel their leaf columns through this same add_nullable_column dispatch, so
1550+
// the ARRAY case exercises (and guards) the one-line fix for every container. ARRAY is used here
1551+
// because it is the path present on all release branches (the STRUCT crash path came from #74901).
1552+
TEST_F(AvroScannerTest, test_array_with_boolean) {
1553+
// record root { array<boolean> a }
1554+
std::string schema_json =
1555+
R"({"type":"record","name":"root","fields":[{"name":"a","type":{"type":"array","items":"boolean"}}]})";
1556+
1557+
AvroHelper avro_helper;
1558+
init_avro_value(schema_json.data(), schema_json.size(), avro_helper);
1559+
DeferOp avro_helper_deleter([&] {
1560+
avro_schema_decref(avro_helper.schema);
1561+
avro_value_iface_decref(avro_helper.iface);
1562+
avro_value_decref(&avro_helper.avro_val);
1563+
});
1564+
1565+
avro_value_t a_value;
1566+
ASSERT_EQ(0, avro_value_get_by_name(&avro_helper.avro_val, "a", &a_value, NULL));
1567+
avro_value_t e0;
1568+
avro_value_append(&a_value, &e0, NULL);
1569+
avro_value_set_boolean(&e0, true);
1570+
avro_value_t e1;
1571+
avro_value_append(&a_value, &e1, NULL);
1572+
avro_value_set_boolean(&e1, false);
1573+
avro_value_t e2;
1574+
avro_value_append(&a_value, &e2, NULL);
1575+
avro_value_set_boolean(&e2, true);
1576+
1577+
std::string data_path = "./be/test/exec/test_data/avro_scanner/tmp/avro_array_boolean_data.avro";
1578+
ASSERT_TRUE(write_avro_data(avro_helper, data_path).ok());
1579+
1580+
std::vector<TypeDescriptor> types;
1581+
TypeDescriptor t(TYPE_ARRAY);
1582+
t.children.emplace_back(TYPE_BOOLEAN);
1583+
types.emplace_back(t);
1584+
1585+
std::vector<TBrokerRangeDesc> ranges;
1586+
TBrokerRangeDesc range;
1587+
range.format_type = TFileFormatType::FORMAT_AVRO;
1588+
range.__isset.jsonpaths = false;
1589+
range.__set_path(data_path);
1590+
ranges.emplace_back(range);
1591+
1592+
auto scanner = create_avro_scanner(types, ranges, {"a"}, avro_helper.schema_text);
1593+
Status st = scanner->open();
1594+
ASSERT_TRUE(st.ok()) << st;
1595+
auto st2 = scanner->get_next();
1596+
ASSERT_TRUE(st2.ok()) << st2.status();
1597+
1598+
ChunkPtr chunk = st2.value();
1599+
EXPECT_EQ(1, chunk->num_columns());
1600+
EXPECT_EQ(1, chunk->num_rows());
1601+
auto array = chunk->get(0)[0].get_array();
1602+
ASSERT_EQ(3, array.size());
1603+
EXPECT_EQ(1, array[0].get_int8());
1604+
EXPECT_EQ(0, array[1].get_int8());
1605+
EXPECT_EQ(1, array[2].get_int8());
1606+
}
1607+
15451608
TEST_F(AvroScannerTest, test_array_of_nullable_string) {
15461609
// record root { array< union{ null, string } > a }
15471610
// Regression guard for the codex review (PR #74901): an ARRAY<VARCHAR> whose elements are avro

0 commit comments

Comments
 (0)