Skip to content

Commit 35249a7

Browse files
line-oadamretter
authored andcommitted
[fix] raise static error for absolute XPaths in functions
The Xquery parser will throw a static error XPDY0002 when an absolute XPath is used inside of a function body without a document context. Examples: - `function () { //a }` - `function () { /a[foo] }` Still allowed: ``` function ($docs as document()*) { $docs ! //a } ```
1 parent 94b69cf commit 35249a7

File tree

1 file changed

+43
-8
lines changed
  • exist-core/src/main/antlr/org/exist/xquery/parser

1 file changed

+43
-8
lines changed

exist-core/src/main/antlr/org/exist/xquery/parser/XQuery.g

Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -521,7 +521,11 @@ functionBody throws XPathException
521521
:
522522
( LCURLY RCURLY ) => l:LCURLY^ RCURLY!
523523
{ #functionBody= #(#l, #(#[PARENTHESIZED, "Parenthesized"], null)); }
524-
| LCURLY^ expr RCURLY!
524+
| LCURLY^
525+
{ lexer.inFunctionBody = true; }
526+
expr
527+
{ lexer.inFunctionBody = false; }
528+
RCURLY!
525529
;
526530
527531
returnType throws XPathException:
@@ -1059,8 +1063,20 @@ unaryExpr throws XPathException
10591063
;
10601064
10611065
valueExpr throws XPathException
1066+
{ Boolean inFunctionBodyState = lexer.inFunctionBody; }
10621067
:
1063-
pathExpr (BANG^ pathExpr)*
1068+
pathExpr (
1069+
BANG^
1070+
{
1071+
// simple map operator might add new document context
1072+
lexer.inFunctionBody = false;
1073+
}
1074+
pathExpr
1075+
{
1076+
// reset state
1077+
lexer.inFunctionBody = inFunctionBodyState;
1078+
}
1079+
)*
10641080
|
10651081
extensionExpr
10661082
;
@@ -1111,15 +1127,33 @@ pathExpr throws XPathException
11111127
relativePathExpr
11121128
|
11131129
( SLASH relativePathExpr )
1114-
=> SLASH relPath:relativePathExpr
1115-
{ #pathExpr= #(#[ABSOLUTE_SLASH, "AbsoluteSlash"], #relPath); }
1130+
=> s1:SLASH relPath:relativePathExpr
1131+
{
1132+
if (lexer.inFunctionBody) {
1133+
throw new XPathException(#s1.getLine(), #s1.getColumn(), ErrorCodes.XPDY0002,
1134+
"Leading '/' selects nothing, ContextItem is absent in function body");
1135+
}
1136+
#pathExpr= #(#[ABSOLUTE_SLASH, "AbsoluteSlash"], #relPath);
1137+
}
11161138
// lone slash
11171139
|
1118-
SLASH
1119-
{ #pathExpr= #[ABSOLUTE_SLASH, "AbsoluteSlash"]; }
1140+
s2:SLASH
1141+
{
1142+
if (lexer.inFunctionBody) {
1143+
throw new XPathException(#s2.getLine(), #s2.getColumn(), ErrorCodes.XPDY0002,
1144+
"Leading '/' selects nothing, ContextItem is absent in function body");
1145+
}
1146+
#pathExpr= #[ABSOLUTE_SLASH, "AbsoluteSlash"];
1147+
}
11201148
|
1121-
DSLASH relPath2:relativePathExpr
1122-
{ #pathExpr= #(#[ABSOLUTE_DSLASH, "AbsoluteSlashSlash"], #relPath2); }
1149+
ds:DSLASH relPath2:relativePathExpr
1150+
{
1151+
if (lexer.inFunctionBody) {
1152+
throw new XPathException(#ds.getLine(), #ds.getColumn(), ErrorCodes.XPDY0002,
1153+
"Leading '//' selects nothing, ContextItem is absent in function body");
1154+
}
1155+
#pathExpr= #(#[ABSOLUTE_DSLASH, "AbsoluteSlashSlash"], #relPath2);
1156+
}
11231157
;
11241158
11251159
relativePathExpr throws XPathException
@@ -2188,6 +2222,7 @@ options {
21882222
protected boolean inStringConstructor = false;
21892223
protected boolean inElementContent= false;
21902224
protected boolean inAttributeContent= false;
2225+
protected boolean inFunctionBody= false;
21912226
protected char attrDelimChar = '"';
21922227
protected boolean inComment= false;
21932228
protected boolean inPragma = false;

0 commit comments

Comments
 (0)