tdf#142460: properly handle boolean values in string pool
This makes sure that results of comparison of literals have proper boolean type,
and that this type is properly stored to/read from the string pool.
This introduces a new non-standard "type" character used in the pool: 'b'. It is
not a proper type character used in Basic (unlike '%'/'&'/'!'/'@'), but we have
to use this trick locally, because we need to pass the type that has no own type
character.
The change should be backward-compatible: older versions reading the value should
just ignore the 'b', and read the value as double.
Change-Id: Ibd4a70b366331342346eb171c8ed3c7026279596
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/117655
Tested-by: Jenkins
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
diff --git a/basic/qa/vba_tests/booltypename.vb b/basic/qa/vba_tests/booltypename.vb
new file mode 100644
index 0000000..8c1fd17
--- /dev/null
+++ b/basic/qa/vba_tests/booltypename.vb
@@ -0,0 +1,37 @@
'
' 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 1
Option Explicit
Function doUnitTest() As String
TestUtil.TestInit
verify_testTypeNameBoolean
doUnitTest = TestUtil.GetResult()
End Function
Sub verify_testTypeNameBoolean()
On Error GoTo errorHandler
TestUtil.AssertEqual(TypeName 1>2, "Boolean", "TypeName 1>2")
TestUtil.AssertEqual(TypeName 2.0>1.0, "Boolean", "TypeName 2.0>1.0")
TestUtil.AssertEqual(TypeName "A">"B", "Boolean", "TypeName ""A"">""B""")
TestUtil.AssertEqual(Str(2>1), "True", "Str(2>1)")
TestUtil.AssertEqual(Str(1>2), "False", "Str(1>2)")
TestUtil.AssertEqual(Str(2.0>1.0), "True", "Str(2.0>1.0)")
TestUtil.AssertEqual(Str(1.0>2.0), "False", "Str(1.0>2.0)")
TestUtil.AssertEqual(Str("B">"A"), "True", "Str(""B"">""A"")")
TestUtil.AssertEqual(Str("A">"B"), "False", "Str(""A"">""B"")")
Exit Sub
errorHandler:
TestUtil.ReportErrorHandler("verify_testTypeNameBoolean", Err, Error$, Erl)
End Sub
diff --git a/basic/source/comp/exprnode.cxx b/basic/source/comp/exprnode.cxx
index 4192ceb..17bdbca 100644
--- a/basic/source/comp/exprnode.cxx
+++ b/basic/source/comp/exprnode.cxx
@@ -262,7 +262,7 @@ void SbiExprNode::FoldConstantsBinaryNode(SbiParser* pParser)
}
else
{
eType = SbxDOUBLE;
eType = SbxBOOL;
eNodeType = SbxNUMVAL;
int eRes = rr.compareTo( rl );
switch( eTok )
@@ -365,22 +365,22 @@ void SbiExprNode::FoldConstantsBinaryNode(SbiParser* pParser)
nVal = nl - nr; break;
case EQ:
nVal = ( nl == nr ) ? SbxTRUE : SbxFALSE;
eType = SbxINTEGER; break;
eType = SbxBOOL; break;
case NE:
nVal = ( nl != nr ) ? SbxTRUE : SbxFALSE;
eType = SbxINTEGER; break;
eType = SbxBOOL; break;
case LT:
nVal = ( nl < nr ) ? SbxTRUE : SbxFALSE;
eType = SbxINTEGER; break;
eType = SbxBOOL; break;
case GT:
nVal = ( nl > nr ) ? SbxTRUE : SbxFALSE;
eType = SbxINTEGER; break;
eType = SbxBOOL; break;
case LE:
nVal = ( nl <= nr ) ? SbxTRUE : SbxFALSE;
eType = SbxINTEGER; break;
eType = SbxBOOL; break;
case GE:
nVal = ( nl >= nr ) ? SbxTRUE : SbxFALSE;
eType = SbxINTEGER; break;
eType = SbxBOOL; break;
case IDIV:
if( !lr )
{
diff --git a/basic/source/comp/symtbl.cxx b/basic/source/comp/symtbl.cxx
index d9e7fca..ed245a3 100644
--- a/basic/source/comp/symtbl.cxx
+++ b/basic/source/comp/symtbl.cxx
@@ -66,6 +66,8 @@ short SbiStringPool::Add( double n, SbxDataType t )
char buf[40]{};
switch( t )
{
// tdf#142460 - properly handle boolean values in string pool
case SbxBOOL: snprintf( buf, sizeof(buf), "%db", static_cast<short>(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;
diff --git a/basic/source/inc/filefmt.hxx b/basic/source/inc/filefmt.hxx
index 3460b1a..25ba647 100644
--- a/basic/source/inc/filefmt.hxx
+++ b/basic/source/inc/filefmt.hxx
@@ -40,6 +40,9 @@
// Version 13: tdf#94617 store methods nStart information greater than sal_Int16 limit
// tdf#57113 store UTF-16 strings after legacy 1-byte-encoded strings in pool (no
// version number bump for backward compatibility; relies on magic number)
// tdf#142460: properly handle boolean values in string pool (no
// version number bump for backward compatibility; relies on
// new integer type suffix 'b')
//
#define B_LEGACYVERSION 0x00000011
diff --git a/basic/source/runtime/runtime.cxx b/basic/source/runtime/runtime.cxx
index 385f675..43e8eea 100644
--- a/basic/source/runtime/runtime.cxx
+++ b/basic/source/runtime/runtime.cxx
@@ -2840,6 +2840,8 @@ void SbiRuntime::StepLOADNC( sal_uInt32 nOp1 )
case '&': eType = SbxLONG; break;
case '!': eType = SbxSINGLE; break;
case '@': eType = SbxCURRENCY; break;
// tdf#142460 - properly handle boolean values in string pool
case 'b': eType = SbxBOOL; break;
}
}
SbxVariable* p = new SbxVariable( eType );