diff --git a/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/HpackContext.java b/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/HpackContext.java index dda8ec30cb7..412f09ebc2a 100644 --- a/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/HpackContext.java +++ b/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/HpackContext.java @@ -461,6 +461,8 @@ public class HpackContext if (value != null && value.length() > 0) { int huffmanLen = Huffman.octetsNeeded(value); + if (huffmanLen < 0) + throw new IllegalStateException("bad value"); int lenLen = NBitInteger.octectsNeeded(7, huffmanLen); _huffmanValue = new byte[1 + lenLen + huffmanLen]; ByteBuffer buffer = ByteBuffer.wrap(_huffmanValue); 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 0e2aeec44da..a6c3bda169b 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 @@ -392,18 +392,18 @@ public class HpackEncoder if (huffman) { // huffman literal value - buffer.put((byte)0x80).mark(); + buffer.put((byte)0x80); - try + int needed = Huffman.octetsNeeded(value); + if (needed >= 0) { - NBitInteger.encode(buffer,7,Huffman.octetsNeeded(value)); - Huffman.encode(buffer,value); + NBitInteger.encode(buffer, 7, needed); + Huffman.encode(buffer, value); } - catch(Throwable th) + else { - LOG.ignore(th); + // Not iso_8859_1 byte[] bytes = value.getBytes(StandardCharsets.UTF_8); - NBitInteger.encode(buffer,7,Huffman.octetsNeeded(bytes)); Huffman.encode(buffer,bytes); } @@ -418,7 +418,7 @@ public class HpackEncoder char c = value.charAt(i); if (c < ' ' || c > 127) { - // Not iso_8859_1, so re-encode remaining as UTF-8 + // Not iso_8859_1, so re-encode as UTF-8 buffer.reset(); byte[] bytes = value.getBytes(StandardCharsets.UTF_8); NBitInteger.encode(buffer,7,bytes.length); diff --git a/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/Huffman.java b/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/Huffman.java index 8197eb62898..4645a6cebfb 100644 --- a/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/Huffman.java +++ b/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/Huffman.java @@ -360,7 +360,7 @@ public class Huffman public static String decode(ByteBuffer buffer,int length) throws HpackException.CompressionException { - Utf8StringBuilder utf8 = new Utf8StringBuilder(length*2); + Utf8StringBuilder utf8 = new Utf8StringBuilder(length * 2); int node = 0; int current = 0; int bits = 0; @@ -380,7 +380,7 @@ public class Huffman throw new HpackException.CompressionException("EOS in content"); // terminal node - utf8.append((byte)(0xFF&rowsym[node])); + utf8.append((byte)(0xFF & rowsym[node])); bits -= rowbits[node]; node = 0; } @@ -413,7 +413,7 @@ public class Huffman break; } - utf8.append((byte)(0xFF&rowsym[node])); + utf8.append((byte)(0xFF & rowsym[node])); bits -= rowbits[node]; node = 0; } @@ -462,7 +462,7 @@ public class Huffman { char c = s.charAt(i); if (c >= 128 || c < ' ') - throw new IllegalArgumentException(); + return -1; needed += table[c][1]; } @@ -470,17 +470,23 @@ public class Huffman } private static int octetsNeeded(final int[][] table,byte[] b) - { - int needed=0; + { + int needed = 0; int len = b.length; - for (int i=0;i= 8) + while (n >= 8) { n -= 8; - array[p++]=(byte)(current >> n); + array[p++] = (byte)(current >> n); } } - if (n > 0) + if (n > 0) { - current <<= (8 - n); - current |= (0xFF >>> n); - array[p++]=(byte)current; + current <<= (8 - n); + current |= (0xFF >>> n); + array[p++] = (byte)current; } - - buffer.position(p-buffer.arrayOffset()); + + buffer.position(p - buffer.arrayOffset()); } } diff --git a/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HuffmanTest.java b/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HuffmanTest.java index 802427f1866..5a947b8fd78 100644 --- a/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HuffmanTest.java +++ b/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HuffmanTest.java @@ -25,11 +25,13 @@ import java.util.stream.Stream; import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.TypeUtil; +import org.hamcrest.Matchers; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.ValueSource; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -77,8 +79,7 @@ public class HuffmanTest { String s = "bad '" + bad + "'"; - assertThrows(IllegalArgumentException.class, - () -> Huffman.octetsNeeded(s)); + assertThat(Huffman.octetsNeeded(s), Matchers.is(-1)); assertThrows(BufferOverflowException.class, () -> Huffman.encode(BufferUtil.allocate(32), s));