avoid exceptions for non iso characters

Signed-off-by: Greg Wilkins <gregw@webtide.com>
This commit is contained in:
Greg Wilkins 2019-09-11 10:50:42 +10:00
parent bc96561865
commit 90cf7c80bd
4 changed files with 40 additions and 30 deletions

View File

@ -461,6 +461,8 @@ public class HpackContext
if (value != null && value.length() > 0) if (value != null && value.length() > 0)
{ {
int huffmanLen = Huffman.octetsNeeded(value); int huffmanLen = Huffman.octetsNeeded(value);
if (huffmanLen < 0)
throw new IllegalStateException("bad value");
int lenLen = NBitInteger.octectsNeeded(7, huffmanLen); int lenLen = NBitInteger.octectsNeeded(7, huffmanLen);
_huffmanValue = new byte[1 + lenLen + huffmanLen]; _huffmanValue = new byte[1 + lenLen + huffmanLen];
ByteBuffer buffer = ByteBuffer.wrap(_huffmanValue); ByteBuffer buffer = ByteBuffer.wrap(_huffmanValue);

View File

@ -392,18 +392,18 @@ public class HpackEncoder
if (huffman) if (huffman)
{ {
// huffman literal value // 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)); NBitInteger.encode(buffer, 7, needed);
Huffman.encode(buffer,value); Huffman.encode(buffer, value);
} }
catch(Throwable th) else
{ {
LOG.ignore(th); // Not iso_8859_1
byte[] bytes = value.getBytes(StandardCharsets.UTF_8); byte[] bytes = value.getBytes(StandardCharsets.UTF_8);
NBitInteger.encode(buffer,7,Huffman.octetsNeeded(bytes)); NBitInteger.encode(buffer,7,Huffman.octetsNeeded(bytes));
Huffman.encode(buffer,bytes); Huffman.encode(buffer,bytes);
} }
@ -418,7 +418,7 @@ public class HpackEncoder
char c = value.charAt(i); char c = value.charAt(i);
if (c < ' ' || c > 127) 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(); buffer.reset();
byte[] bytes = value.getBytes(StandardCharsets.UTF_8); byte[] bytes = value.getBytes(StandardCharsets.UTF_8);
NBitInteger.encode(buffer,7,bytes.length); NBitInteger.encode(buffer,7,bytes.length);

View File

@ -360,7 +360,7 @@ public class Huffman
public static String decode(ByteBuffer buffer,int length) throws HpackException.CompressionException 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 node = 0;
int current = 0; int current = 0;
int bits = 0; int bits = 0;
@ -380,7 +380,7 @@ public class Huffman
throw new HpackException.CompressionException("EOS in content"); throw new HpackException.CompressionException("EOS in content");
// terminal node // terminal node
utf8.append((byte)(0xFF&rowsym[node])); utf8.append((byte)(0xFF & rowsym[node]));
bits -= rowbits[node]; bits -= rowbits[node];
node = 0; node = 0;
} }
@ -413,7 +413,7 @@ public class Huffman
break; break;
} }
utf8.append((byte)(0xFF&rowsym[node])); utf8.append((byte)(0xFF & rowsym[node]));
bits -= rowbits[node]; bits -= rowbits[node];
node = 0; node = 0;
} }
@ -462,7 +462,7 @@ public class Huffman
{ {
char c = s.charAt(i); char c = s.charAt(i);
if (c >= 128 || c < ' ') if (c >= 128 || c < ' ')
throw new IllegalArgumentException(); return -1;
needed += table[c][1]; needed += table[c][1];
} }
@ -470,17 +470,23 @@ public class Huffman
} }
private static int octetsNeeded(final int[][] table,byte[] b) private static int octetsNeeded(final int[][] table,byte[] b)
{ {
int needed=0; int needed = 0;
int len = b.length; int len = b.length;
for (int i=0;i<len;i++) for (int i = 0; i < len; i++)
{ {
int c=0xFF&b[i]; int c = 0xFF & b[i];
needed += table[c][1]; needed += table[c][1];
} }
return (needed+7) / 8; return (needed + 7) / 8;
} }
/**
* @param table The table to encode by
* @param buffer The buffer to encode to
* @param s The string to encode
* @return True if the string could be encoded, false otherwise (and the buffer may have been modified).
*/
private static void encode(final int[][] table, ByteBuffer buffer, String s) private static void encode(final int[][] table, ByteBuffer buffer, String s)
{ {
long current = 0; long current = 0;
@ -512,18 +518,19 @@ public class Huffman
buffer.put((byte)(current)); buffer.put((byte)(current));
} }
} }
private static void encode(final int[][] table,ByteBuffer buffer,byte[] b) private static void encode(final int[][] table,ByteBuffer buffer,byte[] b)
{ {
long current = 0; long current = 0;
int n = 0; int n = 0;
byte[] array = buffer.array(); byte[] array = buffer.array();
int p=buffer.arrayOffset()+buffer.position(); int p = buffer.arrayOffset() + buffer.position();
int len = b.length; int len = b.length;
for (int i=0;i<len;i++) for (int i = 0; i < len; i++)
{ {
int c=0xFF&b[i]; int c = 0xFF & b[i];
int code = table[c][0]; int code = table[c][0];
int bits = table[c][1]; int bits = table[c][1];
@ -531,20 +538,20 @@ public class Huffman
current |= code; current |= code;
n += bits; n += bits;
while (n >= 8) while (n >= 8)
{ {
n -= 8; n -= 8;
array[p++]=(byte)(current >> n); array[p++] = (byte)(current >> n);
} }
} }
if (n > 0) if (n > 0)
{ {
current <<= (8 - n); current <<= (8 - n);
current |= (0xFF >>> n); current |= (0xFF >>> n);
array[p++]=(byte)current; array[p++] = (byte)current;
} }
buffer.position(p-buffer.arrayOffset()); buffer.position(p - buffer.arrayOffset());
} }
} }

View File

@ -25,11 +25,13 @@ import java.util.stream.Stream;
import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.TypeUtil; import org.eclipse.jetty.util.TypeUtil;
import org.hamcrest.Matchers;
import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.MethodSource;
import org.junit.jupiter.params.provider.ValueSource; 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.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertThrows;
@ -77,8 +79,7 @@ public class HuffmanTest
{ {
String s = "bad '" + bad + "'"; String s = "bad '" + bad + "'";
assertThrows(IllegalArgumentException.class, assertThat(Huffman.octetsNeeded(s), Matchers.is(-1));
() -> Huffman.octetsNeeded(s));
assertThrows(BufferOverflowException.class, assertThrows(BufferOverflowException.class,
() -> Huffman.encode(BufferUtil.allocate(32), s)); () -> Huffman.encode(BufferUtil.allocate(32), s));