Skip to content

Commit 94899de

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 6952335 commit 94899de

File tree

2 files changed

+48
-8
lines changed

2 files changed

+48
-8
lines changed

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

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -262,15 +262,19 @@ public boolean equals(final Object obj) {
262262
if(obj == null || !(obj instanceof FunctionSignature other)) {
263263
return false;
264264
}
265+
// quick comparison by object identity
266+
if (this == other) { return true; }
265267

266-
if(name == null) {
267-
if(other.name != null) {
268-
return false;
269-
}
270-
return getArgumentCount() == other.getArgumentCount();
268+
// anonymous functions cannot be compared by name and argument count
269+
if (
270+
name == null || other.name == null ||
271+
name.getLocalPart().equals("") ||
272+
other.name.getLocalPart().equals("")
273+
) {
274+
return false;
271275
}
272-
273-
if(name.equals(other.name)) {
276+
277+
if (name.equals(other.name)) {
274278
return getArgumentCount() == other.getArgumentCount();
275279
}
276280

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
@@ -714,7 +724,7 @@ function mt:single-entry-map() {
714724
map:for-each($map, function($k, $v) { $k })
715725
};
716726

717-
declare
727+
declare
718728
%test:assertEquals(5)
719729
function mt:qname() {
720730
let $a := 1
@@ -976,3 +986,29 @@ function mt:map-merge-2-empty-options-map() {
976986
let $actual := map:merge($maps, map {})
977987
return $expected?Su eq $actual?Su
978988
};
989+
990+
(: test for issue https://github.com/eXist-db/exist/issues/5685 :)
991+
declare
992+
%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>")
993+
function mt:nested-map-for-each() {
994+
<ul>{
995+
map:for-each($mt:places, function($country-key, $region-map) {
996+
<li>{
997+
$country-key,
998+
<ul>{
999+
map:for-each($region-map, function($region-key, $town-map) {
1000+
<li>{
1001+
$region-key,
1002+
<ul>{
1003+
map:for-each($town-map, function($town-key, $town-value) {
1004+
<li>{ $town-key }</li>
1005+
})
1006+
}</ul>
1007+
}</li>
1008+
})
1009+
}</ul>
1010+
}</li>
1011+
})
1012+
}</ul>
1013+
=> serialize(map{'indent':false()})
1014+
};

0 commit comments

Comments
 (0)