basic/qa/basic_coverage/test_string_fixed_len.bas |   54 ++++++++++++++++++++++
 basic/source/comp/parser.cxx                      |   14 +++--
 basic/source/runtime/runtime.cxx                  |    5 ++
 3 files changed, 68 insertions(+), 5 deletions(-)

New commits:
commit 8e37f8ab3798fbaad92179ad745962c62bb0fd73
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Wed Oct 30 15:31:33 2024 +0500
Commit:     Xisco Fauli <xiscofa...@libreoffice.org>
CommitDate: Fri Nov 1 18:53:06 2024 +0100

    tdf#163680: fix fixed-length strings assignment
    
    Change-Id: I4aa8144df5dfb836ad0689c7855301b8b04da485
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/175878
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>
    Tested-by: Jenkins
    (cherry picked from commit de4ef353503c794f72e6e0bbca41fd5beb25aafe)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/175903
    Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org>

diff --git a/basic/qa/basic_coverage/test_string_fixed_len.bas 
b/basic/qa/basic_coverage/test_string_fixed_len.bas
new file mode 100644
index 000000000000..d0bc1f30ea6a
--- /dev/null
+++ b/basic/qa/basic_coverage/test_string_fixed_len.bas
@@ -0,0 +1,54 @@
+' This file is part of the LibreOffice project.
+'
+' This Source Code Form is subject to the terms of the Mozilla Public
+' License, v. 2.0. If a copy of the MPL was not distributed with this
+' file, You can obtain one at http://mozilla.org/MPL/2.0/.
+'
+
+Option VBASupport 0
+Option Explicit
+
+Function doUnitTest() As String
+    TestUtil.TestInit
+    verify_stringFixedLen
+    doUnitTest = TestUtil.GetResult()
+End Function
+
+Sub verify_stringFixedLen()
+    On Error GoTo errorHandler
+    ' tdf#163680 - fixed-length strings support
+
+    Dim s As String * 10
+    TestUtil.AssertEqual(Len(s), 10, "Len(s) - default")
+    ' The default value is 10 null characters
+    TestUtil.AssertEqual(s, String(10, 0), "s - default")
+    s = "abc"
+    TestUtil.AssertEqual(Len(s), 10, "Len(s) - abc")
+    TestUtil.AssertEqual("""" & s & """", """abc       """, """s"" - abc")
+    s = "defghijklmno"
+    TestUtil.AssertEqual(Len(s), 10, "Len(s) - defghijklmno")
+    TestUtil.AssertEqual("""" & s & """", """defghijklm""", """s"" - 
defghijklmno")
+    Let s = "xyz" ' Test also Let keyword - uses a different code path
+    TestUtil.AssertEqual(Len(s), 10, "Len(s) - xyz")
+    TestUtil.AssertEqual("""" & s & """", """xyz       """, """s"" - xyz")
+    Let s = "opqrstuvwxyz"
+    TestUtil.AssertEqual(Len(s), 10, "Len(s) - opqrstuvwxyz")
+    TestUtil.AssertEqual("""" & s & """", """opqrstuvwx""", """s"" - 
opqrstuvwxyz")
+
+    Dim s1 As String * 0 ' Unlike VBA, LibreOffice Basic allows this for 
unrestricted strings
+    TestUtil.AssertEqual(Len(s1), 0, "Len(s1) - default")
+    TestUtil.AssertEqual("""" & s1 & """", """""", """s1"" - default")
+    s1 = "klm"
+    TestUtil.AssertEqual(Len(s1), 3, "Len(s1) - klm")
+    TestUtil.AssertEqual("""" & s1 & """", """klm""", """s1"" - klm")
+    s = s1
+    TestUtil.AssertEqual(Len(s), 10, "Len(s) - klm")
+    TestUtil.AssertEqual("""" & s & """", """klm       """, """s"" - klm")
+    ' Also test s1 - it must not be affected
+    TestUtil.AssertEqual(Len(s1), 3, "Len(s1) - klm")
+    TestUtil.AssertEqual("""" & s1 & """", """klm""", """s1"" - klm")
+
+    Exit Sub
+errorHandler:
+    TestUtil.ReportErrorHandler("verify_stringFixedLen", Err, Error$, Erl)
+End Sub
diff --git a/basic/source/comp/parser.cxx b/basic/source/comp/parser.cxx
index d62fc921aa90..cc6ee0b7cc5c 100644
--- a/basic/source/comp/parser.cxx
+++ b/basic/source/comp/parser.cxx
@@ -551,6 +551,10 @@ void SbiParser::Symbol( const KeywordSymbolInfo* 
pKeywordSymbolInfo )
                     return;
                 }
             }
+            else if (auto nLen = pDef->GetLen()) // Dim s As String * 123 ' 
123 -> nLen
+            {
+                aGen.Gen(SbiOpcode::PAD_, nLen);
+            }
         }
         aGen.Gen( eOp );
     }
@@ -564,15 +568,15 @@ void SbiParser::Assign()
     SbiExpression aExpr( this );
     aLvalue.Gen();
     aExpr.Gen();
-    sal_uInt16 nLen = 0;
-    SbiSymDef* pDef = aLvalue.GetRealVar();
+    if (SbiSymDef* pDef = aLvalue.GetRealVar())
     {
         if( pDef->GetConstDef() )
             Error( ERRCODE_BASIC_DUPLICATE_DEF, pDef->GetName() );
-        nLen = aLvalue.GetRealVar()->GetLen();
+        if (auto nLen = pDef->GetLen()) // Dim s As String * 123 ' 123 -> nLen
+        {
+            aGen.Gen( SbiOpcode::PAD_, nLen );
+        }
     }
-    if( nLen )
-        aGen.Gen( SbiOpcode::PAD_, nLen );
     aGen.Gen( SbiOpcode::PUT_ );
 }
 
diff --git a/basic/source/runtime/runtime.cxx b/basic/source/runtime/runtime.cxx
index 994a01e4c74e..06ba4a50cc45 100644
--- a/basic/source/runtime/runtime.cxx
+++ b/basic/source/runtime/runtime.cxx
@@ -2977,6 +2977,11 @@ void SbiRuntime::StepPAD( sal_uInt32 nOp1 )
         comphelper::string::padToLength(aBuf, nLen, ' ');
     }
     s = aBuf.makeStringAndClear();
+    // Do not modify the original variable inadvertently
+    PopVar();
+    p = new SbxVariable;
+    p->PutString(s);
+    PushVar(p);
 }
 
 // jump (+target)

Reply via email to