From 0a9155777333ff89fdc39a5ffdd30653e38874f2 Mon Sep 17 00:00:00 2001 From: Dan Dees Date: Fri, 6 Mar 2026 20:23:32 +0700 Subject: [PATCH] Fixed: UBSAN reports from empty memory copies Skip zero-length memcpy/memmove calls in AbstractString construction and Array copy, insert, and capacity growth operations. Assert that nonempty Array storage is valid before copying during capacity growth. --- src/common/classes/array.h | 24 +++++++++++++++++------- src/common/classes/fb_string.cpp | 3 ++- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/src/common/classes/array.h b/src/common/classes/array.h index 897474fbb27..51af8bb29cb 100644 --- a/src/common/classes/array.h +++ b/src/common/classes/array.h @@ -193,7 +193,8 @@ class Array : public Storage void copyFrom(const Array& source) { ensureCapacity(source.count, false); - memcpy(static_cast(data), source.data, sizeof(T) * source.count); + if (source.count) + memcpy(static_cast(data), source.data, sizeof(T) * source.count); count = source.count; } @@ -260,8 +261,10 @@ class Array : public Storage fb_assert(index <= count); fb_assert(count < FB_MAX_SIZEOF); ensureCapacity(count + 1); - memmove(static_cast(data + index + 1), data + index, sizeof(T) * (count++ - index)); + if (count - index) + memmove(static_cast(data + index + 1), data + index, sizeof(T) * (count - index)); data[index] = item; + ++count; } void insert(const size_type index, const Array& items) @@ -269,8 +272,10 @@ class Array : public Storage fb_assert(index <= count); fb_assert(count <= FB_MAX_SIZEOF - items.count); ensureCapacity(count + items.count); - memmove(static_cast(data + index + items.count), data + index, sizeof(T) * (count - index)); - memcpy(static_cast(data + index), items.data, items.count); + if (count - index) + memmove(static_cast(data + index + items.count), data + index, sizeof(T) * (count - index)); + if (items.count) + memcpy(static_cast(data + index), items.data, items.count); count += items.count; } @@ -279,8 +284,10 @@ class Array : public Storage fb_assert(index <= count); fb_assert(count <= FB_MAX_SIZEOF - itemsCount); ensureCapacity(count + itemsCount); - memmove(static_cast(data + index + itemsCount), data + index, sizeof(T) * (count - index)); - memcpy(static_cast(data + index), items, sizeof(T) * itemsCount); + if (count - index) + memmove(static_cast(data + index + itemsCount), data + index, sizeof(T) * (count - index)); + if (itemsCount) + memcpy(static_cast(data + index), items, sizeof(T) * itemsCount); count += itemsCount; } @@ -574,8 +581,11 @@ class Array : public Storage T* newdata = static_cast (this->getPool().allocate(sizeof(T) * newcapacity)); - if (preserve) + if (preserve && count != 0) + { + fb_assert(data != nullptr); memcpy(static_cast(newdata), data, sizeof(T) * count); + } freeData(); data = newdata; capacity = newcapacity; diff --git a/src/common/classes/fb_string.cpp b/src/common/classes/fb_string.cpp index 616996553d7..b4f26ac8689 100644 --- a/src/common/classes/fb_string.cpp +++ b/src/common/classes/fb_string.cpp @@ -100,7 +100,8 @@ namespace Firebird : max_length(static_cast(limit)) { initialize(sizeL); - memcpy(stringBuffer, dataL, sizeL); + if (sizeL) + memcpy(stringBuffer, dataL, sizeL); } AbstractString::AbstractString(const size_type limit, const_pointer p1, const size_type n1,