1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
|
From 48ce354351d58f4a63c45d0c56156ff1268bd050 Mon Sep 17 00:00:00 2001
From: Eike Rathke <erack@redhat.com>
Date: Thu, 16 Feb 2023 20:20:31 +0100
Subject: [PATCH] Obtain actual 0-parameter count for OR(), AND() and
1-parameter functions
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
OR and AND for legacy infix notation are classified as binary
operators but in fact are functions with parameter count. In case
no argument is supplied, GetByte() returns 0 and for that case the
implicit binary operator 2 parameters were wrongly assumed.
Similar for functions expecting 1 parameter, without argument 1
was assumed. For "real" unary and binary operators the compiler
already checks parameters. Omit OR and AND and 1-parameter
functions from this implicit assumption and return the actual 0
count.
Change-Id: Ie05398c112a98021ac2875cf7b6de994aee9d882
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/147173
Reviewed-by: Eike Rathke <erack@redhat.com>
Tested-by: Jenkins
(cherry picked from commit e7ce9bddadb2db222eaa5f594ef1de2e36d57e5c)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/147129
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
(cherry picked from commit d6599a2af131994487d2d9223a4fd32a8c3ddc49)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/147132
Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
Tested-by: Caolán McNamara <caolanm@redhat.com>
---
formula/source/core/api/token.cxx | 13 +++++--------
sc/source/core/tool/interpr4.cxx | 10 +++++++++-
2 files changed, 14 insertions(+), 9 deletions(-)
From 48ce354351d58f4a63c45d0c56156ff1268bd050 Mon Sep 17 00:00:00 2001
From: Eike Rathke <erack@redhat.com>
Date: Thu, 16 Feb 2023 20:20:31 +0100
Subject: [PATCH] Obtain actual 0-parameter count for OR(), AND() and
1-parameter functions
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
OR and AND for legacy infix notation are classified as binary
operators but in fact are functions with parameter count. In case
no argument is supplied, GetByte() returns 0 and for that case the
implicit binary operator 2 parameters were wrongly assumed.
Similar for functions expecting 1 parameter, without argument 1
was assumed. For "real" unary and binary operators the compiler
already checks parameters. Omit OR and AND and 1-parameter
functions from this implicit assumption and return the actual 0
count.
Change-Id: Ie05398c112a98021ac2875cf7b6de994aee9d882
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/147173
Reviewed-by: Eike Rathke <erack@redhat.com>
Tested-by: Jenkins
(cherry picked from commit e7ce9bddadb2db222eaa5f594ef1de2e36d57e5c)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/147129
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
(cherry picked from commit d6599a2af131994487d2d9223a4fd32a8c3ddc49)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/147132
Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
Tested-by: Caolán McNamara <caolanm@redhat.com>
---
formula/source/core/api/token.cxx | 13 +++++--------
sc/source/core/tool/interpr4.cxx | 10 +++++++++-
2 files changed, 14 insertions(+), 9 deletions(-)
From ef9af49e1060bfb2a15db81ba10703ebd520bbf6 Mon Sep 17 00:00:00 2001
From: Eike Rathke <erack@redhat.com>
Date: Mon, 27 Feb 2023 16:10:06 +0100
Subject: [PATCH] Always push a result, even if it's only an error
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
PERCENTILE() and QUARTILE() if an error was passed as argument (or
an error encountered during obtaining arguments) omitted to push
an error result, only setting the error.
Fallout from
commit f336f63da900d76c2bf6e5690f1c8a7bd15a0aa2
CommitDate: Thu Mar 3 16:28:59 2016 +0000
tdf#94635 Add FORECAST.ETS functions to Calc
Change-Id: I23e276fb0ce735cfd6383cc963446499dcf819f4
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/147922
Reviewed-by: Eike Rathke <erack@redhat.com>
Tested-by: Jenkins
(cherry picked from commit 64914560e279c71ff1233f4bab851e2a292797e6)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/147901
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
Reviewed-by: Michael Stahl <michael.stahl@allotropia.de>
Tested-by: Christian Lohmaier <lohmaier+LibreOffice@googlemail.com>
Reviewed-by: Christian Lohmaier <lohmaier+LibreOffice@googlemail.com>
---
sc/source/core/tool/interpr3.cxx | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff -urN libreoffice-7-0-4.old/formula/source/core/api/token.cxx libreoffice-7-0-4/formula/source/core/api/token.cxx
--- libreoffice-7-0-4.old/formula/source/core/api/token.cxx 2021-10-27 07:29:16.182034576 +0200
+++ libreoffice-7-0-4/formula/source/core/api/token.cxx 2023-05-22 19:05:09.572018039 +0200
@@ -93,17 +93,14 @@
return 0; // parameters and specials
// ocIf... jump commands not for FAP, have cByte then
//2do: bool parameter whether FAP or not?
- else if ( GetByte() )
+ else if (GetByte())
return GetByte(); // all functions, also ocExternal and ocMacro
- else if (SC_OPCODE_START_BIN_OP <= eOp && eOp < SC_OPCODE_STOP_BIN_OP)
- return 2; // binary
- else if ((SC_OPCODE_START_UN_OP <= eOp && eOp < SC_OPCODE_STOP_UN_OP)
- || eOp == ocPercentSign)
- return 1; // unary
+ else if (SC_OPCODE_START_BIN_OP <= eOp && eOp < SC_OPCODE_STOP_BIN_OP && eOp != ocAnd && eOp != ocOr)
+ return 2; // binary operators, compiler checked; OR and AND legacy but are functions
+ else if ((SC_OPCODE_START_UN_OP <= eOp && eOp < SC_OPCODE_STOP_UN_OP) || eOp == ocPercentSign)
+ return 1; // unary operators, compiler checked
else if (SC_OPCODE_START_NO_PAR <= eOp && eOp < SC_OPCODE_STOP_NO_PAR)
return 0; // no parameter
- else if (SC_OPCODE_START_1_PAR <= eOp && eOp < SC_OPCODE_STOP_1_PAR)
- return 1; // one parameter
else if (FormulaCompiler::IsOpCodeJumpCommand( eOp ))
return 1; // only the condition counts as parameter
else
diff -urN libreoffice-7-0-4.old/sc/source/core/inc/interpre.hxx libreoffice-7-0-4/sc/source/core/inc/interpre.hxx
--- libreoffice-7-0-4.old/sc/source/core/inc/interpre.hxx 2021-10-27 07:29:17.774042923 +0200
+++ libreoffice-7-0-4/sc/source/core/inc/interpre.hxx 2023-05-22 19:05:09.576018095 +0200
@@ -235,6 +235,7 @@
inline bool MustHaveParamCount( short nAct, short nMust );
inline bool MustHaveParamCount( short nAct, short nMust, short nMax );
inline bool MustHaveParamCountMin( short nAct, short nMin );
+ inline bool MustHaveParamCountMinWithStackCheck( short nAct, short nMin );
void PushParameterExpected();
void PushIllegalParameter();
void PushIllegalArgument();
@@ -1089,6 +1090,17 @@
return false;
}
+inline bool ScInterpreter::MustHaveParamCountMinWithStackCheck( short nAct, short nMin )
+{
+ assert(sp >= nAct);
+ if (sp < nAct)
+ {
+ PushParameterExpected();
+ return false;
+ }
+ return MustHaveParamCountMin( nAct, nMin);
+}
+
inline bool ScInterpreter::CheckStringPositionArgument( double & fVal )
{
if (!std::isfinite( fVal))
diff -urN libreoffice-7-0-4.old/sc/source/core/tool/interpr1.cxx libreoffice-7-0-4/sc/source/core/tool/interpr1.cxx
--- libreoffice-7-0-4.old/sc/source/core/tool/interpr1.cxx 2023-05-20 18:17:05.645488480 +0200
+++ libreoffice-7-0-4/sc/source/core/tool/interpr1.cxx 2023-05-22 19:06:29.129145235 +0200
@@ -7528,7 +7528,7 @@
void ScInterpreter::ScSubTotal()
{
sal_uInt8 nParamCount = GetByte();
- if ( MustHaveParamCountMin( nParamCount, 2 ) )
+ if ( MustHaveParamCountMinWithStackCheck( nParamCount, 2 ) )
{
// We must fish the 1st parameter deep from the stack! And push it on top.
const FormulaToken* p = pStack[ sp - nParamCount ];
@@ -7575,7 +7575,7 @@
void ScInterpreter::ScAggregate()
{
sal_uInt8 nParamCount = GetByte();
- if ( MustHaveParamCountMin( nParamCount, 3 ) )
+ if ( MustHaveParamCountMinWithStackCheck( nParamCount, 3 ) )
{
const FormulaError nErr = nGlobalError;
nGlobalError = FormulaError::NONE;
diff -urN libreoffice-7-0-4.old/sc/source/core/tool/interpr3.cxx libreoffice-7-0-4/sc/source/core/tool/interpr3.cxx
--- libreoffice-7-0-4.old/sc/source/core/tool/interpr3.cxx 2021-10-27 07:29:17.798043049 +0200
+++ libreoffice-7-0-4/sc/source/core/tool/interpr3.cxx 2023-05-22 19:05:09.584018209 +0200
@@ -3478,7 +3478,7 @@
GetNumberSequenceArray( 1, aArray, false );
if ( aArray.empty() || nGlobalError != FormulaError::NONE )
{
- SetError( FormulaError::NoValue );
+ PushNoValue();
return;
}
if ( bInclusive )
@@ -3501,7 +3501,7 @@
GetNumberSequenceArray( 1, aArray, false );
if ( aArray.empty() || nGlobalError != FormulaError::NONE )
{
- SetError( FormulaError::NoValue );
+ PushNoValue();
return;
}
if ( bInclusive )
diff --git a/sc/source/core/tool/interpr4.cxx b/sc/source/core/tool/interpr4.cxx
index 347377ed0a90..80a0e3027bc3 100644
--- a/sc/source/core/tool/interpr4.cxx
+++ b/sc/source/core/tool/interpr4.cxx
@@ -4023,7 +4023,15 @@ StackVar ScInterpreter::Interpret()
else if (sp >= pCur->GetParamCount())
nStackBase = sp - pCur->GetParamCount();
else
- nStackBase = sp; // underflow?!?
+ {
+ SAL_WARN("sc.core", "Stack anomaly at " << aPos.Format(
+ ScRefFlags::VALID | ScRefFlags::FORCE_DOC | ScRefFlags::TAB_3D, pDok)
+ << " eOp: " << static_cast<int>(eOp)
+ << " params: " << static_cast<int>(pCur->GetParamCount())
+ << " nStackBase: " << nStackBase << " sp: " << sp);
+ nStackBase = sp;
+ assert(!"underflow");
+ }
}
switch( eOp )
|