[Libreoffice-commits] core.git: basic/source sc/qa

Andreas Heinisch (via logerrit) logerrit at kemper.freedesktop.org
Tue Mar 24 08:31:13 UTC 2020


 basic/source/comp/exprgen.cxx                   |    8 --
 basic/source/comp/symtbl.cxx                    |   11 ++-
 basic/source/runtime/runtime.cxx                |   35 +++++-----
 sc/qa/extras/macros-test.cxx                    |   83 ++++++++++++++++++++++++
 sc/qa/extras/testdocuments/tdf131296_legacy.ods |binary
 sc/qa/extras/testdocuments/tdf131296_new.ods    |binary
 6 files changed, 113 insertions(+), 24 deletions(-)

New commits:
commit 16b0bbb671a8080655e27542e576478486810404
Author:     Andreas Heinisch <andreas.heinisch at yahoo.de>
AuthorDate: Sat Mar 21 14:59:27 2020 +0100
Commit:     Mike Kaganski <mike.kaganski at collabora.com>
CommitDate: Tue Mar 24 09:30:38 2020 +0100

    tdf#131296: get numeric value with its data type in StepLOADNC
    
    In order to load numeric values, generate SbiOpcode::NUMBER_ opcodes
    including the numeric value and its data type instead of SbiOpcode::CONST_.
    
    The numeric value and its data type will be restored in
    SbiRuntime::StepLOADNC. When the new compiled code is stored in documents,
    e.g. password-protected libraries, leagcy LO versions will just read up to
    non-numeric characters, thus correctly obtaining number value and ignoring
    the type, so the change is backward-compatible.
    
    To interpret legacy compiled code, old treatment of SbiRuntime::StepLOADI
    is restored, reverting commit 0b4f8bf571baf2ccd5a8aafdc4deb41867420be3.
    This change reimplements the fix for tdf#129596.
    
    Change-Id: I46ebfc77f9bea69479968950c0fb7264e4a7ab27
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/90858
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kaganski at collabora.com>

diff --git a/basic/source/comp/exprgen.cxx b/basic/source/comp/exprgen.cxx
index 3981bef2fb5e..6c60c02b0d7e 100644
--- a/basic/source/comp/exprgen.cxx
+++ b/basic/source/comp/exprgen.cxx
@@ -72,16 +72,14 @@ void SbiExprNode::Gen( SbiCodeGen& rGen, RecursiveMode eRecMode )
         case SbxEMPTY:
             rGen.Gen( SbiOpcode::EMPTY_ );
             break;
-        case SbxLONG:
-        case SbxINTEGER:
-            nStringId = rGen.GetParser()->aGblStrings.Add(nVal, eType);
-            rGen.Gen( SbiOpcode::CONST_, nStringId );
-            break;
         case SbxSTRING:
             nStringId = rGen.GetParser()->aGblStrings.Add( aStrVal );
             rGen.Gen( SbiOpcode::SCONST_, nStringId );
             break;
         default:
+            // tdf#131296 - generate SbiOpcode::NUMBER_ instead of SbiOpcode::CONST_
+            // for SbxINTEGER and SbxLONG including their numeric value and its data type,
+            // which will be restored in SbiRuntime::StepLOADNC.
             nStringId = rGen.GetParser()->aGblStrings.Add( nVal, eType );
             rGen.Gen( SbiOpcode::NUMBER_, nStringId );
             break;
diff --git a/basic/source/comp/symtbl.cxx b/basic/source/comp/symtbl.cxx
index b05575adfdfb..ac6f1ecd29da 100644
--- a/basic/source/comp/symtbl.cxx
+++ b/basic/source/comp/symtbl.cxx
@@ -66,10 +66,13 @@ short SbiStringPool::Add( double n, SbxDataType t )
     char buf[ 40 ];
     switch( t )
     {
-        case SbxINTEGER: snprintf( buf, sizeof(buf), "%d", static_cast<short>(n) ); break;
-        case SbxLONG:    snprintf( buf, sizeof(buf), "%ld", static_cast<long>(n) ); break;
-        case SbxSINGLE:  snprintf( buf, sizeof(buf), "%.6g", static_cast<float>(n) ); break;
-        case SbxDOUBLE:  snprintf( buf, sizeof(buf), "%.16g", n ); break;
+        // tdf#131296 - store numeric value including its type character
+        // See GetSuffixType in basic/source/comp/scanner.cxx for type characters
+        case SbxINTEGER: snprintf( buf, sizeof(buf), "%d%%", static_cast<short>(n) ); break;
+        case SbxLONG:    snprintf( buf, sizeof(buf), "%ld&", static_cast<long>(n) ); break;
+        case SbxSINGLE:  snprintf( buf, sizeof(buf), "%.6g!", static_cast<float>(n) ); break;
+        case SbxDOUBLE:  snprintf( buf, sizeof(buf), "%.16g", n ); break; // default processing in SbiRuntime::StepLOADNC - no type character
+        case SbxCURRENCY: snprintf(buf, sizeof(buf), "%.16g@", n); break;
         default: break;
     }
     return Add( OUString::createFromAscii( buf ) );
