tdf#144353 - Handling of missing optional parameters
Don't assign a missing optional variable to a property and don't allow
the computation/comparision including missing optional attributes.
In the previous cases a ERRCODE_BASIC_NOT_OPTIONAL is raised.
Change-Id: Iab391286fcace16c271ae511304075e2a0c5c651
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/121794
Tested-by: Jenkins
Reviewed-by: Andreas Heinisch <andreas.heinisch@yahoo.de>
diff --git a/basic/qa/basic_coverage/test_optional_paramters_basic.bas b/basic/qa/basic_coverage/test_optional_paramters_basic.bas
index ed2cdc7..a684fc2 100644
--- a/basic/qa/basic_coverage/test_optional_paramters_basic.bas
+++ b/basic/qa/basic_coverage/test_optional_paramters_basic.bas
@@ -1,5 +1,9 @@
Option Explicit
Type testObject
testInt As Integer
End Type
Function doUnitTest() As String
TestUtil.TestInit
verify_testOptionalsBasic
@@ -97,6 +101,30 @@ Sub verify_testOptionalsBasic()
TestUtil.AssertEqualApprox(TestOptArrayByRefByVal(, aB), 691.2, 1E-5, "TestOptArrayByRefByVal(, B)")
TestUtil.AssertEqualApprox(TestOptArrayByRefByVal(aA, aB), 1270.2, 1E-5, "TestOptArrayByRefByVal(A, B)")
' tdf#144353 - error handling of missing optional parameters (arithmetic operator)
' Without the fix in place, this test would have failed with:
' - Expected: 449 (ERRCODE_BASIC_NOT_OPTIONAL - Argument not optional)
' - Actual : 549 (Actual value of the variable)
TestUtil.AssertEqual(TestArithmeticOperator, 449, "TestArithmeticOperator")
' tdf#144353 - error handling of missing optional parameters (unary operator)
' Without the fix in place, this test would have failed with:
' - Expected: 449 (ERRCODE_BASIC_NOT_OPTIONAL - Argument not optional)
' - Actual : 100 (Actual value of the variable)
TestUtil.AssertEqual(TestUnaryOperator, 449, "TestUnaryOperator")
' tdf#144353 - error handling of missing optional parameters (assigning to a collection)
' Without the fix in place, this test would have failed with:
' - Expected: 449 (ERRCODE_BASIC_NOT_OPTIONAL - Argument not optional)
' - Actual : 549 (Actual value of the variable)
TestUtil.AssertEqual(TestCollection, 449, "TestCollection")
' tdf#144353 - error handling of missing optional parameters
' Without the fix in place, this test would have failed with:
' - Expected: 449 (ERRCODE_BASIC_NOT_OPTIONAL - Argument not optional)
' - Actual : 448 (Actual value of the variable)
TestUtil.AssertEqual(TestObjectError, 449, "TestObjectError")
Exit Sub
errorHandler:
TestUtil.ReportErrorHandler("verify_testOptionalsBasic", Err, Error$, Erl)
@@ -166,6 +194,41 @@ Function OptStringConcat(is_missingA As Boolean, A, is_missingB As Boolean, B)
If Not is_missingB Then OptStringConcat = OptStringConcat & B
End Function
Function TestArithmeticOperator(Optional optInt)
On Error GoTo errorHandler
optInt = optInt + 100
TestArithmeticOperator = optInt
errorHandler:
TestArithmeticOperator = Err()
End Function
Function TestUnaryOperator(Optional optInt)
On Error GoTo errorHandler
If (Not optInt) Then optInt = 100
TestUnaryOperator = optInt
errorHandler:
TestUnaryOperator = Err()
End Function
Function TestCollection(Optional optInt)
On Error GoTo errorHandler
Dim cA As New Collection
cA.Add(optInt)
TestCollection = cA.Item(1) + 100
errorHandler:
TestCollection = Err()
End Function
Function TestObjectError(Optional optInt)
On Error GoTo errorHandler
Dim aTestObject As Variant
aTestObject = CreateObject("testObject")
aTestObject.testInt = optInt
TestObjectError = optInt
errorHandler:
TestObjectError = Err()
End Function
Function CollectionSum(C)
Dim idx As Integer
CollectionSum = 0
diff --git a/basic/qa/basic_coverage/test_optional_paramters_compatible.bas b/basic/qa/basic_coverage/test_optional_paramters_compatible.bas
index 00aada0..56b3142 100644
--- a/basic/qa/basic_coverage/test_optional_paramters_compatible.bas
+++ b/basic/qa/basic_coverage/test_optional_paramters_compatible.bas
@@ -1,6 +1,10 @@
Option Compatible
Option Explicit
Type testObject
testInt As Integer
End Type
Function doUnitTest() As String
TestUtil.TestInit
verify_testOptionalsCompatible
@@ -99,6 +103,30 @@ Sub verify_testOptionalsCompatible()
TestUtil.AssertEqualApprox(TestOptArrayByRefByVal(, aB), 691.2, 1E-5, "TestOptArrayByRefByVal(, B)")
TestUtil.AssertEqualApprox(TestOptArrayByRefByVal(aA, aB), 1270.2, 1E-5, "TestOptArrayByRefByVal(A, B)")
' tdf#144353 - error handling of missing optional parameters (arithmetic operator)
' Without the fix in place, this test would have failed with:
' - Expected: 449 (ERRCODE_BASIC_NOT_OPTIONAL - Argument not optional)
' - Actual : 549 (Actual value of the variable)
TestUtil.AssertEqual(TestArithmeticOperator, 449, "TestArithmeticOperator")
' tdf#144353 - error handling of missing optional parameters (unary operator)
' Without the fix in place, this test would have failed with:
' - Expected: 449 (ERRCODE_BASIC_NOT_OPTIONAL - Argument not optional)
' - Actual : 100 (Actual value of the variable)
TestUtil.AssertEqual(TestUnaryOperator, 449, "TestUnaryOperator")
' tdf#144353 - error handling of missing optional parameters (assigning to a collection)
' Without the fix in place, this test would have failed with:
' - Expected: 449 (ERRCODE_BASIC_NOT_OPTIONAL - Argument not optional)
' - Actual : 549 (Actual value of the variable)
TestUtil.AssertEqual(TestCollection, 449, "TestCollection")
' tdf#144353 - error handling of missing optional parameters (assigning to an object)
' Without the fix in place, this test would have failed with:
' - Expected: 449 (ERRCODE_BASIC_NOT_OPTIONAL - Argument not optional)
' - Actual : 448 (Actual value of the variable)
TestUtil.AssertEqual(TestObjectError, 449, "TestObjectError")
Exit Sub
errorHandler:
TestUtil.ReportErrorHandler("verify_testOptionalsCompatible", Err, Error$, Erl)
@@ -168,6 +196,41 @@ Function OptStringConcat(is_missingA As Boolean, A, is_missingB As Boolean, B)
If Not is_missingB Then OptStringConcat = OptStringConcat & B
End Function
Function TestArithmeticOperator(Optional optInt)
On Error GoTo errorHandler
optInt = optInt + 100
TestArithmeticOperator = optInt
errorHandler:
TestArithmeticOperator = Err()
End Function
Function TestUnaryOperator(Optional optInt)
On Error GoTo errorHandler
If (Not optInt) Then optInt = 100
TestUnaryOperator = optInt
errorHandler:
TestUnaryOperator = Err()
End Function
Function TestCollection(Optional optInt)
On Error GoTo errorHandler
Dim cA As New Collection
cA.Add(optInt)
TestCollection = cA.Item(1) + 100
errorHandler:
TestCollection = Err()
End Function
Function TestObjectError(Optional optInt)
On Error GoTo errorHandler
Dim aTestObject As Variant
aTestObject = CreateObject("testObject")
aTestObject.testInt = optInt
TestObjectError = optInt
errorHandler:
TestObjectError = Err()
End Function
Function CollectionSum(C)
Dim idx As Integer
CollectionSum = 0
diff --git a/basic/source/runtime/runtime.cxx b/basic/source/runtime/runtime.cxx
index 6ab4972..cbe62a6 100644
--- a/basic/source/runtime/runtime.cxx
+++ b/basic/source/runtime/runtime.cxx
@@ -1309,6 +1309,14 @@ void SbiRuntime::StepArith( SbxOperator eOp )
TOSMakeTemp();
SbxVariable* p2 = GetTOS();
// tdf#144353 - do not compute any operation with a missing optional variable
if ((p1->GetType() == SbxERROR && IsMissing(p1.get(), 1))
|| (p2->GetType() == SbxERROR && IsMissing(p2, 1)))
{
Error(ERRCODE_BASIC_NOT_OPTIONAL);
return;
}
p2->ResetFlag( SbxFlagBits::Fixed );
p2->Compute( eOp, *p1 );
@@ -1319,6 +1327,12 @@ void SbiRuntime::StepUnary( SbxOperator eOp )
{
TOSMakeTemp();
SbxVariable* p = GetTOS();
// tdf#144353 - do not compute any operation with a missing optional variable
if (p->GetType() == SbxERROR && IsMissing(p, 1))
{
Error(ERRCODE_BASIC_NOT_OPTIONAL);
return;
}
p->Compute( eOp, *p );
}
@@ -1327,6 +1341,14 @@ void SbiRuntime::StepCompare( SbxOperator eOp )
SbxVariableRef p1 = PopVar();
SbxVariableRef p2 = PopVar();
// tdf#144353 - do not compare a missing optional variable
if ((p1->GetType() == SbxERROR && SbiRuntime::IsMissing(p1.get(), 1))
|| (p2->GetType() == SbxERROR && SbiRuntime::IsMissing(p2.get(), 1)))
{
SbxBase::SetError(ERRCODE_BASIC_NOT_OPTIONAL);
return;
}
// Make sure objects with default params have
// values ( and type ) set as appropriate
SbxDataType p1Type = p1->GetType();
@@ -1607,6 +1629,13 @@ static bool checkUnoStructCopy( bool bVBA, SbxVariableRef const & refVal, SbxVar
SbxDataType eVarType = refVar->GetType();
SbxDataType eValType = refVal->GetType();
// tdf#144353 - do not assign a missing optional variable to a property
if (refVal->GetType() == SbxERROR && SbiRuntime::IsMissing(refVal.get(), 1))
{
SbxBase::SetError(ERRCODE_BASIC_NOT_OPTIONAL);
return true;
}
if ( ( bVBA && ( eVarType == SbxEMPTY ) ) || !refVar->CanWrite() )
return false;
diff --git a/basic/source/sbx/sbxvar.cxx b/basic/source/sbx/sbxvar.cxx
index 5900c68..b8be36e 100644
--- a/basic/source/sbx/sbxvar.cxx
+++ b/basic/source/sbx/sbxvar.cxx
@@ -280,6 +280,9 @@ SbxVariable& SbxVariable::operator=( const SbxVariable& r )
if (this != &r)
{
SbxValue::operator=( r );
// tdf#144353 - copy information about a missing parameter. See SbiRuntime::SetIsMissing.
if (r.pInfo && !dynamic_cast<const SbxMethod*>(&r))
pInfo = r.pInfo;
m_aDeclareClassName = r.m_aDeclareClassName;
m_xComListener = r.m_xComListener;
m_pComListenerParentBasic = r.m_pComListenerParentBasic;