Skip to content

Commit 5e2ef13

Browse files
Matthew J GreenwoodMatthew J Greenwood
authored andcommitted
added negative test cases - removed readPosition from function parameter parser, ready for review
1 parent 5d8e209 commit 5e2ef13

File tree

2 files changed

+76
-18
lines changed

2 files changed

+76
-18
lines changed

json-path/src/main/java/com/jayway/jsonpath/internal/path/PathCompiler.java

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -204,8 +204,10 @@ else if (c == OPEN_PARENTHESIS) {
204204
// read the next token to determine if we have a simple no-args function call
205205
char c = path.charAt(readPosition + 1);
206206
if (c != CLOSE_PARENTHESIS) {
207+
path.setPosition(endPosition+1);
207208
// parse the arguments of the function - arguments that are inner queries or JSON document(s)
208-
functionParameters = parseFunctionParameters(readPosition);
209+
String functionName = path.subSequence(startPosition, endPosition).toString();
210+
functionParameters = parseFunctionParameters(functionName);
209211
} else {
210212
path.setPosition(readPosition + 1);
211213
}
@@ -252,14 +254,12 @@ else if (c == OPEN_PARENTHESIS) {
252254
*
253255
* The above is a valid function call, we're first summing 10 + avg of 1...10 (5.5) so the total should be 15.5
254256
*
255-
* @param readPosition
256-
* The current position within the stream we've advanced - TODO remove the need for this...
257257
* @return
258258
* An ordered list of parameters that are to processed via the function. Typically functions either process
259259
* an array of values and/or can consume parameters in addition to the values provided from the consumption of
260260
* an array.
261261
*/
262-
private List<Parameter> parseFunctionParameters(int readPosition) {
262+
private List<Parameter> parseFunctionParameters(String funcName) {
263263
PathToken currentToken;
264264
ParamType type = null;
265265

@@ -270,8 +270,9 @@ private List<Parameter> parseFunctionParameters(int readPosition) {
270270
char priorChar = 0;
271271
List<Parameter> parameters = new ArrayList<Parameter>();
272272
StringBuffer parameter = new StringBuffer();
273-
while (path.inBounds(readPosition) && !endOfStream) {
274-
char c = path.charAt(readPosition++);
273+
while (path.inBounds() && !endOfStream) {
274+
char c = path.currentChar();
275+
path.incrementPosition(1);
275276

276277
// we're at the start of the stream, and don't know what type of parameter we have
277278
if (type == null) {
@@ -290,6 +291,9 @@ else if (isPathContext(c)) {
290291
switch (c) {
291292
case DOUBLE_QUOTE:
292293
if (priorChar != '\\' && groupQuote > 0) {
294+
if (groupQuote == 0) {
295+
throw new InvalidPathException("Unexpected quote '\"' at character position: " + path.position());
296+
}
293297
groupQuote--;
294298
}
295299
else {
@@ -307,9 +311,15 @@ else if (isPathContext(c)) {
307311
break;
308312

309313
case CLOSE_BRACE:
314+
if (0 == groupBrace) {
315+
throw new InvalidPathException("Unexpected close brace '}' at character position: " + path.position());
316+
}
310317
groupBrace--;
311318
break;
312319
case CLOSE_SQUARE_BRACKET:
320+
if (0 == groupBracket) {
321+
throw new InvalidPathException("Unexpected close bracket ']' at character position: " + path.position());
322+
}
313323
groupBracket--;
314324
break;
315325

@@ -323,26 +333,27 @@ else if (isPathContext(c)) {
323333
case COMMA:
324334
// In this state we've reach the end of a function parameter and we can pass along the parameter string
325335
// to the parser
326-
if ((0 == groupQuote && 0 == groupBrace && 0 == groupBracket && ((0 == groupParen && CLOSE_PARENTHESIS == c) || 1 == groupParen))) {
336+
if ((0 == groupQuote && 0 == groupBrace && 0 == groupBracket
337+
&& ((0 == groupParen && CLOSE_PARENTHESIS == c) || 1 == groupParen))) {
327338
endOfStream = (0 == groupParen);
328339

329340
if (null != type) {
330341
Parameter param = null;
331-
if (type == ParamType.JSON) {
332-
// parse the json and set the value
333-
param = new Parameter(parameter.toString());
334-
} else if (type == ParamType.PATH) {
335-
LinkedList<Predicate> predicates = new LinkedList<Predicate>();
336-
PathCompiler compiler = new PathCompiler(parameter.toString(), predicates);
337-
param = new Parameter(compiler.compile());
342+
switch (type) {
343+
case JSON:
344+
// parse the json and set the value
345+
param = new Parameter(parameter.toString());
346+
break;
347+
case PATH:
348+
LinkedList<Predicate> predicates = new LinkedList<Predicate>();
349+
PathCompiler compiler = new PathCompiler(parameter.toString(), predicates);
350+
param = new Parameter(compiler.compile());
351+
break;
338352
}
339353
if (null != param) {
340354
parameters.add(param);
341-
} else {
342-
// TODO: raise error...
343355
}
344356
parameter.delete(0, parameter.length());
345-
346357
type = null;
347358
}
348359
}
@@ -354,7 +365,9 @@ else if (isPathContext(c)) {
354365
}
355366
priorChar = c;
356367
}
357-
path.setPosition(readPosition);
368+
if (0 != groupBrace || 0 != groupParen || 0 != groupBracket) {
369+
throw new InvalidPathException("Arguments to function: '" + funcName + "' are not closed properly.");
370+
}
358371
return parameters;
359372
}
360373

json-path/src/test/java/com/jayway/jsonpath/internal/function/NestedFunctionTest.java

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
import org.slf4j.Logger;
99
import org.slf4j.LoggerFactory;
1010

11+
import static com.jayway.jsonpath.JsonPath.using;
12+
import static org.junit.Assert.assertTrue;
13+
1114
/**
1215
* Created by matt@mjgreenwood.net on 12/10/15.
1316
*/
@@ -74,4 +77,46 @@ public void testLoadFunction() {
7477
public void testAppendNumber() {
7578
verifyMathFunction(conf, "$.numbers.append(11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 0).avg()", 10.0);
7679
}
80+
81+
/**
82+
* Aggregation function should ignore text values
83+
*/
84+
@Test
85+
public void testAppendTextAndNumberThenSum() {
86+
verifyMathFunction(conf, "$.numbers.append(\"0\", \"11\").sum()", 55.0);
87+
}
88+
89+
@Test
90+
public void testErrantCloseBraceNegative() {
91+
try {
92+
using(conf).parse(this.NUMBER_SERIES).read("$.numbers.append(0, 1, 2}).avg()");
93+
assert(false);
94+
}
95+
catch (Exception e) {
96+
assertTrue(e.getMessage().startsWith("Unexpected close brace"));
97+
}
98+
}
99+
100+
@Test
101+
public void testErrantCloseBracketNegative() {
102+
try {
103+
using(conf).parse(this.NUMBER_SERIES).read("$.numbers.append(0, 1, 2]).avg()");
104+
assert(false);
105+
}
106+
catch (Exception e) {
107+
assertTrue(e.getMessage().startsWith("Unexpected close bracket"));
108+
}
109+
}
110+
111+
@Test
112+
public void testUnclosedFunctionCallNegative() {
113+
try {
114+
using(conf).parse(this.NUMBER_SERIES).read("$.numbers.append(0, 1, 2");
115+
assert(false);
116+
}
117+
catch (Exception e) {
118+
assertTrue(e.getMessage().startsWith("Arguments to function: 'append'"));
119+
}
120+
}
121+
77122
}

0 commit comments

Comments
 (0)