diff --git a/basic/source/runtime/runtime.cxx b/basic/source/runtime/runtime.cxx
index ffd03f28b7cf..15b45ec736a0 100644
--- a/basic/source/runtime/runtime.cxx
+++ b/basic/source/runtime/runtime.cxx
@@ -2773,8 +2773,6 @@ void SbiRuntime::StepERROR()
 
 void SbiRuntime::StepLOADNC( sal_uInt32 nOp1 )
 {
-    SbxVariable* p = new SbxVariable( SbxDOUBLE );
-
     // #57844 use localized function
     OUString aStr = pImg->GetString( static_cast<short>( nOp1 ) );
     // also allow , !!!
@@ -2783,8 +2781,24 @@ void SbiRuntime::StepLOADNC( sal_uInt32 nOp1 )
     {
         aStr = aStr.replaceAt(iComma, 1, ".");
     }
-    double n = ::rtl::math::stringToDouble( aStr, '.', ',' );
+    sal_Int32 nParseEnd = 0;
+    rtl_math_ConversionStatus eStatus = rtl_math_ConversionStatus_Ok;
+    double n = ::rtl::math::stringToDouble( aStr, '.', ',', &eStatus, &nParseEnd );
 
+    // tdf#131296 - retrieve data type put in SbiExprNode::Gen
+    SbxDataType eType = SbxDOUBLE;
+    if ( nParseEnd < aStr.getLength() )
+    {
+        switch ( aStr[nParseEnd] )
+        {
+            // See GetSuffixType in basic/source/comp/scanner.cxx for type characters
+            case '%': eType = SbxINTEGER; break;
+            case '&': eType = SbxLONG; break;
+            case '!': eType = SbxSINGLE; break;
+            case '@': eType = SbxCURRENCY; break;
+        }
+    }
+    SbxVariable* p = new SbxVariable( eType );
     p->PutDouble( n );
     PushVar( p );
 }
@@ -2799,22 +2813,13 @@ void SbiRuntime::StepLOADSC( sal_uInt32 nOp1 )
 }
 
 // Immediate Load (+value)
+// The opcode is not generated in SbiExprNode::Gen anymore; used for legacy images
 
 void SbiRuntime::StepLOADI( sal_uInt32 nOp1 )
 {
     SbxVariable* p = new SbxVariable;
-
-    OUString aStr = pImg->GetString(static_cast<short>(nOp1));
-    double n = ::rtl::math::stringToDouble(aStr, '.', ',');
-    if (n >= SbxMININT && n <= SbxMAXINT)
-    {
-        p->PutInteger(static_cast<sal_Int16>(n));
-    }
-    else
-    {
-        p->PutLong(static_cast<sal_Int32>(n));
-    }
-    PushVar(p);
+    p->PutInteger( static_cast<sal_Int16>( nOp1 ) );
+    PushVar( p );
 }
 
 // store a named argument in Argv (+Arg-no. from 1!)
diff --git a/sc/qa/extras/macros-test.cxx b/sc/qa/extras/macros-test.cxx
index f887a95f7223..3801a9998895 100644
--- a/sc/qa/extras/macros-test.cxx
+++ b/sc/qa/extras/macros-test.cxx
@@ -37,6 +37,8 @@ public:
     void testPasswordProtectedStarBasic();
     void testRowColumn();
     void testPasswordProtectedUnicodeString();
+    void testTdf131296_legacy();
+    void testTdf131296_new();
 
     CPPUNIT_TEST_SUITE(ScMacrosTest);
     CPPUNIT_TEST(testStarBasic);
@@ -45,6 +47,8 @@ public:
     CPPUNIT_TEST(testPasswordProtectedStarBasic);
     CPPUNIT_TEST(testRowColumn);
     CPPUNIT_TEST(testPasswordProtectedUnicodeString);
