From fc800ec1791d5b0b614577b345fbea65933a229b Mon Sep 17 00:00:00 2001 From: AnamayNarkar Date: Mon, 2 Mar 2026 05:15:23 +0530 Subject: [PATCH] tdf#106137 sc: process Unicode escapes in regex replacement strings This uses i18nutil::processUnicodeEscapes(), introduced in the parent commit. Change-Id: Ieb780d494ea3cdb8a976bb4ca33d95baa7127c8e Reviewed-on: https://gerrit.libreoffice.org/c/core/+/200739 Tested-by: Jenkins Reviewed-by: Mike Kaganski --- sc/qa/unit/ucalc.cxx | 51 ++++++++++++++++++++++++++++++++++ sc/source/core/data/table6.cxx | 2 ++ 2 files changed, 53 insertions(+) diff --git a/sc/qa/unit/ucalc.cxx b/sc/qa/unit/ucalc.cxx index 34b6f4e2bda0..79c579016ac6 100644 --- a/sc/qa/unit/ucalc.cxx +++ b/sc/qa/unit/ucalc.cxx @@ -4460,6 +4460,57 @@ CPPUNIT_TEST_FIXTURE(Test, testSearchCells) m_pDoc->DeleteTab(0); } +CPPUNIT_TEST_FIXTURE(Test, testTdf106137_UnicodeEscapeInReplacement) +{ + m_pDoc->InsertTab(0, u"Test"_ustr); + + // test basic unicode escape expansion + // unicode values in replacement strings should expand to Unicode character when regular expressions is selected + m_pDoc->SetString(ScAddress(0, 0, 0), u"hello world"_ustr); + + SvxSearchItem aItem(SID_SEARCH_ITEM); + aItem.SetSearchString(u"world"_ustr); + aItem.SetReplaceString(u"\\u0041\\u0042\\u0043"_ustr); + aItem.SetCommand(SvxSearchCmd::REPLACE_ALL); + aItem.SetRegExp(true); + + ScMarkData aMarkData(m_pDoc->GetSheetLimits()); + aMarkData.SelectOneTable(0); + SCCOL nCol = 0; + SCROW nRow = 0; + SCTAB nTab = 0; + ScRangeList aMatchedRanges; + OUString aUndoStr; + bool bClamped = false; + + m_pDoc->SearchAndReplace(aItem, nCol, nRow, nTab, aMarkData, aMatchedRanges, aUndoStr, nullptr, + bClamped); + CPPUNIT_ASSERT_EQUAL(u"hello ABC"_ustr, m_pDoc->GetString(ScAddress(0, 0, 0))); + + // test Backreference edge case + // \uXXXX in replacement template should expand before back-references are substituted, + // so that the 'searched' content containing literal \u sequences is not accidentally expanded + + // Insert text that contains an actual escaped unicode string + m_pDoc->SetString(ScAddress(0, 1, 0), u"find \\u0042"_ustr); // A2 + + // Capture the literal "\u0042" in a regex group + aItem.SetSearchString(u"(find .*)"_ustr); + // Replace with \u0041 (which should become 'A') + the backreference + aItem.SetReplaceString(u"\\u0041 $1"_ustr); + + nCol = 0; + nRow = 0; + nTab = 0; + m_pDoc->SearchAndReplace(aItem, nCol, nRow, nTab, aMarkData, aMatchedRanges, aUndoStr, nullptr, + bClamped); + + // shouldn't be 'A find B' + CPPUNIT_ASSERT_EQUAL(u"A find \\u0042"_ustr, m_pDoc->GetString(ScAddress(0, 1, 0))); + + m_pDoc->DeleteTab(0); +} + CPPUNIT_TEST_FIXTURE(Test, testFormulaPosition) { m_pDoc->InsertTab(0, u"Test"_ustr); diff --git a/sc/source/core/data/table6.cxx b/sc/source/core/data/table6.cxx index 970ae62e6467..89803bb125cb 100644 --- a/sc/source/core/data/table6.cxx +++ b/sc/source/core/data/table6.cxx @@ -32,6 +32,7 @@ #include #include #include +#include namespace { @@ -185,6 +186,7 @@ bool ScTable::SearchCell(const SvxSearchItem& rSearchItem, SCCOL nCol, sc::Colum OUString sReplStr = rSearchItem.GetReplaceString(); if (rSearchItem.GetRegExp()) { + sReplStr = i18nutil::processUnicodeEscapes(sReplStr); utl::TextSearch::ReplaceBackReferences( sReplStr, aString, aSearchResult ); OUStringBuffer aStrBuffer(aString); aStrBuffer.remove(nStart, nEnd-nStart+1);