desktop/source/deployment/dp_persmap.cxx |   43 +++++++++++++++----------------
 1 file changed, 21 insertions(+), 22 deletions(-)

New commits:
commit 5028a5f7564b8a2d8df626feb1a6a85ee8a65db3
Author:     Mike Kaganski <[email protected]>
AuthorDate: Mon Nov 10 18:11:23 2025 +0500
Commit:     Mike Kaganski <[email protected]>
CommitDate: Sun Nov 16 11:34:53 2025 +0100

    tdf#80959: fix percent character escaping in dp_misc::(en|de)codeString
    
    The intention that these functions, that use % as a special character,
    escape existing % with another %, was documented in comments at both
    functions. But it had never been implemented properly.
    
    In encodeString, the code did wrong calculations, and wrote first
    special character (either %, or 0x00-0x0F) verbatim; and only then
    processed following characters according to the algorithm. That meant
    that an input with percent-encoded space, like
    
    Foo%20Bar
    
    was checked until the percent; then first four characters "Foo%" were
    copied to the resulting buffer; and then the rest of characters were
    sequentially checked for % or 0x00-0x0F (and none of them were). The
    result was unchanged "Foo%20Bar", instead of expected "Foo%%20Bar".
    
    In decodeString, despite the idea that %% must convert to %, the code
    didn't expect anything except 0-9 and A-F after the first %. As the
    result, an input string of "Foo%%20Bar" would become "Foo\EEBar", and
    "Foo%20Bar" would become "FooBar".
    
    This was that way since introduction of this code in AOO in commit
    65415c716863d17196eae2a4a7f86f2e0ba5c1b6 (#i118662# remove usage of
    BerkeleyDB in desktop module, 2011-12-12), ported to LO in commit
    daeed90f4586eb9533041fb89bee163a5193596c (re-base on ALv2 code.
    Includes:, 2012-11-19).
    
    This change fixes and unifies the logic of both of the functions.
    
    Change-Id: Ice5d078b007dbffacea247daaf81bde9c6386963
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/194066
    Reviewed-by: Mike Kaganski <[email protected]>
    Tested-by: Jenkins

diff --git a/desktop/source/deployment/dp_persmap.cxx 
b/desktop/source/deployment/dp_persmap.cxx
index 9cc74b0c79a8..c2d7eb4a11b8 100644
--- a/desktop/source/deployment/dp_persmap.cxx
+++ b/desktop/source/deployment/dp_persmap.cxx
@@ -72,27 +72,25 @@ PersistentMap::~PersistentMap()
 // replace "%" with "%%"
 static OString encodeString( const OString& rStr)
 {
-    const char* pChar = rStr.getStr();
-    const sal_Int32 nLen = rStr.getLength();
-    sal_Int32 i = nLen;
+    const char *pChar = rStr.getStr(), *const pEnd = pChar + rStr.getLength();
     // short circuit for the simple non-encoded case
-    while( --i >= 0)
+    for (; pChar != pEnd; ++pChar)
     {
-        const unsigned char c = static_cast<unsigned char>(*(pChar++));
+        const unsigned char c = static_cast<unsigned char>(*pChar);
         if( c <= 0x0F )
             break;
         if( c == '%')
             break;
     }
-    if( i < 0)
+    if (pChar == pEnd)
         return rStr;
 
     // escape chars 0x00..0x0F with "%0".."%F"
-    OStringBuffer aEncStr( nLen + 32);
-    aEncStr.append( pChar - (nLen-i), nLen - i);
-    while( --i >= 0)
+    OStringBuffer aEncStr(rStr.getLength() + 32);
+    aEncStr.append(rStr.getStr(), pChar - rStr.getStr());
+    for (; pChar != pEnd; ++pChar)
     {
-        unsigned char c = static_cast<unsigned char>(*(pChar++));
+        unsigned char c = static_cast<unsigned char>(*pChar);
         if( c <= 0x0F )
         {
             aEncStr.append( '%');
@@ -109,30 +107,31 @@ static OString encodeString( const OString& rStr)
 // replace "%%" with "%"
 static OString decodeString( const char* pEncChars, int nLen)
 {
-    const char* pChar = pEncChars;
-    sal_Int32 i = nLen;
+    const char *pChar = pEncChars, *const pEnd = pChar + nLen;
     // short circuit for the simple non-encoded case
-    while( --i >= 0)
-        if( *(pChar++) == '%')
+    for (; pChar != pEnd; ++pChar)
+        if (*pChar == '%')
             break;
-    if( i < 0)
+    if (pChar == pEnd)
         return OString( pEncChars, nLen);
 
     // replace escaped chars with their decoded counterparts
     OStringBuffer aDecStr( nLen);
-    pChar = pEncChars;
-    for( i = nLen; --i >= 0;)
+    aDecStr.append(pEncChars, pChar - pEncChars);
+    for (; pChar != pEnd; ++pChar)
     {
-        char c = *(pChar++);
+        char c = *pChar;
         // handle escaped character
         if( c == '%')
         {
-            --i;
-            OSL_ASSERT( i >= 0);
-            c = *(pChar++);
+            ++pChar;
+            OSL_ASSERT(pChar != pEnd);
+            if (pChar == pEnd)
+                break;
+            c = *pChar;
             if( ('0' <= c) && (c <= '9'))
                 c -= '0';
-            else
+            else if (c != '%')
             {
                 OSL_ASSERT( ('A' <= c) && (c <= 'F'));
                 c -= ('A'-10);

Reply via email to