Skip to content

Commit 9ab11b0

Browse files
committed
[fix] improve FunctionSignature.equals
fixes #5685 Erroneous comparison of signatures of anonymous functions lead to wrong tail call optimizations that lead to an NPE further down the call stack.
1 parent 70b0704 commit 9ab11b0

File tree

2 files changed

+50
-10
lines changed

2 files changed

+50
-10
lines changed

exist-core/src/main/java/org/exist/xquery/FunctionSignature.java

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -262,16 +262,20 @@ public boolean equals(final Object obj) {
262262
if(obj == null || !(obj instanceof FunctionSignature)) {
263263
return false;
264264
}
265-
266-
final FunctionSignature other = (FunctionSignature)obj;
267-
if(name == null) {
268-
if(other.name != null) {
269-
return false;
270-
}
271-
return getArgumentCount() == other.getArgumentCount();
265+
// quick comparison by object identity
266+
if (this == obj) { return true; }
267+
268+
// anonymous functions cannot be compared by name and argument count
269+
final FunctionSignature other = (FunctionSignature) obj;
270+
if (
271+
name == null || other.name == null ||
272+
name.getLocalPart().equals("") ||
273+
other.name.getLocalPart().equals("")
274+
) {
275+
return false;
272276
}
273-
274-
if(name.equals(other.name)) {
277+
278+
if (name.equals(other.name)) {
275279
return getArgumentCount() == other.getArgumentCount();
276280
}
277281

exist-core/src/test/xquery/maps/maps.xqm

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,16 @@ declare variable $mt:integerKeys := map {
4949
7 : "Saturday"
5050
};
5151

52+
declare variable $mt:places := map {
53+
"Scotland": map {
54+
"Highlands": map {
55+
"Inverness": 1,
56+
"Fort William": 1
57+
},
58+
"Lowlands": map { "Glasgow": 1 }
59+
}
60+
};
61+
5262
declare variable $mt:mapOfSequences := map {0: (), 1 : ("One", "Two") };
5363

5464
declare
@@ -720,7 +730,7 @@ function mt:single-entry-map() {
720730
map:for-each($map, function($k, $v) { $k })
721731
};
722732

723-
declare
733+
declare
724734
%test:assertEquals(5)
725735
function mt:qname() {
726736
let $a := 1
@@ -989,3 +999,29 @@ function mt:map-merge-2-empty-options-map() {
989999
let $actual := map:merge($maps, map {})
9901000
return $expected?Su eq $actual?Su
9911001
};
1002+
1003+
(: test for issue https://github.com/eXist-db/exist/issues/5685 :)
1004+
declare
1005+
%test:assertEquals("<ul><li>Scotland<ul><li>Highlands<ul><li>Fort William</li><li>Inverness</li></ul></li><li>Lowlands<ul><li>Glasgow</li></ul></li></ul></li></ul>")
1006+
function mt:nested-map-for-each() {
1007+
<ul>{
1008+
map:for-each($mt:places, function($country-key, $region-map) {
1009+
<li>{
1010+
$country-key,
1011+
<ul>{
1012+
map:for-each($region-map, function($region-key, $town-map) {
1013+
<li>{
1014+
$region-key,
1015+
<ul>{
1016+
map:for-each($town-map, function($town-key, $town-value) {
1017+
<li>{ $town-key }</li>
1018+
})
1019+
}</ul>
1020+
}</li>
1021+
})
1022+
}</ul>
1023+
}</li>
1024+
})
1025+
}</ul>
1026+
=> serialize(map{'indent':false()})
1027+
};

0 commit comments

Comments
 (0)