From 09e6e6b211d9479dbe6b91418b41af2822d671ca Mon Sep 17 00:00:00 2001 From: Lachlan Roberts Date: Tue, 18 Apr 2023 10:46:29 +1000 Subject: [PATCH] Issue #9554 - add javadoc for illegal vchar methods and move to HttpTokens Signed-off-by: Lachlan Roberts --- .../org/eclipse/jetty/http/HttpTokens.java | 55 +++++++++++++++++++ .../jetty/http/compression/Huffman.java | 43 --------------- .../http/compression/HuffmanDecoder.java | 5 +- .../http/compression/HuffmanEncoder.java | 6 +- .../jetty/http2/hpack/HpackEncoder.java | 4 +- 5 files changed, 64 insertions(+), 49 deletions(-) diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpTokens.java b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpTokens.java index 305c8b59fce..c492842d526 100644 --- a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpTokens.java +++ b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpTokens.java @@ -231,5 +231,60 @@ public class HttpTokens } } } + + /** + * This is used when decoding to not decode illegal characters based on RFC9110. + * CR, LF, or NUL are replaced with ' ', all other control and multibyte characters + * are replaced with '?'. If this is given a legal character the same value will be returned. + * + * @param c the character to test. + * @return the original character or the replacement character ' ' or '?'. + */ + public static char sanitizeFieldVchar(char c) + { + switch (c) + { + // A recipient of CR, LF, or NUL within a field value MUST either reject the message + // or replace each of those characters with SP before further processing + case '\r': + case '\n': + case 0x00: + return ' '; + + default: + if (c >= 256 || c < ' ') + return '?'; + } + + return c; + } + + /** + * This is used when decoding to not decode illegal characters based on RFC9110. + * CR, LF, or NUL are replaced with ' ', all other control and multibyte characters + * are replaced with '?'. If this is given a legal character the same value will be returned. + * + * @param i the character to test. + * @return the original character or the replacement character ' ' or '?'. + */ + public static int sanitizeFieldVchar(int i) + { + if (i > Character.MAX_VALUE) + return '?'; + return sanitizeFieldVchar((char)i); + } + + /** + * Checks whether this is an invalid VCHAR based on RFC9110. + * If this not a valid ISO-8859-1 character or a control character + * we say that it is illegal. + * + * @param c the character to test. + * @return true if this is invalid VCHAR. + */ + public static boolean isIllegalFieldVchar(char c) + { + return (c >= 256 || c < ' '); + } } diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/compression/Huffman.java b/jetty-http/src/main/java/org/eclipse/jetty/http/compression/Huffman.java index 354885b9b9e..6a1ad3d6789 100644 --- a/jetty-http/src/main/java/org/eclipse/jetty/http/compression/Huffman.java +++ b/jetty-http/src/main/java/org/eclipse/jetty/http/compression/Huffman.java @@ -346,47 +346,4 @@ public class Huffman } } } - - public static boolean isIllegalCharacter(char c) - { - return (c >= 256 || c < ' '); - } - - public static char getReplacementCharacter(char c) - { - switch (c) - { - // A recipient of CR, LF, or NUL within a field value MUST either reject the message - // or replace each of those characters with SP before further processing - case '\r': - case '\n': - case 0x00: - return ' '; - - default: - if (c >= 256 || c < ' ') - return '?'; - } - - return c; - } - - public static int getReplacementCharacter(int i) - { - switch (i) - { - // A recipient of CR, LF, or NUL within a field value MUST either reject the message - // or replace each of those characters with SP before further processing - case '\r': - case '\n': - case 0x00: - return ' '; - - default: - if (i >= 256 || i < ' ') - return '?'; - } - - return i; - } } diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/compression/HuffmanDecoder.java b/jetty-http/src/main/java/org/eclipse/jetty/http/compression/HuffmanDecoder.java index c0f19dc0851..cd1ed97fc37 100644 --- a/jetty-http/src/main/java/org/eclipse/jetty/http/compression/HuffmanDecoder.java +++ b/jetty-http/src/main/java/org/eclipse/jetty/http/compression/HuffmanDecoder.java @@ -15,6 +15,7 @@ package org.eclipse.jetty.http.compression; import java.nio.ByteBuffer; +import org.eclipse.jetty.http.HttpTokens; import org.eclipse.jetty.util.CharsetStringBuilder; import static org.eclipse.jetty.http.compression.Huffman.rowbits; @@ -72,7 +73,7 @@ public class HuffmanDecoder // terminal node int i = 0xFF & rowsym[_node]; - i = Huffman.getReplacementCharacter(i); + i = HttpTokens.sanitizeFieldVchar(i); _builder.append((byte)i); _bits -= rowbits[_node]; _node = 0; @@ -107,7 +108,7 @@ public class HuffmanDecoder } int i = 0xFF & rowsym[_node]; - i = Huffman.getReplacementCharacter(i); + i = HttpTokens.sanitizeFieldVchar(i); _builder.append((byte)i); _bits -= rowbits[_node]; _node = 0; diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/compression/HuffmanEncoder.java b/jetty-http/src/main/java/org/eclipse/jetty/http/compression/HuffmanEncoder.java index b6f05b5fc6b..13cb81b0492 100644 --- a/jetty-http/src/main/java/org/eclipse/jetty/http/compression/HuffmanEncoder.java +++ b/jetty-http/src/main/java/org/eclipse/jetty/http/compression/HuffmanEncoder.java @@ -15,6 +15,8 @@ package org.eclipse.jetty.http.compression; import java.nio.ByteBuffer; +import org.eclipse.jetty.http.HttpTokens; + import static org.eclipse.jetty.http.compression.Huffman.CODES; import static org.eclipse.jetty.http.compression.Huffman.LCCODES; @@ -67,7 +69,7 @@ public class HuffmanEncoder for (int i = 0; i < len; i++) { char c = s.charAt(i); - if (Huffman.isIllegalCharacter(c)) + if (HttpTokens.isIllegalFieldVchar(c)) return -1; needed += table[c][1]; } @@ -88,7 +90,7 @@ public class HuffmanEncoder for (int i = 0; i < len; i++) { char c = s.charAt(i); - if (Huffman.isIllegalCharacter(c)) + if (HttpTokens.isIllegalFieldVchar(c)) throw new IllegalArgumentException(); int code = table[c][0]; int bits = table[c][1]; diff --git a/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/HpackEncoder.java b/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/HpackEncoder.java index e665c839f35..77b486a17f4 100644 --- a/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/HpackEncoder.java +++ b/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/HpackEncoder.java @@ -25,10 +25,10 @@ import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpScheme; import org.eclipse.jetty.http.HttpStatus; +import org.eclipse.jetty.http.HttpTokens; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.http.MetaData; import org.eclipse.jetty.http.PreEncodedHttpField; -import org.eclipse.jetty.http.compression.Huffman; import org.eclipse.jetty.http.compression.HuffmanEncoder; import org.eclipse.jetty.http.compression.NBitIntegerEncoder; import org.eclipse.jetty.http2.hpack.HpackContext.Entry; @@ -468,7 +468,7 @@ public class HpackEncoder for (int i = 0; i < value.length(); i++) { char c = value.charAt(i); - c = Huffman.getReplacementCharacter(c); + c = HttpTokens.sanitizeFieldVchar(c); buffer.put((byte)c); } }