From 6da4acb41e8fdcee67aa3cf96c332e6b405cb861 Mon Sep 17 00:00:00 2001 From: Piotr Sarna Date: Mon, 7 Feb 2022 08:39:20 +0100 Subject: [PATCH] expression: fix get_value for mismatched column definitions As observed in #10026, after schema changes it somehow happened that a column defition that does not match any of the base table columns was passed to expression verification code. The function that looks up the index of a column happens to return -1 when it doesn't find anything, so using this returned index without checking if it's nonnegative results in accessing invalid vector data, and a segfault or silent memory corruption. Therefore, an explicit check is added to see if the column was actually found. This serves two purposes: - avoiding segfaults/memory corruption - making it easier to investigate the root cause of #10026 Closes #10039 (cherry picked from commit 7b364fec9849e9a342af1c240e3a7185bf5401ef) --- cql3/expr/expression.cc | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/cql3/expr/expression.cc b/cql3/expr/expression.cc index 57dfbbfbe3..98404a39d1 100644 --- a/cql3/expr/expression.cc +++ b/cql3/expr/expression.cc @@ -117,7 +117,13 @@ managed_bytes_opt get_value(const column_value& col, const column_value_eval_bag if (!col_type->is_map()) { throw exceptions::invalid_request_exception(format("subscripting non-map column {}", cdef->name_as_text())); } - const auto deserialized = cdef->type->deserialize(managed_bytes_view(*data.other_columns[data.sel.index_of(*cdef)])); + int32_t index = data.sel.index_of(*cdef); + if (index == -1) { + throw std::runtime_error( + format("Column definition {} does not match any column in the query selection", + cdef->name_as_text())); + } + const auto deserialized = cdef->type->deserialize(managed_bytes_view(*data.other_columns[index])); const auto& data_map = value_cast(deserialized); const auto key = evaluate_to_raw_view(col.sub, options); auto&& key_type = col_type->name_comparator(); @@ -135,8 +141,16 @@ managed_bytes_opt get_value(const column_value& col, const column_value_eval_bag case column_kind::clustering_key: return managed_bytes(data.clustering_key[cdef->id]); case column_kind::static_column: - case column_kind::regular_column: - return managed_bytes_opt(data.other_columns[data.sel.index_of(*cdef)]); + [[fallthrough]]; + case column_kind::regular_column: { + int32_t index = data.sel.index_of(*cdef); + if (index == -1) { + throw std::runtime_error( + format("Column definition {} does not match any column in the query selection", + cdef->name_as_text())); + } + return managed_bytes_opt(data.other_columns[index]); + } default: throw exceptions::unsupported_operation_exception("Unknown column kind"); }