This is an automated email from the ASF dual-hosted git repository. rombert pushed a commit to annotated tag org.apache.sling.xss-1.0.0 in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-xss.git
commit bc82200b533f02b27a2087cec17c193e80f32768 Author: Felix Meschberger <[email protected]> AuthorDate: Thu Dec 11 09:15:04 2014 +0000 SLING-4236 Clarify XSSAPI with respect to null and empty input strings * Include patch by Radu Cotescu (thanks a lot) * Extend patch to getValid* and filterHtml methods * Leverage TestCase.assertEquals for result validation * Add more tests for empty and null input * Add LongValidationRule git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/contrib/extensions/xss@1644580 13f79535-47bb-0310-9956-ffa450edef68 --- pom.xml | 6 + src/main/java/org/apache/sling/xss/XSSAPI.java | 65 ++++++---- .../apache/sling/xss/impl/LongValidationRule.java | 114 ++++++++++++++++++ .../java/org/apache/sling/xss/impl/XSSAPIImpl.java | 127 ++++++++++--------- .../org/apache/sling/xss/impl/XSSAPIImplTest.java | 134 +++++++++++++++------ 5 files changed, 330 insertions(+), 116 deletions(-) diff --git a/pom.xml b/pom.xml index b1e95fb..af111f4 100644 --- a/pom.xml +++ b/pom.xml @@ -265,6 +265,12 @@ <scope>provided</scope> </dependency> <dependency> + <groupId>com.google.code.findbugs</groupId> + <artifactId>jsr305</artifactId> + <version>2.0.0</version> + <scope>provided</scope> + </dependency> + <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <scope>test</scope> diff --git a/src/main/java/org/apache/sling/xss/XSSAPI.java b/src/main/java/org/apache/sling/xss/XSSAPI.java index 0e026b3..f9fc0a8 100644 --- a/src/main/java/org/apache/sling/xss/XSSAPI.java +++ b/src/main/java/org/apache/sling/xss/XSSAPI.java @@ -17,6 +17,9 @@ package org.apache.sling.xss; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + import org.apache.sling.api.SlingHttpServletRequest; import org.apache.sling.api.resource.ResourceResolver; @@ -42,33 +45,36 @@ public interface XSSAPI { /** * Validate a string which should contain an integer, returning a default value if the source is - * empty, can't be parsed, or contains XSS risks. + * {@code null}, empty, can't be parsed, or contains XSS risks. * * @param integer the source integer - * @param defaultValue a default value if the source can't be used + * @param defaultValue a default value if the source can't be used, is {@code null} or an empty string * @return a sanitized integer */ - public Integer getValidInteger(String integer, int defaultValue); + @Nullable + public Integer getValidInteger(@Nullable String integer, @Nullable int defaultValue); /** * Validate a string which should contain a long, returning a default value if the source is - * empty, can't be parsed, or contains XSS risks. + * {@code null}, empty, can't be parsed, or contains XSS risks. * * @param source the source long - * @param defaultValue a default value if the source can't be used + * @param defaultValue a default value if the source can't be used, is {@code null} or an empty string * @return a sanitized integer */ - public Long getValidLong(String source, long defaultValue); + @Nullable + public Long getValidLong(@Nullable String source, @Nullable long defaultValue); /** * Validate a string which should contain a dimension, returning a default value if the source is * empty, can't be parsed, or contains XSS risks. Allows integer dimensions and the keyword "auto". * * @param dimension the source dimension - * @param defaultValue a default value if the source can't be used + * @param defaultValue a default value if the source can't be used, is {@code null} or an empty string * @return a sanitized dimension */ - public String getValidDimension(String dimension, String defaultValue); + @Nullable + public String getValidDimension(@Nullable String dimension, @Nullable String defaultValue); /** * Sanitizes a URL for writing as an HTML href or src attribute value. @@ -76,27 +82,30 @@ public interface XSSAPI { * @param url the source URL * @return a sanitized URL (possibly empty) */ - public String getValidHref(String url); + @Nonnull + public String getValidHref(@Nullable String url); /** * Validate a Javascript token. The value must be either a single identifier, a literal number, * or a literal string. * * @param token the source token - * @param defaultValue a default value to use if the source doesn't meet validity constraints. + * @param defaultValue a default value to use if the source is {@code null}, an empty string, or doesn't meet validity constraints. * @return a string containing a single identifier, a literal number, or a literal string token */ - public String getValidJSToken(String token, String defaultValue); + @Nullable + public String getValidJSToken(@Nullable String token, @Nullable String defaultValue); /** * Validate a style/CSS token. Valid CSS tokens are specified at http://www.w3.org/TR/css3-syntax/ * * @param token the source token - * @param defaultValue a default value to use if the source doesn't meet validity constraints. + * @param defaultValue a default value to use if the source is {@code null}, an empty string, or doesn't meet validity constraints. * * @return a string containing sanitized style token */ - public String getValidStyleToken(String token, String defaultValue); + @Nullable + public String getValidStyleToken(@Nullable String token, @Nullable String defaultValue); /** * Validate a CSS color value. Color values as specified at http://www.w3.org/TR/css3-color/#colorunits @@ -104,10 +113,11 @@ public interface XSSAPI { * vulnerable constructs include url(...), expression(...), and anything with a semicolon. * * @param color the color value to be used. - * @param defaultColor a default value to use if the input color value doesn't meet validity constraints. + * @param defaultColor a default value to use if the input color value is {@code null}, an empty string, doesn't meet validity constraints. * @return a string a css color value. */ - public String getValidCSSColor(String color, String defaultColor); + @Nullable + public String getValidCSSColor(@Nullable String color, @Nullable String defaultColor); // ============================================================================================= // ENCODERS @@ -120,7 +130,8 @@ public interface XSSAPI { * @param source the input to encode * @return an encoded version of the source */ - public String encodeForHTML(String source); + @Nullable + public String encodeForHTML(@Nullable String source); /** * Encodes a source string for writing to an HTML attribute value. @@ -129,7 +140,8 @@ public interface XSSAPI { * @param source the input to encode * @return an encoded version of the source */ - public String encodeForHTMLAttr(String source); + @Nullable + public String encodeForHTMLAttr(@Nullable String source); /** * Encodes a source string for XML element content. @@ -138,7 +150,8 @@ public interface XSSAPI { * @param source the input to encode * @return an encoded version of the source */ - public String encodeForXML(String source); + @Nullable + public String encodeForXML(@Nullable String source); /** * Encodes a source string for writing to an XML attribute value. @@ -146,7 +159,8 @@ public interface XSSAPI { * @param source the input to encode * @return an encoded version of the source */ - public String encodeForXMLAttr(String source); + @Nullable + public String encodeForXMLAttr(@Nullable String source); /** * Encodes a source string for writing to JavaScript string content. @@ -156,17 +170,19 @@ public interface XSSAPI { * @param source the input to encode * @return an encoded version of the source */ - public String encodeForJSString(String source); + @Nullable + public String encodeForJSString(@Nullable String source); /** - * Encodes a souce string for writing to CSS string content. + * Encodes a source string for writing to CSS string content. * DO NOT USE FOR WRITING OUT ARBITRARY CSS TOKENS; YOU MUST USE A VALIDATOR FOR THAT! * (Encoding only ensures the source string cannot break out of its context.) * * @param source the input to encode * @return an encoded version of the source */ - public String encodeForCSSString(String source); + @Nullable + public String encodeForCSSString(@Nullable String source); // ============================================================================================= @@ -178,9 +194,10 @@ public interface XSSAPI { * effect for HTML output (see the XSSFilter service for details). * * @param source a string containing the source HTML - * @return a string containing the sanitized HTML + * @return a string containing the sanitized HTML which may be an empty string if {@code source} is {@code null} or empty */ - public String filterHTML(String source); + @Nonnull + public String filterHTML(@Nullable String source); // ============================================================================================= diff --git a/src/main/java/org/apache/sling/xss/impl/LongValidationRule.java b/src/main/java/org/apache/sling/xss/impl/LongValidationRule.java new file mode 100644 index 0000000..7d258d9 --- /dev/null +++ b/src/main/java/org/apache/sling/xss/impl/LongValidationRule.java @@ -0,0 +1,114 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/** + * OWASP Enterprise Security API (ESAPI) + * + * This file is part of the Open Web Application Security Project (OWASP) + * Enterprise Security API (ESAPI) project. For details, please see + * <a href="http://www.owasp.org/index.php/ESAPI">http://www.owasp.org/index.php/ESAPI</a>. + * + * Copyright (c) 2007 - The OWASP Foundation + * + * The ESAPI is published by OWASP under the BSD license. You should read and accept the + * LICENSE before you use, modify, and/or redistribute this software. + * + * @author Jeff Williams <a href="http://www.aspectsecurity.com">Aspect Security</a> + * @created 2007 + */ +package org.apache.sling.xss.impl; + +import org.apache.sling.xss.XSSAPI; +import org.owasp.esapi.Encoder; +import org.owasp.esapi.StringUtilities; +import org.owasp.esapi.errors.ValidationException; +import org.owasp.esapi.reference.validation.BaseValidationRule; + + +/** + * A validator performs syntax and possibly semantic validation of a single + * piece of data from an untrusted source. + * <p> + * This class is derived from the OWASP ESAPI {@code LongValidationRule} + * class to support validation of {@code long} values. + * + * @see XSSAPI#getValidLong(String, long) + * @see org.owasp.esapi.Validator + * @see org.owasp.esapi.reference.validation.IntegerValidationRule + */ +class LongValidationRule extends BaseValidationRule { + + private final long minValue; + private final long maxValue; + + LongValidationRule( String typeName, Encoder encoder, long minValue, long maxValue ) { + super( typeName, encoder ); + this.minValue = minValue; + this.maxValue = maxValue; + } + + public Long getValid( String context, String input ) throws ValidationException { + return safelyParse(context, input); + } + + private Long safelyParse(String context, String input) throws ValidationException { + // do not allow empty Strings such as " " - so trim to ensure + // isEmpty catches " " + if (input != null) input = input.trim(); + + if ( StringUtilities.isEmpty(input) ) { + if (allowNull) { + return null; + } + throw new ValidationException( context + ": Input number required", "Input number required: context=" + context + ", input=" + input, context ); + } + + // canonicalize + String canonical = encoder.canonicalize( input ); + + if (minValue > maxValue) { + throw new ValidationException( context + ": Invalid number input: context", "Validation parameter error for number: maxValue ( " + maxValue + ") must be greater than minValue ( " + minValue + ") for " + context, context ); + } + + // validate min and max + try { + long i = Long.valueOf(canonical); + if (i < minValue) { + throw new ValidationException( "Invalid number input must be between " + minValue + " and " + maxValue + ": context=" + context, "Invalid number input must be between " + minValue + " and " + maxValue + ": context=" + context + ", input=" + input, context ); + } + if (i > maxValue) { + throw new ValidationException( "Invalid number input must be between " + minValue + " and " + maxValue + ": context=" + context, "Invalid number input must be between " + minValue + " and " + maxValue + ": context=" + context + ", input=" + input, context ); + } + return i; + } catch (NumberFormatException e) { + throw new ValidationException( context + ": Invalid number input", "Invalid number input format: context=" + context + ", input=" + input, e, context); + } + } + + @Override + public Long sanitize( String context, String input ) { + Long toReturn = Long.valueOf( 0 ); + try { + toReturn = safelyParse(context, input); + } catch (ValidationException e ) { + // do nothing + } + return toReturn; + } +} \ No newline at end of file diff --git a/src/main/java/org/apache/sling/xss/impl/XSSAPIImpl.java b/src/main/java/org/apache/sling/xss/impl/XSSAPIImpl.java index e01aff1..bddab78 100644 --- a/src/main/java/org/apache/sling/xss/impl/XSSAPIImpl.java +++ b/src/main/java/org/apache/sling/xss/impl/XSSAPIImpl.java @@ -44,50 +44,60 @@ public class XSSAPIImpl implements XSSAPI { private Validator validator = ESAPI.validator(); + private static final Pattern PATTERN_AUTO_DIMENSION = Pattern.compile("['\"]?auto['\"]?"); + /** * @see org.apache.sling.xss.XSSAPI#getValidInteger(String, int) */ public Integer getValidInteger(String integer, int defaultValue) { - try { - if (integer == null || integer.length() == 0) { - return defaultValue; - } else { + if (integer != null && integer.length() > 0) { + try { return validator.getValidInteger("XSS", integer, -2000000000, 2000000000, false); + } catch (Exception e) { + // ignore } - } catch (Exception e) { - return defaultValue; } + + // fall through to default if empty, null, or validation failure + return defaultValue; } /** * @see org.apache.sling.xss.XSSAPI#getValidLong(String, long) */ public Long getValidLong(String source, long defaultValue) { - try { - if (source == null || source.length() == 0) { - return defaultValue; - } else { - return validator.getValidNumber("XSS", source, -9000000000000000000L, 9000000000000000000L, false).longValue(); + if (source != null && source.length() > 0) { + try { + LongValidationRule ivr = new LongValidationRule( "number", ESAPI.encoder(), -9000000000000000000L, 9000000000000000000L ); + ivr.setAllowNull(false); + return ivr.getValid("XSS", source); + } catch (Exception e) { + // ignore } - } catch (Exception e) { - return defaultValue; } + + // fall through to default if empty, null, or validation failure + return defaultValue; } /** * @see org.apache.sling.xss.XSSAPI#getValidDimension(String, String) */ public String getValidDimension(String dimension, String defaultValue) { - try { - if (dimension == null || dimension.length() == 0) { - return defaultValue; - } else if (dimension.matches("['\"]?auto['\"]?")) { + if (dimension != null && dimension.length() > 0) { + if (PATTERN_AUTO_DIMENSION.matcher(dimension).matches()) { return "\"auto\""; } - return validator.getValidInteger("XSS", dimension, -10000, 10000, false).toString(); - } catch (Exception e) { - return defaultValue; + + try { + return validator.getValidInteger("XSS", dimension, -10000, 10000, false).toString(); + } catch (Exception e) { + // ignore + } } + + // fall through to default if empty, null, or validation failure + return defaultValue; } private static final String LINK_PREFIX = "<a href=\""; @@ -147,7 +157,7 @@ public class XSSAPIImpl implements XSSAPI { * @see org.apache.sling.xss.XSSAPI#getValidHref(String) */ public String getValidHref(final String url) { - try { + if (url != null && url.length() > 0) { // Percent-encode characters that are not allowed in unquoted // HTML attributes: ", ', >, <, ` and space. We don't encode = // since this would break links with query parameters. @@ -163,31 +173,32 @@ public class XSSAPIImpl implements XSSAPI { final String safeHtml = xssFilter.filter(ProtectionContext.HTML_HTML_CONTENT, testHtml); // if the xssFilter didn't like the input string we just return "" // otherwise we return the mangled url without encoding - if (!safeHtml.equals(testHtml)) { - return ""; - } else { + if (safeHtml.equals(testHtml)) { return mangleNamespaces(encodedUrl); } - } catch (final NullPointerException e) { - // ProtectionContext was null - simply return an empty string - return ""; } + + // fall through to empty string + return ""; } /** * @see org.apache.sling.xss.XSSAPI#getValidJSToken(String, String) */ public String getValidJSToken(String token, String defaultValue) { - token = token.trim(); - String q = token.substring(0, 1); - if (q.matches("['\"]") && token.endsWith(q)) { - String literal = token.substring(1, token.length() - 1); - return q + encodeForJSString(literal) + q; - } else if (token.matches("[0-9a-zA-Z_$][0-9a-zA-Z_$.]*")) { - return token; - } else { - return defaultValue; + if (token != null && token.length() > 0) { + token = token.trim(); + String q = token.substring(0, 1); + if (q.matches("['\"]") && token.endsWith(q)) { + String literal = token.substring(1, token.length() - 1); + return q + encodeForJSString(literal) + q; + } else if (token.matches("[0-9a-zA-Z_$][0-9a-zA-Z_$.]*")) { + return token; + } } + + // fall through to default value + return defaultValue; } private static final String NON_ASCII = "\\x00\\x08\\x0B\\x0C\\x0E-\\x1F"; @@ -224,29 +235,33 @@ public class XSSAPIImpl implements XSSAPI { * @see org.apache.sling.xss.XSSAPI#getValidStyleToken(String, String) */ public String getValidStyleToken(String token, String defaultValue) { - if (token.matches(CSS_TOKEN)) { + if (token != null && token.length() > 0 && token.matches(CSS_TOKEN)) { return token; } + return defaultValue; - } + } /** * @see org.apache.sling.xss.XSSAPI#getValidCSSColor(String, String) */ public String getValidCSSColor(String color, String defaultColor) { - color = color.trim(); - /* - * Avoid security implications by including only the characters required to specify colors in hex - * or functional notation. Critical characters disallowed: x (as in expression(...)), - * u (as in url(...)) and semi colon (as in escaping the context of the color value). - */ - if (color.matches("(?i)[#a-fghlrs(+0-9-.%,) \\t\\n\\x0B\\f\\r]+")) { - return color; - } - // named color values - if (color.matches("(?i)[a-zA-Z \\t\\n\\x0B\\f\\r]+")) { - return color; + if (color != null && color.length() > 0) { + color = color.trim(); + /* + * Avoid security implications by including only the characters required to specify colors in hex + * or functional notation. Critical characters disallowed: x (as in expression(...)), + * u (as in url(...)) and semi colon (as in escaping the context of the color value). + */ + if (color.matches("(?i)[#a-fghlrs(+0-9-.%,) \\t\\n\\x0B\\f\\r]+")) { + return color; + } + // named color values + if (color.matches("(?i)[a-zA-Z \\t\\n\\x0B\\f\\r]+")) { + return color; + } } + return defaultColor; } @@ -258,42 +273,42 @@ public class XSSAPIImpl implements XSSAPI { * @see org.apache.sling.xss.XSSAPI#encodeForHTML(String) */ public String encodeForHTML(String source) { - return Encode.forHtml(source); + return source == null ? null : Encode.forHtml(source); } /** * @see org.apache.sling.xss.XSSAPI#encodeForHTMLAttr(String) */ public String encodeForHTMLAttr(String source) { - return Encode.forHtmlAttribute(source); + return source == null ? null : Encode.forHtmlAttribute(source); } /** * @see org.apache.sling.xss.XSSAPI#encodeForXML(String) */ public String encodeForXML(String source) { - return Encode.forXml(source); + return source == null ? null : Encode.forXml(source); } /** * @see org.apache.sling.xss.XSSAPI#encodeForXMLAttr(String) */ public String encodeForXMLAttr(String source) { - return Encode.forXmlAttribute(source); + return source == null ? null : Encode.forXmlAttribute(source); } /** * @see org.apache.sling.xss.XSSAPI#encodeForJSString(String) */ public String encodeForJSString(String source) { - return Encode.forJavaScript(source); + return source == null ? null : Encode.forJavaScript(source); } /** * @see org.apache.sling.xss.XSSAPI#encodeForCSSString(String) */ public String encodeForCSSString(String source) { - return Encode.forCssString(source); + return source == null ? null : Encode.forCssString(source); } // ============================================================================================= diff --git a/src/test/java/org/apache/sling/xss/impl/XSSAPIImplTest.java b/src/test/java/org/apache/sling/xss/impl/XSSAPIImplTest.java index 1367810..a826b06 100644 --- a/src/test/java/org/apache/sling/xss/impl/XSSAPIImplTest.java +++ b/src/test/java/org/apache/sling/xss/impl/XSSAPIImplTest.java @@ -26,6 +26,8 @@ import java.io.InputStream; import java.lang.reflect.Field; import java.util.Map; +import junit.framework.TestCase; + import org.apache.sling.xss.XSSAPI; import org.apache.sling.api.SlingHttpServletRequest; import org.apache.sling.api.resource.ResourceResolver; @@ -87,6 +89,7 @@ public class XSSAPIImplTest { String[][] testData = { // Source Expected Result // + {null, null}, {"simple", "simple"}, {"<script>", "<script>"}, @@ -100,10 +103,29 @@ public class XSSAPIImplTest { String source = aTestData[0]; String expected = aTestData[1]; - String result = xssAPI.encodeForHTML(source); - if (!result.equals(expected)) { - fail("HTML Encoding '" + source + "', expecting '" + expected + "', but got '" + result + "'"); - } + TestCase.assertEquals("HTML Encoding '" + source + "'", expected, xssAPI.encodeForHTML(source)); + } + } + + @Test + public void TestEncodeForHTMLAttr() { + String[][] testData = { + // Source Expected Result + // + {null, null}, + {"simple", "simple"}, + + {"<script>", "<script>"}, + {"\" <script>alert('pwned');</script>", "" <script>alert('pwned');</script>"}, + {"günter", "günter"}, + {"\u30e9\u30c9\u30af\u30ea\u30d5\u3001\u30de\u30e9\u30bd\u30f3\u4e94\u8f2a\u4ee3\u8868\u306b1\u4e07m\u51fa\u5834\u306b\u3082\u542b\u307f", "\u30e9\u30c9\u30af\u30ea\u30d5\u3001\u30de\u30e9\u30bd\u30f3\u4e94\u8f2a\u4ee3\u8868\u306b1\u4e07m\u51fa\u5834\u306b\u3082\u542b\u307f"} + }; + + for (String[] aTestData : testData) { + String source = aTestData[0]; + String expected = aTestData[1]; + + TestCase.assertEquals("HTML Encoding '" + source + "'", expected, xssAPI.encodeForHTMLAttr(source)); } } @@ -112,6 +134,7 @@ public class XSSAPIImplTest { String[][] testData = { // Source Expected Result // + {null, null}, {"simple", "simple"}, {"<script>", "<script>"}, @@ -124,10 +147,30 @@ public class XSSAPIImplTest { String source = aTestData[0]; String expected = aTestData[1]; - String result = xssAPI.encodeForXML(source); - if (!result.equals(expected)) { - fail("XML Encoding '" + source + "', expecting '" + expected + "', but got '" + result + "'"); - } + TestCase.assertEquals("XML Encoding '" + source + "'", expected, xssAPI.encodeForXML(source)); + } + } + + @Test + public void TestEncodeForXMLAttr() { + String[][] testData = { + // Source Expected Result + // + {null, null}, + {"simple", "simple"}, + + {"<script>", "<script>"}, + {"<b>", "<b>"}, + + {"günter", "günter"}, + {"\"xss:expression(alert('XSS'))", ""xss:expression(alert('XSS'))"} + }; + + for (String[] aTestData : testData) { + String source = aTestData[0]; + String expected = aTestData[1]; + + TestCase.assertEquals("XML Encoding '" + source + "'", expected, xssAPI.encodeForXMLAttr(source)); } } @@ -135,6 +178,8 @@ public class XSSAPIImplTest { public void TestFilterHTML() { String[][] testData = { // Source Expected Result + {null, ""}, + {"", ""}, {"simple", "simple"}, {"<script>ugly</script>", ""}, @@ -160,10 +205,7 @@ public class XSSAPIImplTest { String source = aTestData[0]; String expected = aTestData[1]; - String result = xssAPI.filterHTML(source); - if (!result.equals(expected)) { - fail("Filtering '" + source + "', expecting '" + expected + "', but got '" + result + "'"); - } + TestCase.assertEquals("Filtering '" + source + "'", expected, xssAPI.filterHTML(source)); } } @@ -172,6 +214,8 @@ public class XSSAPIImplTest { String[][] testData = { // Href Expected Result // + {null, ""}, + {"", ""}, {"simple", "simple"}, {"../parent", "../parent"}, @@ -217,10 +261,7 @@ public class XSSAPIImplTest { String href = aTestData[0]; String expected = aTestData[1]; - String result = xssAPI.getValidHref(href); - if (!result.equals(expected)) { - fail("Requested '" + href + "', expecting '" + expected + "', but got '" + result + "'"); - } + TestCase.assertEquals("Requested '" + href + "'", expected, xssAPI.getValidHref(href)); } } @@ -229,6 +270,7 @@ public class XSSAPIImplTest { String[][] testData = { // Source Expected Result // + {null, "123"}, {"100", "100"}, {"0", "0"}, @@ -240,12 +282,32 @@ public class XSSAPIImplTest { for (String[] aTestData : testData) { String source = aTestData[0]; - int expected = new Integer(aTestData[1]); + Integer expected = (aTestData[1] != null) ? new Integer(aTestData[1]) : null; - int result = xssAPI.getValidInteger(source, 123); - if (result != expected) { - fail("Validating integer '" + source + "', expecting '" + expected + "', but got '" + result + "'"); - } + TestCase.assertEquals("Validating integer '" + source + "'", expected, xssAPI.getValidInteger(source, 123)); + } + } + + @Test + public void TestGetValidLong() { + String[][] testData = { + // Source Expected Result + // + {null, "123"}, + {"100", "100"}, + {"0", "0"}, + + {"junk", "123"}, + {"100.5", "123"}, + {"", "123"}, + {"null", "123"} + }; + + for (String[] aTestData : testData) { + String source = aTestData[0]; + Long expected = (aTestData[1] != null) ? new Long(aTestData[1]) : null; + + TestCase.assertEquals("Validating long '" + source + "'", expected, xssAPI.getValidLong(source, 123)); } } @@ -254,6 +316,8 @@ public class XSSAPIImplTest { String[][] testData = { // Source Expected Result // + {null, "123"}, + {"", "123"}, {"100", "100"}, {"0", "0"}, @@ -273,10 +337,7 @@ public class XSSAPIImplTest { String source = aTestData[0]; String expected = aTestData[1]; - String result = xssAPI.getValidDimension(source, "123"); - if (!result.equals(expected)) { - fail("Validating dimension '" + source + "', expecting '" + expected + "', but got '" + result + "'"); - } + TestCase.assertEquals("Validating dimension '" + source + "'", expected, xssAPI.getValidDimension(source, "123")); } } @@ -285,6 +346,7 @@ public class XSSAPIImplTest { String[][] testData = { // Source Expected Result // + {null, null}, {"simple", "simple"}, {"break\"out", "break\\x22out"}, @@ -297,10 +359,7 @@ public class XSSAPIImplTest { String source = aTestData[0]; String expected = aTestData[1]; - String result = xssAPI.encodeForJSString(source); - if (!result.equals(expected)) { - fail("Encoding '" + source + "', expecting '" + expected + "', but got '" + result + "'"); - } + TestCase.assertEquals("Encoding '" + source + "'", expected, xssAPI.encodeForJSString(source)); } } @@ -309,6 +368,8 @@ public class XSSAPIImplTest { String[][] testData = { // Source Expected Result // + {null, RUBBISH}, + {"", RUBBISH}, {"simple", "simple"}, {"clickstreamcloud.thingy", "clickstreamcloud.thingy"}, @@ -330,10 +391,7 @@ public class XSSAPIImplTest { String source = aTestData[0]; String expected = aTestData[1]; - String result = xssAPI.getValidJSToken(source, RUBBISH); - if (!result.equals(expected)) { - fail("Validating Javascript token '" + source + "', expecting '" + expected + "', but got '" + result + "'"); - } + TestCase.assertEquals("Validating Javascript token '" + source + "'", expected, xssAPI.getValidJSToken(source, RUBBISH)); } } @@ -341,6 +399,7 @@ public class XSSAPIImplTest { public void TestEncodeForCSSString() { String[][] testData = { // Source Expected result + {null, null}, {"test" , "test"}, {"\\" , "\\5c"}, {"'" , "\\27"}, @@ -352,9 +411,7 @@ public class XSSAPIImplTest { String expected = aTestData[1]; String result = xssAPI.encodeForCSSString(source); - if (!result.equals(expected)) { - fail("Encoding '" + source + "', expecting '" + expected + "', but got '" + result + "'"); - } + TestCase.assertEquals("Encoding '" + source + "'", expected, result); } } @@ -362,6 +419,8 @@ public class XSSAPIImplTest { public void TestGetValidStyleToken() { String[][] testData = { // Source Expected result + {null , RUBBISH}, + {"" , RUBBISH}, // CSS close {"}" , RUBBISH}, @@ -429,6 +488,9 @@ public class XSSAPIImplTest { String[][] testData = { // Source Expected Result // + {null, RUBBISH}, + {"", RUBBISH}, + {"rgb(0,+0,-0)", "rgb(0,+0,-0)"}, {"rgba ( 0\f%, 0%,\t0%,\n100%\r)", "rgba ( 0\f%, 0%,\t0%,\n100%\r)",}, -- To stop receiving notification emails like this one, please contact "[email protected]" <[email protected]>.
