This is an automated email from the ASF dual-hosted git repository. yiguolei pushed a commit to branch branch-2.1 in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/branch-2.1 by this push: new f771a422a94 branch-2.1: [fix](column) fix ColumnWithTypeAndName::get_nested use-after-free when input Const(Nullable) column #48288 (#49258) f771a422a94 is described below commit f771a422a94f0fc2f8dd14f65f1e520fff5a7911 Author: Mryange <yanxuech...@selectdb.com> AuthorDate: Thu Mar 20 09:53:20 2025 +0800 branch-2.1: [fix](column) fix ColumnWithTypeAndName::get_nested use-after-free when input Const(Nullable) column #48288 (#49258) --- be/src/vec/core/column_with_type_and_name.cpp | 5 +- be/test/testutil/column_helper.cpp | 39 +++++++ be/test/testutil/column_helper.h | 116 +++++++++++++++++++++ .../vec/core/column_with_type_and_name_test.cpp | 40 +++++++ 4 files changed, 198 insertions(+), 2 deletions(-) diff --git a/be/src/vec/core/column_with_type_and_name.cpp b/be/src/vec/core/column_with_type_and_name.cpp index cd0f7194004..efd887b194b 100644 --- a/be/src/vec/core/column_with_type_and_name.cpp +++ b/be/src/vec/core/column_with_type_and_name.cpp @@ -93,8 +93,9 @@ ColumnWithTypeAndName ColumnWithTypeAndName::get_nested(bool replace_null_data_t auto nested_type = assert_cast<const DataTypeNullable*>(type.get())->get_nested_type(); ColumnPtr nested_column = column; if (column) { - nested_column = nested_column->convert_to_full_column_if_const(); - const auto* source_column = assert_cast<const ColumnNullable*>(nested_column.get()); + // A column_ptr is needed here to ensure that the column in convert_to_full_column_if_const is not released. + auto column_ptr = nested_column->convert_to_full_column_if_const(); + const auto* source_column = assert_cast<const ColumnNullable*>(column_ptr.get()); nested_column = source_column->get_nested_column_ptr(); if (replace_null_data_to_default) { diff --git a/be/test/testutil/column_helper.cpp b/be/test/testutil/column_helper.cpp new file mode 100644 index 00000000000..b00a681ec72 --- /dev/null +++ b/be/test/testutil/column_helper.cpp @@ -0,0 +1,39 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +#include "column_helper.h" + +#include <gtest/gtest.h> + +#include "vec/data_types/data_type_number.h" + +namespace doris::vectorized { + +TEST(ColumnHelperTest, test) { + EXPECT_TRUE(ColumnHelper::column_equal( + ColumnHelper::create_column<DataTypeInt32>({1, 2, 3, 4, 5}), + ColumnHelper::create_column<DataTypeInt32>({1, 2, 3, 4, 5}))); + + EXPECT_FALSE(ColumnHelper::column_equal( + ColumnHelper::create_column<DataTypeInt32>({1, 2, 3, 4, 5}), + ColumnHelper::create_column<DataTypeInt32>({1, 2, 3, 4, 5, 6}))); + + EXPECT_FALSE(ColumnHelper::column_equal( + ColumnHelper::create_column<DataTypeInt32>({1, 1, 3, 4, 5}), + ColumnHelper::create_column<DataTypeInt32>({1, 2, 3, 4, 5}))); +} + +} // namespace doris::vectorized diff --git a/be/test/testutil/column_helper.h b/be/test/testutil/column_helper.h new file mode 100644 index 00000000000..a9cf58bb880 --- /dev/null +++ b/be/test/testutil/column_helper.h @@ -0,0 +1,116 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +#pragma once + +#include <memory> +#include <type_traits> +#include <vector> + +#include "vec/columns/column_nullable.h" +#include "vec/core/block.h" +#include "vec/data_types/data_type_string.h" + +namespace doris::vectorized { +struct ColumnHelper { +public: + template <typename DataType> + static ColumnPtr create_column(const std::vector<typename DataType::FieldType>& data) { + auto column = DataType::ColumnType::create(); + if constexpr (std::is_same_v<DataTypeString, DataType>) { + for (const auto& datum : data) { + column->insert_data(datum.data(), datum.size()); + } + } else { + for (const auto& datum : data) { + column->insert_value(datum); + } + } + return std::move(column); + } + + template <typename DataType> + static ColumnPtr create_nullable_column( + const std::vector<typename DataType::FieldType>& data, + const std::vector<typename NullMap::value_type>& null_map) { + auto null_col = ColumnUInt8::create(); + for (const auto& datum : null_map) { + null_col->insert_value(datum); + } + auto ptr = create_column<DataType>(data); + return ColumnNullable::create(std::move(ptr), std::move(null_col)); + } + + static bool column_equal(const ColumnPtr& column1, const ColumnPtr& column2) { + if (column1->size() != column2->size()) { + return false; + } + for (size_t i = 0; i < column1->size(); i++) { + if (column1->compare_at(i, i, *column2, 1) != 0) { + return false; + } + } + return true; + } + + static bool block_equal(const Block& block1, const Block& block2) { + if (block1.columns() != block2.columns()) { + return false; + } + for (size_t i = 0; i < block1.columns(); i++) { + if (!column_equal(block1.get_by_position(i).column, block2.get_by_position(i).column)) { + return false; + } + } + return true; + } + + template <typename DataType> + static Block create_block(const std::vector<typename DataType::FieldType>& data) { + auto column = create_column<DataType>(data); + auto data_type = std::make_shared<DataType>(); + Block block({ColumnWithTypeAndName(column, data_type, "column")}); + return block; + } + + template <typename DataType> + static Block create_nullable_block(const std::vector<typename DataType::FieldType>& data, + const std::vector<typename NullMap::value_type>& null_map) { + auto column = create_nullable_column<DataType>(data, null_map); + auto data_type = std::make_shared<DataTypeNullable>(std::make_shared<DataType>()); + Block block({ColumnWithTypeAndName(column, data_type, "column")}); + return block; + } + + template <typename DataType> + static ColumnWithTypeAndName create_column_with_name( + const std::vector<typename DataType::FieldType>& datas) { + auto column = create_column<DataType>(datas); + auto data_type = std::make_shared<DataType>(); + return ColumnWithTypeAndName(column, data_type, "column"); + } + + template <typename DataType> + static ColumnWithTypeAndName create_nullable_column_with_name( + const std::vector<typename DataType::FieldType>& datas, + const std::vector<typename NullMap::value_type>& null_map) { + auto column = create_nullable_column<DataType>(datas, null_map); + auto data_type = std::make_shared<DataTypeNullable>(std::make_shared<DataType>()); + return ColumnWithTypeAndName(column, data_type, "column"); + } +}; +} // namespace doris::vectorized diff --git a/be/test/vec/core/column_with_type_and_name_test.cpp b/be/test/vec/core/column_with_type_and_name_test.cpp new file mode 100644 index 00000000000..1cdda959a82 --- /dev/null +++ b/be/test/vec/core/column_with_type_and_name_test.cpp @@ -0,0 +1,40 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +#include "vec/core/column_with_type_and_name.h" + +#include <gtest/gtest.h> + +#include "testutil/column_helper.h" +#include "vec/core/types.h" +#include "vec/data_types/data_type_nullable.h" +#include "vec/data_types/data_type_number.h" + +namespace doris::vectorized { + +TEST(ColumnWithTypeAndNameTest, get_nested_test) { + ColumnWithTypeAndName column_with_type_and_name; + auto null_column = ColumnNullable::create(ColumnHelper::create_column<DataTypeInt32>({1}), + ColumnHelper::create_column<DataTypeUInt8>({true})); + column_with_type_and_name.column = ColumnConst::create(null_column, 3); + column_with_type_and_name.type = + std::make_shared<DataTypeNullable>(std::make_shared<DataTypeInt32>()); + column_with_type_and_name.name = "column_with_type_and_name"; + column_with_type_and_name.get_nested(true); +} + +} // namespace doris::vectorized --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org For additional commands, e-mail: commits-h...@doris.apache.org