Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions clickhouse/columns/string.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Comment on lines 137 to +141
Copy link

Copilot AI Apr 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const auto pos = &data_[size]; can be undefined behavior when size == capacity (e.g., appending an empty string when the block is full, or when capacity==0), because data_[size] conceptually dereferences one-past-the-end. Prefer computing the pointer via data_.get() + size (and consider applying the same change in the other Block helpers that use &data_[size]), so zero-length operations don’t rely on out-of-bounds operator[] evaluation.

Copilot uses AI. Check for mistakes.
Comment on lines +140 to +141
Copy link

Copilot AI Apr 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment suggests an empty std::string may have data() == nullptr, but standard std::string::data() is generally non-null even when empty. The nullptr case is definitely possible for an empty std::string_view (e.g., default-constructed std::string_view{} or a view built from a nullable C string), so it would be clearer/safer to describe the issue as “empty string_view can have null .data()” rather than tying it specifically to std::string().

Suggested change
// size argument, so an empty string_view backed by std::string()
// (where data() may be null) trips UBSan on every empty append.
// size argument, so an empty string_view with a null data() pointer
// trips UBSan on every empty append.

Copilot uses AI. Check for mistakes.
if (str.size() > 0) {
memcpy(pos, str.data(), str.size());
size += str.size();
}

return std::string_view(pos, str.size());
}
Expand Down