Program: 23
Project: VUL4J
Buggy source:
//******************************************************************************* * 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: * 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. ******************************************************************************//package org.apache.sling.xss.impl;import java.io.StringReader;import java.util.regex.Matcher;import java.util.regex.Pattern;import javax.annotation.Nonnull;import javax.xml.parsers.SAXParser;import javax.xml.parsers.SAXParserFactory;import org.apache.felix.scr.annotations.Activate;import org.apache.felix.scr.annotations.Component;import org.apache.felix.scr.annotations.Deactivate;import org.apache.felix.scr.annotations.Reference;import org.apache.felix.scr.annotations.Service;import org.apache.sling.api.SlingHttpServletRequest;import org.apache.sling.api.resource.ResourceResolver;import org.apache.sling.commons.json.JSONArray;import org.apache.sling.commons.json.JSONException;import org.apache.sling.commons.json.JSONObject;import org.apache.sling.xss.ProtectionContext;import org.apache.sling.xss.XSSAPI;import org.apache.sling.xss.XSSFilter;import org.owasp.encoder.Encode;import org.owasp.esapi.ESAPI;import org.owasp.esapi.Validator;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.xml.sax.InputSource;import org.xml.sax.XMLReader;@Component@Service(value = XSSAPI.class)public class XSSAPIImpl implements XSSAPI {    private static final Logger LOGGER = LoggerFactory.getLogger(XSSAPIImpl.class);    @Reference    private XSSFilter xssFilter = null;    private Validator validator = ESAPI.validator();    private static final Pattern PATTERN_AUTO_DIMENSION = Pattern.compile("['\"]?auto['\"]?");    private SAXParserFactory factory;    @Activate    @SuppressWarnings("unused")    protected void activate() {        factory = SAXParserFactory.newInstance();        factory.setValidating(false);        factory.setNamespaceAware(true);    }    @Deactivate    @SuppressWarnings("unused")    protected void deactivate() {        factory = null;    }                //**     * @see org.apache.sling.xss.XSSAPI#getValidInteger(String, int)     *//    @Override    public Integer getValidInteger(String integer, int defaultValue) {        if (integer != null && integer.length() > 0) {            try {                return validator.getValidInteger("XSS", integer, -2000000000, 2000000000, false);            } catch (Exception e) {                            }        }                return defaultValue;    }    //**     * @see org.apache.sling.xss.XSSAPI#getValidLong(String, long)     *//    @Override    public Long getValidLong(String source, long defaultValue) {        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) {                            }        }                return defaultValue;    }    //**     * @see org.apache.sling.xss.XSSAPI#getValidDouble(String, double)     *//    @Override    public Double getValidDouble(String source, double defaultValue) {        if (source != null && source.length() > 0) {            try {                return validator.getValidDouble("XSS", source, 0d, Double.MAX_VALUE, false);            } catch (Exception e) {                            }        }                return defaultValue;    }    //**     * @see org.apache.sling.xss.XSSAPI#getValidDimension(String, String)     *//    @Override    public String getValidDimension(String dimension, String defaultValue) {        if (dimension != null && dimension.length() > 0) {            if (PATTERN_AUTO_DIMENSION.matcher(dimension).matches()) {                return "\"auto\"";            }            try {                return validator.getValidInteger("XSS", dimension, -10000, 10000, false).toString();            } catch (Exception e) {                            }        }                return defaultValue;    }    private static final String LINK_PREFIX = "<a href=\"";    private static final String LINK_SUFFIX = "\"><//a>";    private static final String MANGLE_NAMESPACE_OUT_SUFFIX = ":";    private static final String MANGLE_NAMESPACE_OUT = "//([^://]+):";    private static final Pattern MANGLE_NAMESPACE_PATTERN = Pattern.compile(MANGLE_NAMESPACE_OUT);    private static final String MANGLE_NAMESPACE_IN_SUFFIX = "_";    private static final String MANGLE_NAMESPACE_IN_PREFIX = "//_";    private static final String SCHEME_PATTERN = ":    private String mangleNamespaces(String absPath) {        if (absPath != null) {                        final int schemeIndex = absPath.indexOf(SCHEME_PATTERN);            final String manglePath;            final String prefix;            if (schemeIndex != -1) {                final int pathIndex = absPath.indexOf("//", schemeIndex + 3);                if (pathIndex != -1) {                    prefix = absPath.substring(0, pathIndex);                    manglePath = absPath.substring(pathIndex);                } else {                    prefix = absPath;                    manglePath = "";                }            } else {                prefix = "";                manglePath = absPath;            }            if (manglePath.contains(MANGLE_NAMESPACE_OUT_SUFFIX)) {                final Matcher m = MANGLE_NAMESPACE_PATTERN.matcher(manglePath);                final StringBuffer buf = new StringBuffer();                while (m.find()) {                    final String replacement = MANGLE_NAMESPACE_IN_PREFIX + m.group(1) + MANGLE_NAMESPACE_IN_SUFFIX;                    m.appendReplacement(buf, replacement);                }                m.appendTail(buf);                absPath = prefix + buf.toString();            }        }        return absPath;    }    //**     * @see org.apache.sling.xss.XSSAPI#getValidHref(String)     *//    @Override    @Nonnull    public String getValidHref(final String url) {        if (url != null && url.length() > 0) {                                                String encodedUrl = url.replaceAll("\"", "%22")                    .replaceAll("'", "%27")                    .replaceAll(">", "%3E")                    .replaceAll("<", "%3C")                    .replaceAll("`", "%60")                    .replaceAll(" ", "%20");            int qMarkIx = encodedUrl.indexOf('?');            if (qMarkIx > 0) {                encodedUrl = encodedUrl.substring(0, qMarkIx) + encodedUrl.substring(qMarkIx).replaceAll(":", "%3A");            }            encodedUrl = mangleNamespaces(encodedUrl);            if (xssFilter.isValidHref(encodedUrl)) {                return encodedUrl;            }        }                return "";    }    //**     * @see org.apache.sling.xss.XSSAPI#getValidJSToken(String, String)     *//    @Override    public String getValidJSToken(String token, String 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;            }        }                return defaultValue;    }    private static final String NON_ASCII = "\\x00\\x08\\x0B\\x0C\\x0E-\\x1F";    //** http:    private static final String NUMBER = "[+-]?[\\d]*[\\.]?[\\d]*(?:[e][+-]?\\d+)?";    //** http:    private static final String HEX_DIGITS = "#[0-9a-f]*";    //** http:    private static final String IDENTIFIER = "-?[a-z_" + NON_ASCII + "][\\w_\\-" + NON_ASCII + "]*";    //** http:    private static final String STRING = "\"(?:(?!javascript\\s?:)[^\"^\\\\^\\n]|(?:\\\\\"))*\"|'(?:(?!javascript\\s?:)[^'^\\\\^\\n]|(?:\\\\'))*'";    //** http:    private static final String DIMENSION = NUMBER + IDENTIFIER;    //** http:    private static final String PERCENT = NUMBER + "%";    //** http:    private static final String FUNCTION = IDENTIFIER + "\\((?:(?:" + NUMBER + ")|(?:" + IDENTIFIER + ")|(?:[\\s]*)|(?:,))*\\)";    //** http:    private static final String URL_UNQUOTED = "[^\"^'^\\(^\\)^[" + NON_ASCII + "]]*";    //** http:    private static final String URL = "url\\((?:(?:" + URL_UNQUOTED + ")|(?:" + STRING + "))\\)";    //** composite regular expression for style token validation *//    private static final String CSS_TOKEN = "(?i)"             + "(?:" + NUMBER + ")"            + "|(?:" + DIMENSION + ")"            + "|(?:" + PERCENT + ")"            + "|(?:" + HEX_DIGITS + ")"            + "|(?:" + IDENTIFIER + ")"            + "|(?:" + STRING + ")"            + "|(?:" + FUNCTION + ")"            + "|(?:" + URL + ")";    //**     * @see org.apache.sling.xss.XSSAPI#getValidStyleToken(String, String)     *//    @Override    public String getValidStyleToken(String token, String defaultValue) {        if (token != null && token.length() > 0 && token.matches(CSS_TOKEN)) {            return token;        }        return defaultValue;   }    //**     * @see org.apache.sling.xss.XSSAPI#getValidCSSColor(String, String)     *//    @Override    public String getValidCSSColor(String color, String defaultColor) {        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;            }                        if (color.matches("(?i)[a-zA-Z \\t\\n\\x0B\\f\\r]+")) {                return color;            }        }        return defaultColor;    }    //**     * @see org.apache.sling.xss.XSSAPI#getValidMultiLineComment(String, String)     *//    @Override    public String getValidMultiLineComment(String comment, String defaultComment) {        if (comment != null && !comment.contains("*//")) {            return comment;        }        return defaultComment;    }    //**     * @see org.apache.sling.xss.XSSAPI#getValidJSON(String, String)     *//    @Override    public String getValidJSON(String json, String defaultJson) {        if (json == null) {            return getValidJSON(defaultJson, "");        }        json = json.trim();        if ("".equals(json)) {            return "";        }        int curlyIx = json.indexOf("{");        int straightIx = json.indexOf("[");        if (curlyIx >= 0 && (curlyIx < straightIx || straightIx < 0)) {            try {                JSONObject obj = new JSONObject(json);                return obj.toString();            } catch (JSONException e) {                LOGGER.debug("JSON validation failed: " + e.getMessage(), e);            }        } else {            try {                JSONArray arr = new JSONArray(json);                return arr.toString();            } catch (JSONException e) {                LOGGER.debug("JSON validation failed: " + e.getMessage(), e);            }        }        return getValidJSON(defaultJson, "");    }    //**     * @see org.apache.sling.xss.XSSAPI#getValidXML(String, String)     *//    @Override    public String getValidXML(String xml, String defaultXml) {        if (xml == null) {            return getValidXML(defaultXml, "");        }        xml = xml.trim();        if ("".equals(xml)) {            return "";        }        try {            SAXParser parser = factory.newSAXParser();            XMLReader reader = parser.getXMLReader();            reader.parse(new InputSource(new StringReader(xml)));            return xml;        } catch (Exception e) {            LOGGER.debug("XML validation failed: " + e.getMessage(), e);        }        return getValidXML(defaultXml, "");    }                //**     * @see org.apache.sling.xss.XSSAPI#encodeForHTML(String)     *//    @Override    public String encodeForHTML(String source) {        return source == null ? null : Encode.forHtml(source);    }    //**     * @see org.apache.sling.xss.XSSAPI#encodeForHTMLAttr(String)     *//    @Override    public String encodeForHTMLAttr(String source) {        return source == null ? null : Encode.forHtmlAttribute(source);    }    //**     * @see org.apache.sling.xss.XSSAPI#encodeForXML(String)     *//    @Override    public String encodeForXML(String source) {        return source == null ? null : Encode.forXml(source);    }    //**     * @see org.apache.sling.xss.XSSAPI#encodeForXMLAttr(String)     *//    @Override    public String encodeForXMLAttr(String source) {        return source == null ? null : Encode.forXmlAttribute(source);    }    //**     * @see org.apache.sling.xss.XSSAPI#encodeForJSString(String)     *//    @Override    public String encodeForJSString(String source) {       <START_BUG> return source == null ? null : Encode.forJavaScriptSource(source);<END_BUG>    }    //**     * @see org.apache.sling.xss.XSSAPI#encodeForCSSString(String)     *//    @Override    public String encodeForCSSString(String source) {        return source == null ? null : Encode.forCssString(source);    }                //**     * @see org.apache.sling.xss.XSSAPI#filterHTML(String)     *//    @Override    @Nonnull    public String filterHTML(String source) {        return xssFilter.filter(ProtectionContext.HTML_HTML_CONTENT, source);    }                //**     * @see org.apache.sling.xss.XSSAPI#getRequestSpecificAPI(org.apache.sling.api.SlingHttpServletRequest)     *//    @Override    public XSSAPI getRequestSpecificAPI(final SlingHttpServletRequest request) {        return this;    }    //**     * @see org.apache.sling.xss.XSSAPI#getResourceResolverSpecificAPI(org.apache.sling.api.resource.ResourceResolver)     *//    @Override    public XSSAPI getResourceResolverSpecificAPI(final ResourceResolver resourceResolver) {        return this;    }}}


Fixed version (ground truth):
return source == null ? null : Encode.forJavaScript(source).replace("\\-", "\\u002D");