View | Details | Raw Unified | Return to bug 62273
Collapse All | Expand All

(-)java/org/apache/coyote/http11/Http11InputBuffer.java (-1 / +2 lines)
Lines 456-462 Link Here
456
                    end = pos;
456
                    end = pos;
457
                } else if (chr == Constants.QUESTION && parsingRequestLineQPos == -1) {
457
                } else if (chr == Constants.QUESTION && parsingRequestLineQPos == -1) {
458
                    parsingRequestLineQPos = pos;
458
                    parsingRequestLineQPos = pos;
459
                } else if (HttpParser.isNotRequestTarget(chr)) {
459
                } else if ((parsingRequestLineQPos == -1 && HttpParser.isNotRequestTarget(chr))
460
                        || (parsingRequestLineQPos >= 0 && HttpParser.isNotQuery(chr))) {
460
                    throw new IllegalArgumentException(sm.getString("iib.invalidRequestTarget"));
461
                    throw new IllegalArgumentException(sm.getString("iib.invalidRequestTarget"));
461
                }
462
                }
462
            }
463
            }
(-)java/org/apache/tomcat/util/http/parser/HttpParser.java (-7 / +39 lines)
Lines 38-48 Link Here
38
38
39
    private static final int ARRAY_SIZE = 128;
39
    private static final int ARRAY_SIZE = 128;
40
40
41
    private static final boolean USE_URL_LIVING_STANDARD =
42
            Boolean.getBoolean("org.apache.tomcat.util.http.parser.HttpParser.USE_URL_LIVING_STANDARD");
43
41
    private static final boolean[] IS_CONTROL = new boolean[ARRAY_SIZE];
44
    private static final boolean[] IS_CONTROL = new boolean[ARRAY_SIZE];
42
    private static final boolean[] IS_SEPARATOR = new boolean[ARRAY_SIZE];
45
    private static final boolean[] IS_SEPARATOR = new boolean[ARRAY_SIZE];
43
    private static final boolean[] IS_TOKEN = new boolean[ARRAY_SIZE];
46
    private static final boolean[] IS_TOKEN = new boolean[ARRAY_SIZE];
44
    private static final boolean[] IS_HEX = new boolean[ARRAY_SIZE];
47
    private static final boolean[] IS_HEX = new boolean[ARRAY_SIZE];
45
    private static final boolean[] IS_NOT_REQUEST_TARGET = new boolean[ARRAY_SIZE];
48
    private static final boolean[] IS_NOT_REQUEST_TARGET = new boolean[ARRAY_SIZE];
49
    private static final boolean[] IS_NOT_QUERY = new boolean[ARRAY_SIZE];
46
    private static final boolean[] IS_HTTP_PROTOCOL = new boolean[ARRAY_SIZE];
50
    private static final boolean[] IS_HTTP_PROTOCOL = new boolean[ARRAY_SIZE];
47
    private static final boolean[] IS_ALPHA = new boolean[ARRAY_SIZE];
51
    private static final boolean[] IS_ALPHA = new boolean[ARRAY_SIZE];
48
    private static final boolean[] IS_NUMERIC = new boolean[ARRAY_SIZE];
52
    private static final boolean[] IS_NUMERIC = new boolean[ARRAY_SIZE];
Lines 72-84 Link Here
72
                IS_HEX[i] = true;
76
                IS_HEX[i] = true;
73
            }
77
            }
74
78
75
            // Not valid for request target.
79
            // Not valid for request target and query.
76
            // Combination of multiple rules from RFC7230 and RFC 3986. Must be
80
            if (USE_URL_LIVING_STANDARD) {
77
            // ASCII, no controls plus a few additional characters excluded
81
                // This complies with the URL living standard: https://url.spec.whatwg.org/#query-state
78
            if (IS_CONTROL[i] || i > 127 ||
82
                // If byte is less than 0x21 (!), greater than 0x7E (~), or is 0x22 ("), 0x23 (#), 0x3C (<), or 0x3E (>), append byte, percent encoded, to url’s query.
79
                    i == ' ' || i == '\"' || i == '#' || i == '<' || i == '>' || i == '\\' ||
83
                if (IS_CONTROL[i] || i > 127 ||
80
                    i == '^' || i == '`'  || i == '{' || i == '|' || i == '}') {
84
                        i == ' ' || i == '\"' || i == '#' || i == '<' || i == '>') {
81
                IS_NOT_REQUEST_TARGET[i] = true;
85
                    IS_NOT_QUERY[i] = true;
86
                }
87
                // The C0 control percent-encode set are the C0 controls and all code points greater than U+007E (~).
88
                // The fragment percent-encode set is the C0 control percent-encode set and U+0020 SPACE, U+0022 ("), U+003C (<), U+003E (>), and U+0060 (`).
89
                // The path percent-encode set is the fragment percent-encode set and U+0023 (#), U+003F (?), U+007B ({), and U+007D (}).
90
                if (IS_CONTROL[i] || i > 127 ||
91
                        i == ' ' || i == '\"' || i == '#' || i == '<' || i == '>' ||
92
                        i == '`'  || i == '{' || i == '}') {
93
                    IS_NOT_REQUEST_TARGET[i] = true;
94
                }
95
            } else {
96
                // Combination of multiple rules from RFC7230 and RFC 3986. Must be
97
                // ASCII, no controls plus a few additional characters excluded
98
                if (IS_CONTROL[i] || i > 127 ||
99
                        i == ' ' || i == '\"' || i == '#' || i == '<' || i == '>' || i == '\\' ||
100
                        i == '^' || i == '`'  || i == '{' || i == '|' || i == '}') {
101
                    IS_NOT_REQUEST_TARGET[i] = true;
102
                    IS_NOT_QUERY[i] = true;
103
                }
82
            }
104
            }
83
105
84
            // Not valid for HTTP protocol
106
            // Not valid for HTTP protocol
Lines 163-168 Link Here
163
    }
185
    }
164
186
165
187
188
    public static boolean isNotQuery(int c) {
189
        // Fast for valid query characters, slower for some incorrect ones
190
        try {
191
            return IS_NOT_QUERY[c];
192
        } catch (ArrayIndexOutOfBoundsException ex) {
193
            return true;
194
        }
195
    }
196
197
166
    public static boolean isHttpProtocol(int c) {
198
    public static boolean isHttpProtocol(int c) {
167
        // Fast for valid HTTP protocol characters, slower for some incorrect
199
        // Fast for valid HTTP protocol characters, slower for some incorrect
168
        // ones
200
        // ones
(-)java/org/apache/tomcat/util/net/TLSClientHelloExtractor.java (-1 / +1 lines)
Lines 271-277 Link Here
271
271
272
        // Read the target
272
        // Read the target
273
        while (chr != ' ' && chr != '\t') {
273
        while (chr != ' ' && chr != '\t') {
274
            if (HttpParser.isNotRequestTarget(chr) || !bb.hasRemaining()) {
274
            if (HttpParser.isNotQuery(chr) || !bb.hasRemaining()) {
275
                return false;
275
                return false;
276
            }
276
            }
277
            chr = bb.get();
277
            chr = bb.get();

Return to bug 62273