From d0fe2b8bd0f4f622919033d8f1f78bd02ccd0fd5 Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Sat, 25 Apr 2026 17:06:36 -0400 Subject: [PATCH] Fix UB in ColumnStringBlock::AppendUnsafe with empty string_view memcpy's source pointer is declared nonnull regardless of the size argument. When AppendUnsafe is called with an empty string_view that was constructed from an empty std::string, str.data() can be null (the standard allows it), so UBSan flags every empty-string append: runtime error: null pointer passed as argument 2, which is declared to never be null SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior clickhouse/columns/string.cpp:139:21 Guard the memcpy with a zero-size short-circuit. Behavior is unchanged for non-empty inputs and the returned string_view still points at pos with length 0 for empty inputs. --- clickhouse/columns/string.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/clickhouse/columns/string.cpp b/clickhouse/columns/string.cpp index dff45bac..cb1b5932 100644 --- a/clickhouse/columns/string.cpp +++ b/clickhouse/columns/string.cpp @@ -136,8 +136,13 @@ struct ColumnString::Block std::string_view AppendUnsafe(std::string_view str) { const auto pos = &data_[size]; - memcpy(pos, str.data(), str.size()); - size += str.size(); + // memcpy's source pointer is declared nonnull regardless of the + // size argument, so an empty string_view backed by std::string() + // (where data() may be null) trips UBSan on every empty append. + if (str.size() > 0) { + memcpy(pos, str.data(), str.size()); + size += str.size(); + } return std::string_view(pos, str.size()); }