From 58dd5870a77344754ea459d8423d1b3787a6a813 Mon Sep 17 00:00:00 2001
From: Stephan Bergmann <sbergman@redhat.com>
Date: Mon, 27 Mar 2023 14:22:03 +0200
Subject: Avoid dangling references to temporary O[U]StringConcatMarker
 instances

...which were created in O[U]String::Concat and bound to O[U]StringConcat::left.
Thanks to Mike Kaganski for finding this.

Change-Id: Id7838bc55eec7cba8860c2ec21a247bf4abd3c62
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/149629
Tested-by: Jenkins
Reviewed-by: Stephan Bergmann <sbergman@redhat.com>
---
 include/rtl/string.hxx       |  4 ++--
 include/rtl/stringconcat.hxx | 20 +++++++++++++-------
 include/rtl/ustring.hxx      |  4 ++--
 3 files changed, 17 insertions(+), 11 deletions(-)

(limited to 'include/rtl')

diff --git a/include/rtl/string.hxx b/include/rtl/string.hxx
index 6af1a1a3b339..70829b43aae2 100644
--- a/include/rtl/string.hxx
+++ b/include/rtl/string.hxx
@@ -2229,14 +2229,14 @@ public:
     // would not compile):
     template<typename T> [[nodiscard]] static
     OStringConcat<OStringConcatMarker, T>
-    Concat(T const & value) { return OStringConcat<OStringConcatMarker, T>({}, value); }
+    Concat(T const & value) { return OStringConcat<OStringConcatMarker, T>(value); }
 
     // This overload is needed so that an argument of type 'char const[N]' ends up as
     // 'OStringConcat<rtl::OStringConcatMarker, char const[N]>' rather than as
     // 'OStringConcat<rtl::OStringConcatMarker, char[N]>':
     template<typename T, std::size_t N> [[nodiscard]] static
     OStringConcat<OStringConcatMarker, T[N]>
-    Concat(T (& value)[N]) { return OStringConcat<OStringConcatMarker, T[N]>({}, value); }
+    Concat(T (& value)[N]) { return OStringConcat<OStringConcatMarker, T[N]>(value); }
 #endif
 };
 
diff --git a/include/rtl/stringconcat.hxx b/include/rtl/stringconcat.hxx
index 4d4eccd60ba4..c94f8b919e14 100644
--- a/include/rtl/stringconcat.hxx
+++ b/include/rtl/stringconcat.hxx
@@ -459,16 +459,22 @@ template<typename C> struct ToStringHelper<std::basic_string_view<C>> {
 // An internal marker class used by O(U)String::Concat:
 template<typename C> struct StringConcatMarker {};
 
-template<typename C> struct ToStringHelper<StringConcatMarker<C>> {
-    static constexpr std::size_t length(StringConcatMarker<C>) { return 0; }
-
-    constexpr C * operator()(C * buffer, StringConcatMarker<C>) const SAL_RETURNS_NONNULL
-    { return buffer; }
-};
-
 using OStringConcatMarker = StringConcatMarker<char>;
 using OUStringConcatMarker = StringConcatMarker<sal_Unicode>;
 
+template<typename C> constexpr bool allowStringConcat<C, StringConcatMarker<C>> = true;
+
+template <typename C, typename T2, std::enable_if_t<allowStringConcat<C, T2>, int> Dummy>
+struct StringConcat<C, StringConcatMarker<C>, T2, Dummy>
+{
+public:
+    StringConcat( const T2& right_ ) : right( right_ ) {}
+    std::size_t length() const { return ToStringHelper< T2 >::length( right ); }
+    C* addData( C* buffer ) const SAL_RETURNS_NONNULL { return ToStringHelper< T2 >()( buffer, right ); }
+private:
+    const T2& right;
+};
+
 } // namespace
 
 #endif
diff --git a/include/rtl/ustring.hxx b/include/rtl/ustring.hxx
index 008f820bb3b1..c3966ac15cab 100644
--- a/include/rtl/ustring.hxx
+++ b/include/rtl/ustring.hxx
@@ -3313,14 +3313,14 @@ public:
     // would not compile):
     template<typename T> [[nodiscard]] static
     OUStringConcat<OUStringConcatMarker, T>
-    Concat(T const & value) { return OUStringConcat<OUStringConcatMarker, T>({}, value); }
+    Concat(T const & value) { return OUStringConcat<OUStringConcatMarker, T>(value); }
 
     // This overload is needed so that an argument of type 'char const[N]' ends up as
     // 'OUStringConcat<rtl::OUStringConcatMarker, char const[N]>' rather than as
     // 'OUStringConcat<rtl::OUStringConcatMarker, char[N]>':
     template<typename T, std::size_t N> [[nodiscard]] static
     OUStringConcat<OUStringConcatMarker, T[N]>
-    Concat(T (& value)[N]) { return OUStringConcat<OUStringConcatMarker, T[N]>({}, value); }
+    Concat(T (& value)[N]) { return OUStringConcat<OUStringConcatMarker, T[N]>(value); }
 #endif
 
 private:
-- 
cgit