Issue #4538 - add invalid utf8 validation tests for MessageReader

Signed-off-by: Lachlan Roberts <lachlan@webtide.com>
This commit is contained in:
Lachlan Roberts 2020-02-18 10:54:18 +11:00
parent 2467d5a8c5
commit 1b123b87a9
2 changed files with 50 additions and 6 deletions

View File

@ -23,6 +23,7 @@ import java.io.Reader;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CoderResult;
import java.nio.charset.CodingErrorAction;
import java.nio.charset.StandardCharsets;
@ -63,19 +64,25 @@ public class MessageReader extends Reader implements MessageSink
public int read(char[] cbuf, int off, int len) throws IOException
{
CharBuffer charBuffer = CharBuffer.wrap(cbuf, off, len);
if (!buffer.hasRemaining())
boolean endOfInput = false;
while (true)
{
int read = stream.read(buffer);
if (read == 0)
return read;
break;
if (read < 0)
{
utf8Decoder.decode(BufferUtil.EMPTY_BUFFER, charBuffer, true);
return (charBuffer.position() > 0) ? charBuffer.position() : read;
endOfInput = true;
break;
}
}
utf8Decoder.decode(buffer, charBuffer, false);
CoderResult result = utf8Decoder.decode(buffer, charBuffer, endOfInput);
if (result.isError())
result.throwException();
if (endOfInput && (charBuffer.position() == 0))
return -1;
return charBuffer.position();
}

View File

@ -1,12 +1,34 @@
//
// ========================================================================
// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others.
//
// This program and the accompanying materials are made available under
// the terms of the Eclipse Public License 2.0 which is available at
// https://www.eclipse.org/legal/epl-2.0
//
// This Source Code may also be made available under the following
// Secondary Licenses when the conditions for such availability set
// forth in the Eclipse Public License, v. 2.0 are satisfied:
// the Apache License v2.0 which is available at
// https://www.apache.org/licenses/LICENSE-2.0
//
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
// ========================================================================
//
package org.eclipse.jetty.websocket.util;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.charset.MalformedInputException;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.FutureCallback;
import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.websocket.core.Frame;
import org.eclipse.jetty.websocket.core.OpCode;
import org.eclipse.jetty.websocket.util.messages.MessageReader;
@ -90,10 +112,25 @@ public class MessageReaderTest
assertThat(cause.getMessage(), is("Closed"));
}
@Test
public void testInvalidUtf8() throws Exception
{
ByteBuffer invalidUtf8Payload = BufferUtil.toBuffer(new byte[]{0x7F, (byte)0xFF, (byte)0xFF});
giveByteBuffer(invalidUtf8Payload, true);
ExecutionException error = assertThrows(ExecutionException.class, () -> message.get(5, TimeUnit.SECONDS));
assertThat(error.getCause(), instanceOf(MalformedInputException.class));
}
private void giveString(String s, boolean last) throws IOException
{
giveByteBuffer(ByteBuffer.wrap(StringUtil.getUtf8Bytes(s)), last);
}
private void giveByteBuffer(ByteBuffer buffer, boolean last) throws IOException
{
byte opCode = first ? OpCode.TEXT : OpCode.CONTINUATION;
Frame frame = new Frame(opCode, last, s);
Frame frame = new Frame(opCode, last, buffer);
FutureCallback callback = new FutureCallback();
reader.accept(frame, callback);
callback.block(5, TimeUnit.SECONDS);