+    CPPUNIT_TEST(testTdf131296_legacy);
+    CPPUNIT_TEST(testTdf131296_new);
 
     CPPUNIT_TEST_SUITE_END();
 };
@@ -453,6 +457,85 @@ void ScMacrosTest::testPasswordProtectedUnicodeString()
     xCloseable->close(true);
 }
 
+void ScMacrosTest::testTdf131296_legacy()
+{
+    // For legacy password-protected library images, we must correctly get the constants' values,
+    // and also - for Integer - the type.
+    const std::vector<std::pair<OUString, OUString>> aTests({
+        { "TestIntConst", "Integer: 123" },
+        { "TestLongConst", "Double: 123" },
+        { "TestSingleConst", "Double: 123" },
+        { "TestDoubleConst", "Double: 123" },
+    });
+
+    OUString aFileName;
+    createFileURL("tdf131296_legacy.ods", aFileName);
+    auto xComponent = loadFromDesktop(aFileName, "com.sun.star.sheet.SpreadsheetDocument");
+    CPPUNIT_ASSERT(xComponent);
+
+    {
+        Any aRet;
+        Sequence<sal_Int16> aOutParamIndex;
+        Sequence<Any> aOutParam;
+        Sequence<uno::Any> aParams;
+
+        for (auto& [sTestName, sExpected] : aTests)
+        {
+            SfxObjectShell::CallXScript(xComponent,
+                                        "vnd.sun.Star.script:Protected.Module1." + sTestName
+                                            + "?language=Basic&location=document",
+                                        aParams, aRet, aOutParamIndex, aOutParam);
+
+            OUString aReturnValue;
+            aRet >>= aReturnValue;
+            CPPUNIT_ASSERT_EQUAL_MESSAGE(sTestName.toUtf8().getStr(), sExpected, aReturnValue);
+        }
+    }
+
+    css::uno::Reference<css::util::XCloseable> xCloseable(xComponent, css::uno::UNO_QUERY_THROW);
+    xCloseable->close(true);
+}
+
+void ScMacrosTest::testTdf131296_new()
+{
+    // For new password-protected library images, we must correctly get both the constants' values
+    // and their types.
+    const std::vector<std::pair<OUString, OUString>> aTests({
+        { "TestIntConst", "Integer: 123" },
+        { "TestLongConst", "Long: 123" },
+        { "TestSingleConst", "Single: 123" },
+        { "TestDoubleConst", "Double: 123" },
+        { "TestCurrencyConst", "Currency: 123.0000" },
+    });
+
+    OUString aFileName;
+    createFileURL("tdf131296_new.ods", aFileName);
+    auto xComponent = loadFromDesktop(aFileName, "com.sun.star.sheet.SpreadsheetDocument");
+    CPPUNIT_ASSERT(xComponent);
+
+    {
+        Any aRet;
+        Sequence<sal_Int16> aOutParamIndex;
+        Sequence<Any> aOutParam;
+        Sequence<uno::Any> aParams;
+
+        for (auto& [sTestName, sExpected] : aTests)
+        {
+            SfxObjectShell::CallXScript(xComponent,
+                                        "vnd.sun.Star.script:Protected.Module1." + sTestName
+                                            + "?language=Basic&location=document",
+                                        aParams, aRet, aOutParamIndex, aOutParam);
+
+            OUString aReturnValue;
+            aRet >>= aReturnValue;
+            CPPUNIT_ASSERT_EQUAL_MESSAGE(sTestName.toUtf8().getStr(), sExpected, aReturnValue);
+        }
+    }
+
+    css::uno::Reference<css::util::XCloseable> xCloseable(xComponent, css::uno::UNO_QUERY_THROW);
+    xCloseable->close(true);
+}
+
 ScMacrosTest::ScMacrosTest()
       : UnoApiTest("/sc/qa/extras/testdocuments")
 {
diff --git a/sc/qa/extras/testdocuments/tdf131296_legacy.ods b/sc/qa/extras/testdocuments/tdf131296_legacy.ods
new file mode 100644
index 000000000000..43ebdeb24f67
Binary files /dev/null and b/sc/qa/extras/testdocuments/tdf131296_legacy.ods differ
diff --git a/sc/qa/extras/testdocuments/tdf131296_new.ods b/sc/qa/extras/testdocuments/tdf131296_new.ods
new file mode 100644
index 000000000000..9c0161c40ccd
Binary files /dev/null and b/sc/qa/extras/testdocuments/tdf131296_new.ods differ


More information about the Libreoffice-commits mailing list