SLING-10342: The recursion selector value for the JsonRenderServlet s… (#7)
* SLING-10342: The recursion selector value for the JsonRenderServlet should be limited to real numbers
diff --git a/src/main/java/org/apache/sling/servlets/get/impl/helpers/JsonRenderer.java b/src/main/java/org/apache/sling/servlets/get/impl/helpers/JsonRenderer.java
index 975f520..b1648c4 100644
--- a/src/main/java/org/apache/sling/servlets/get/impl/helpers/JsonRenderer.java
+++ b/src/main/java/org/apache/sling/servlets/get/impl/helpers/JsonRenderer.java
@@ -18,12 +18,12 @@
import java.io.IOException;
import java.io.StringWriter;
+import java.math.BigInteger;
import javax.json.Json;
import javax.json.stream.JsonGenerator;
import javax.servlet.http.HttpServletResponse;
-import org.apache.commons.lang3.StringUtils;
import org.apache.sling.api.SlingException;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
@@ -160,14 +160,11 @@
maxRecursionLevels = -1;
} else {
try {
- maxRecursionLevels = Integer.parseInt(level);
+ maxRecursionLevels = parseRecursionLevel(level);
+ } catch (ArithmeticException ae) {
+ maxRecursionLevels = -1;
} catch (NumberFormatException nfe) {
- //SLING-2324
- if (StringUtils.isNumeric(level)){
- maxRecursionLevels = -1;
- } else {
- throw new IllegalArgumentException("Invalid recursion selector value '" + level + "'");
- }
+ throw new IllegalArgumentException("Invalid recursion selector value '" + level + "'");
}
}
}
@@ -176,6 +173,27 @@
}
/**
+ * parse the int value from an input string but only when the input is a real number and >= -1 i.e., [0-9]+ | -1
+ * @param input
+ * @return the value of the number as an int
+ * @throws ArithmeticException - if the input was a real positive number but didn't fit into an int
+ * @throws IllegalArgumentException - if the input was not a real number or out of bounds
+ */
+ private int parseRecursionLevel(String input) throws ArithmeticException, IllegalArgumentException {
+ if ("-1".equals(input)) {
+ return -1;
+ }
+ BigInteger inputNumber = new BigInteger(input);
+ if (!inputNumber.toString().equals(input)) {
+ throw new NumberFormatException("Not a real number string");
+ }
+ if (inputNumber.signum() == -1) {
+ throw new NumberFormatException("Not a valid negative number");
+ }
+ return inputNumber.intValueExact();
+ }
+
+ /**
* Checks if the provided request contains a certain selector.
* @param req the request
* @param selectorToCheck the selector
diff --git a/src/test/java/org/apache/sling/servlets/get/impl/helpers/JsonRendererTest.java b/src/test/java/org/apache/sling/servlets/get/impl/helpers/JsonRendererTest.java
index 720b483..b5ac6a0 100644
--- a/src/test/java/org/apache/sling/servlets/get/impl/helpers/JsonRendererTest.java
+++ b/src/test/java/org/apache/sling/servlets/get/impl/helpers/JsonRendererTest.java
@@ -99,6 +99,42 @@
assertTrue(jrs.isTidy(request));
}
+ @Test(expected = IllegalArgumentException.class)
+ public void testRecursionLevelNumeric() {
+ context.requestPathInfo().setSelectorString("᭙");
+ jrs.getMaxRecursionLevel(request);
+ }
+
+ @Test
+ public void testRecursionLevelOverflow() {
+ context.requestPathInfo().setSelectorString(Long.toString(((long) Integer.MAX_VALUE) + 1L));
+ assertEquals(-1, jrs.getMaxRecursionLevel(request));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testRecursionLevelUnderflow() {
+ context.requestPathInfo().setSelectorString(Long.toString(((long) Integer.MIN_VALUE) - 1L));
+ jrs.getMaxRecursionLevel(request);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testRecursionLevelNegativ() {
+ context.requestPathInfo().setSelectorString(Long.toString( - 2L));
+ jrs.getMaxRecursionLevel(request);
+ }
+
+ @Test
+ public void testRecursionLevelInfinity() {
+ context.requestPathInfo().setSelectorString("infinity");
+ assertEquals(-1, jrs.getMaxRecursionLevel(request));
+ }
+
+ @Test
+ public void testRecursionLevelInfinityNumeric() {
+ context.requestPathInfo().setSelectorString("-1");
+ assertEquals(-1, jrs.getMaxRecursionLevel(request));
+ }
+
@Test
public void testBadRequest() throws IOException {
context.requestPathInfo().setSelectorString("bad.selectors");