Revert "ByteProcessor shouldn't throw checked exception"
This reverts commit b70d0fa6e3
.
This commit is contained in:
parent
b70d0fa6e3
commit
ff2e790e89
@ -1262,37 +1262,58 @@ public abstract class AbstractByteBuf extends ByteBuf {
|
||||
@Override
|
||||
public int forEachByte(ByteProcessor processor) {
|
||||
ensureAccessible();
|
||||
try {
|
||||
return forEachByteAsc0(readerIndex, writerIndex, processor);
|
||||
} catch (Exception e) {
|
||||
PlatformDependent.throwException(e);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int forEachByte(int index, int length, ByteProcessor processor) {
|
||||
checkIndex(index, length);
|
||||
try {
|
||||
return forEachByteAsc0(index, index + length, processor);
|
||||
} catch (Exception e) {
|
||||
PlatformDependent.throwException(e);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int forEachByteAsc0(int start, int end, ByteProcessor processor) {
|
||||
int forEachByteAsc0(int start, int end, ByteProcessor processor) throws Exception {
|
||||
for (; start < end; ++start) {
|
||||
if (!processor.process(_getByte(start))) {
|
||||
return start;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int forEachByteDesc(ByteProcessor processor) {
|
||||
ensureAccessible();
|
||||
try {
|
||||
return forEachByteDesc0(writerIndex - 1, readerIndex, processor);
|
||||
} catch (Exception e) {
|
||||
PlatformDependent.throwException(e);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int forEachByteDesc(int index, int length, ByteProcessor processor) {
|
||||
checkIndex(index, length);
|
||||
try {
|
||||
return forEachByteDesc0(index + length - 1, index, processor);
|
||||
} catch (Exception e) {
|
||||
PlatformDependent.throwException(e);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int forEachByteDesc0(int rStart, final int rEnd, ByteProcessor processor) {
|
||||
int forEachByteDesc0(int rStart, final int rEnd, ByteProcessor processor) throws Exception {
|
||||
for (; rStart >= rEnd; --rStart) {
|
||||
if (!processor.process(_getByte(rStart))) {
|
||||
return rStart;
|
||||
|
@ -660,7 +660,7 @@ public class CompositeByteBuf extends AbstractReferenceCountedByteBuf implements
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int forEachByteAsc0(int start, int end, ByteProcessor processor) {
|
||||
protected int forEachByteAsc0(int start, int end, ByteProcessor processor) throws Exception {
|
||||
if (end <= start) {
|
||||
return -1;
|
||||
}
|
||||
@ -686,7 +686,7 @@ public class CompositeByteBuf extends AbstractReferenceCountedByteBuf implements
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int forEachByteDesc0(int rStart, int rEnd, ByteProcessor processor) {
|
||||
protected int forEachByteDesc0(int rStart, int rEnd, ByteProcessor processor) throws Exception {
|
||||
if (rEnd > rStart) { // rStart *and* rEnd are inclusive
|
||||
return -1;
|
||||
}
|
||||
|
@ -2284,7 +2284,7 @@ public abstract class AbstractByteBufTest {
|
||||
int i = CAPACITY / 4;
|
||||
|
||||
@Override
|
||||
public boolean process(byte value) {
|
||||
public boolean process(byte value) throws Exception {
|
||||
assertThat(value, is((byte) (i + 1)));
|
||||
lastIndex.set(i);
|
||||
i ++;
|
||||
@ -2307,7 +2307,7 @@ public abstract class AbstractByteBufTest {
|
||||
int i = CAPACITY / 3;
|
||||
|
||||
@Override
|
||||
public boolean process(byte value) {
|
||||
public boolean process(byte value) throws Exception {
|
||||
assertThat(value, is((byte) (i + 1)));
|
||||
if (i == stop) {
|
||||
return false;
|
||||
@ -4608,7 +4608,7 @@ public abstract class AbstractByteBufTest {
|
||||
private int index = bytes.length - 1;
|
||||
|
||||
@Override
|
||||
public boolean process(byte value) {
|
||||
public boolean process(byte value) throws Exception {
|
||||
bytes[index--] = value;
|
||||
return true;
|
||||
}
|
||||
@ -4631,7 +4631,7 @@ public abstract class AbstractByteBufTest {
|
||||
private int index;
|
||||
|
||||
@Override
|
||||
public boolean process(byte value) {
|
||||
public boolean process(byte value) throws Exception {
|
||||
bytes[index++] = value;
|
||||
return true;
|
||||
}
|
||||
@ -4804,7 +4804,7 @@ public abstract class AbstractByteBufTest {
|
||||
|
||||
private static final class TestByteProcessor implements ByteProcessor {
|
||||
@Override
|
||||
public boolean process(byte value) {
|
||||
public boolean process(byte value) throws Exception {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ import io.netty.handler.codec.HeadersUtils;
|
||||
import io.netty.handler.codec.ValueConverter;
|
||||
import io.netty.util.AsciiString;
|
||||
import io.netty.util.ByteProcessor;
|
||||
import io.netty.util.internal.PlatformDependent;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
@ -49,10 +50,14 @@ public class DefaultHttpHeaders extends HttpHeaders {
|
||||
};
|
||||
static final NameValidator<CharSequence> HttpNameValidator = name -> {
|
||||
if (name == null || name.length() == 0) {
|
||||
throw new IllegalArgumentException("empty headers are not allowed [" + name + ']');
|
||||
throw new IllegalArgumentException("empty headers are not allowed [" + name + "]");
|
||||
}
|
||||
if (name instanceof AsciiString) {
|
||||
try {
|
||||
((AsciiString) name).forEachByte(HEADER_NAME_VALIDATOR);
|
||||
} catch (Exception e) {
|
||||
PlatformDependent.throwException(e);
|
||||
}
|
||||
} else {
|
||||
// Go through each character in the name
|
||||
for (int index = 0; index < name.length(); ++index) {
|
||||
@ -68,7 +73,7 @@ public class DefaultHttpHeaders extends HttpHeaders {
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>Warning!</b> Setting {@code validate} to {@code false} will mean that Netty won't
|
||||
* <b>Warning!</b> Setting <code>validate</code> to <code>false</code> will mean that Netty won't
|
||||
* validate & protect against user-supplied header values that are malicious.
|
||||
* This can leave your server implementation vulnerable to
|
||||
* <a href="https://cwe.mitre.org/data/definitions/113.html">
|
||||
|
@ -936,7 +936,7 @@ public abstract class HttpObjectDecoder extends ByteToMessageDecoder {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean process(byte value) {
|
||||
public boolean process(byte value) throws Exception {
|
||||
char nextByte = (char) (value & 0xFF);
|
||||
if (nextByte == HttpConstants.LF) {
|
||||
int len = seq.length();
|
||||
@ -983,7 +983,7 @@ public abstract class HttpObjectDecoder extends ByteToMessageDecoder {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean process(byte value) {
|
||||
public boolean process(byte value) throws Exception {
|
||||
if (currentState == State.SKIP_CONTROL_CHARS) {
|
||||
char c = (char) (value & 0xFF);
|
||||
if (Character.isISOControl(c) || Character.isWhitespace(c)) {
|
||||
|
@ -706,7 +706,7 @@ public class HttpPostStandardRequestDecoder implements InterfaceHttpPostRequestD
|
||||
|
||||
private static final class UrlEncodedDetector implements ByteProcessor {
|
||||
@Override
|
||||
public boolean process(byte value) {
|
||||
public boolean process(byte value) throws Exception {
|
||||
return value != '%' && value != '+';
|
||||
}
|
||||
}
|
||||
|
@ -84,7 +84,7 @@ final class Utf8Validator implements ByteProcessor {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean process(byte b) {
|
||||
public boolean process(byte b) throws Exception {
|
||||
byte type = TYPES[b & 0xFF];
|
||||
|
||||
codep = state != UTF8_ACCEPT ? b & 0x3f | codep << 6 : 0xff >> type & b;
|
||||
|
@ -38,7 +38,18 @@ public class DefaultHttp2Headers
|
||||
"empty headers are not allowed [%s]", name));
|
||||
}
|
||||
if (name instanceof AsciiString) {
|
||||
int index = ((AsciiString) name).forEachByte(HTTP2_NAME_VALIDATOR_PROCESSOR);
|
||||
final int index;
|
||||
try {
|
||||
index = ((AsciiString) name).forEachByte(HTTP2_NAME_VALIDATOR_PROCESSOR);
|
||||
} catch (Http2Exception e) {
|
||||
PlatformDependent.throwException(e);
|
||||
return;
|
||||
} catch (Throwable t) {
|
||||
PlatformDependent.throwException(connectionError(PROTOCOL_ERROR, t,
|
||||
"unexpected error. invalid header name [%s]", name));
|
||||
return;
|
||||
}
|
||||
|
||||
if (index != -1) {
|
||||
PlatformDependent.throwException(connectionError(PROTOCOL_ERROR,
|
||||
"invalid header name [%s]", name));
|
||||
@ -98,7 +109,7 @@ public class DefaultHttp2Headers
|
||||
|
||||
@Override
|
||||
public Http2Headers clear() {
|
||||
firstNonPseudo = head;
|
||||
this.firstNonPseudo = head;
|
||||
return super.clear();
|
||||
}
|
||||
|
||||
|
@ -70,9 +70,11 @@ final class HpackHuffmanEncoder {
|
||||
requireNonNull(out, "out");
|
||||
if (data instanceof AsciiString) {
|
||||
AsciiString string = (AsciiString) data;
|
||||
encodeProcessor.out = out;
|
||||
try {
|
||||
encodeProcessor.out = out;
|
||||
string.forEachByte(encodeProcessor);
|
||||
} catch (Exception e) {
|
||||
PlatformDependent.throwException(e);
|
||||
} finally {
|
||||
encodeProcessor.end();
|
||||
}
|
||||
@ -116,9 +118,14 @@ final class HpackHuffmanEncoder {
|
||||
int getEncodedLength(CharSequence data) {
|
||||
if (data instanceof AsciiString) {
|
||||
AsciiString string = (AsciiString) data;
|
||||
try {
|
||||
encodedLengthProcessor.reset();
|
||||
string.forEachByte(encodedLengthProcessor);
|
||||
return encodedLengthProcessor.length();
|
||||
} catch (Exception e) {
|
||||
PlatformDependent.throwException(e);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
return getEncodedLengthSlowPath(data);
|
||||
}
|
||||
|
@ -427,6 +427,7 @@ public final class HttpConversionUtil {
|
||||
|
||||
while (valuesIter.hasNext()) {
|
||||
AsciiString lowerCased = AsciiString.of(valuesIter.next()).toLowerCase();
|
||||
try {
|
||||
int index = lowerCased.forEachByte(FIND_COMMA);
|
||||
if (index != -1) {
|
||||
int start = 0;
|
||||
@ -439,6 +440,11 @@ public final class HttpConversionUtil {
|
||||
} else {
|
||||
result.add(lowerCased.trim(), EMPTY_STRING);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// This is not expect to happen because FIND_COMMA never throws but must be caught
|
||||
// because of the ByteProcessor interface.
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -483,6 +489,7 @@ public final class HttpConversionUtil {
|
||||
AsciiString value = AsciiString.of(entry.getValue());
|
||||
// split up cookies to allow for better compression
|
||||
// https://tools.ietf.org/html/rfc7540#section-8.1.2.5
|
||||
try {
|
||||
int index = value.forEachByte(FIND_SEMI_COLON);
|
||||
if (index != -1) {
|
||||
int start = 0;
|
||||
@ -499,6 +506,11 @@ public final class HttpConversionUtil {
|
||||
} else {
|
||||
out.add(COOKIE, value);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// This is not expect to happen because FIND_SEMI_COLON never throws but must be caught
|
||||
// because of the ByteProcessor interface.
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
} else {
|
||||
out.add(aName, entry.getValue());
|
||||
}
|
||||
|
@ -311,7 +311,7 @@ public final class RedisDecoder extends ByteToMessageDecoder {
|
||||
private long result;
|
||||
|
||||
@Override
|
||||
public boolean process(byte value) {
|
||||
public boolean process(byte value) throws Exception {
|
||||
if (value < '0' || value > '9') {
|
||||
throw new RedisCodecException("bad byte in number: " + value);
|
||||
}
|
||||
|
@ -274,7 +274,7 @@ public class StompSubframeDecoder extends ReplayingDecoder<State> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean process(byte nextByte) {
|
||||
public boolean process(byte nextByte) throws Exception {
|
||||
if (nextByte == StompConstants.CR) {
|
||||
++lineLength;
|
||||
return true;
|
||||
@ -353,7 +353,7 @@ public class StompSubframeDecoder extends ReplayingDecoder<State> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean process(byte nextByte) {
|
||||
public boolean process(byte nextByte) throws Exception {
|
||||
if (nextByte == StompConstants.COLON) {
|
||||
if (name == null) {
|
||||
AppendableCharSequence charSeq = charSequence();
|
||||
|
@ -331,7 +331,7 @@ public final class Base64 {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean process(byte value) {
|
||||
public boolean process(byte value) throws Exception {
|
||||
if (value > 0) {
|
||||
byte sbiDecode = decodabet[value];
|
||||
if (sbiDecode >= WHITE_SPACE_ENC) { // White space, Equals sign or better
|
||||
|
@ -255,7 +255,7 @@ public final class AsciiString implements CharSequence, Comparable<CharSequence>
|
||||
* @return {@code -1} if the processor iterated to or beyond the end of the readable bytes.
|
||||
* The last-visited index If the {@link ByteProcessor#process(byte)} returned {@code false}.
|
||||
*/
|
||||
public int forEachByte(ByteProcessor visitor) {
|
||||
public int forEachByte(ByteProcessor visitor) throws Exception {
|
||||
return forEachByte0(0, length(), visitor);
|
||||
}
|
||||
|
||||
@ -266,7 +266,7 @@ public final class AsciiString implements CharSequence, Comparable<CharSequence>
|
||||
* @return {@code -1} if the processor iterated to or beyond the end of the specified area.
|
||||
* The last-visited index If the {@link ByteProcessor#process(byte)} returned {@code false}.
|
||||
*/
|
||||
public int forEachByte(int index, int length, ByteProcessor visitor) {
|
||||
public int forEachByte(int index, int length, ByteProcessor visitor) throws Exception {
|
||||
if (isOutOfBounds(index, length, length())) {
|
||||
throw new IndexOutOfBoundsException("expected: " + "0 <= index(" + index + ") <= start + length(" + length
|
||||
+ ") <= " + "length(" + length() + ')');
|
||||
@ -274,7 +274,7 @@ public final class AsciiString implements CharSequence, Comparable<CharSequence>
|
||||
return forEachByte0(index, length, visitor);
|
||||
}
|
||||
|
||||
private int forEachByte0(int index, int length, ByteProcessor visitor) {
|
||||
private int forEachByte0(int index, int length, ByteProcessor visitor) throws Exception {
|
||||
final int len = offset + index + length;
|
||||
for (int i = offset + index; i < len; ++i) {
|
||||
if (!visitor.process(value[i])) {
|
||||
@ -290,7 +290,7 @@ public final class AsciiString implements CharSequence, Comparable<CharSequence>
|
||||
* @return {@code -1} if the processor iterated to or beyond the beginning of the readable bytes.
|
||||
* The last-visited index If the {@link ByteProcessor#process(byte)} returned {@code false}.
|
||||
*/
|
||||
public int forEachByteDesc(ByteProcessor visitor) {
|
||||
public int forEachByteDesc(ByteProcessor visitor) throws Exception {
|
||||
return forEachByteDesc0(0, length(), visitor);
|
||||
}
|
||||
|
||||
@ -301,7 +301,7 @@ public final class AsciiString implements CharSequence, Comparable<CharSequence>
|
||||
* @return {@code -1} if the processor iterated to or beyond the beginning of the specified area.
|
||||
* The last-visited index If the {@link ByteProcessor#process(byte)} returned {@code false}.
|
||||
*/
|
||||
public int forEachByteDesc(int index, int length, ByteProcessor visitor) {
|
||||
public int forEachByteDesc(int index, int length, ByteProcessor visitor) throws Exception {
|
||||
if (isOutOfBounds(index, length, length())) {
|
||||
throw new IndexOutOfBoundsException("expected: " + "0 <= index(" + index + ") <= start + length(" + length
|
||||
+ ") <= " + "length(" + length() + ')');
|
||||
@ -309,7 +309,7 @@ public final class AsciiString implements CharSequence, Comparable<CharSequence>
|
||||
return forEachByteDesc0(index, length, visitor);
|
||||
}
|
||||
|
||||
private int forEachByteDesc0(int index, int length, ByteProcessor visitor) {
|
||||
private int forEachByteDesc0(int index, int length, ByteProcessor visitor) throws Exception {
|
||||
final int end = offset + index;
|
||||
for (int i = offset + index + length - 1; i >= end; --i) {
|
||||
if (!visitor.process(value[i])) {
|
||||
|
@ -124,5 +124,5 @@ public interface ByteProcessor {
|
||||
* @return {@code true} if the processor wants to continue the loop and handle the next byte in the buffer.
|
||||
* {@code false} if the processor wants to stop handling bytes and abort the loop.
|
||||
*/
|
||||
boolean process(byte value);
|
||||
boolean process(byte value) throws Exception;
|
||||
}
|
||||
|
@ -78,13 +78,13 @@ public class AsciiStringMemoryTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void forEachTest() {
|
||||
public void forEachTest() throws Exception {
|
||||
final AtomicReference<Integer> aCount = new AtomicReference<>(0);
|
||||
final AtomicReference<Integer> bCount = new AtomicReference<>(0);
|
||||
aAsciiString.forEachByte(new ByteProcessor() {
|
||||
int i;
|
||||
@Override
|
||||
public boolean process(byte value) {
|
||||
public boolean process(byte value) throws Exception {
|
||||
assertEquals("failed at index: " + i, value, bAsciiString.byteAt(i++));
|
||||
aCount.set(aCount.get() + 1);
|
||||
return true;
|
||||
@ -93,7 +93,7 @@ public class AsciiStringMemoryTest {
|
||||
bAsciiString.forEachByte(new ByteProcessor() {
|
||||
int i;
|
||||
@Override
|
||||
public boolean process(byte value) {
|
||||
public boolean process(byte value) throws Exception {
|
||||
assertEquals("failed at index: " + i, value, aAsciiString.byteAt(i++));
|
||||
bCount.set(bCount.get() + 1);
|
||||
return true;
|
||||
@ -104,25 +104,25 @@ public class AsciiStringMemoryTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void forEachWithIndexEndTest() {
|
||||
public void forEachWithIndexEndTest() throws Exception {
|
||||
assertNotEquals(-1, aAsciiString.forEachByte(aAsciiString.length() - 1,
|
||||
1, new IndexOfProcessor(aAsciiString.byteAt(aAsciiString.length() - 1))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void forEachWithIndexBeginTest() {
|
||||
public void forEachWithIndexBeginTest() throws Exception {
|
||||
assertNotEquals(-1, aAsciiString.forEachByte(0,
|
||||
1, new IndexOfProcessor(aAsciiString.byteAt(0))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void forEachDescTest() {
|
||||
public void forEachDescTest() throws Exception {
|
||||
final AtomicReference<Integer> aCount = new AtomicReference<>(0);
|
||||
final AtomicReference<Integer> bCount = new AtomicReference<>(0);
|
||||
aAsciiString.forEachByteDesc(new ByteProcessor() {
|
||||
int i = 1;
|
||||
@Override
|
||||
public boolean process(byte value) {
|
||||
public boolean process(byte value) throws Exception {
|
||||
assertEquals("failed at index: " + i, value, bAsciiString.byteAt(bAsciiString.length() - (i++)));
|
||||
aCount.set(aCount.get() + 1);
|
||||
return true;
|
||||
@ -131,7 +131,7 @@ public class AsciiStringMemoryTest {
|
||||
bAsciiString.forEachByteDesc(new ByteProcessor() {
|
||||
int i = 1;
|
||||
@Override
|
||||
public boolean process(byte value) {
|
||||
public boolean process(byte value) throws Exception {
|
||||
assertEquals("failed at index: " + i, value, aAsciiString.byteAt(aAsciiString.length() - (i++)));
|
||||
bCount.set(bCount.get() + 1);
|
||||
return true;
|
||||
@ -142,13 +142,13 @@ public class AsciiStringMemoryTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void forEachDescWithIndexEndTest() {
|
||||
public void forEachDescWithIndexEndTest() throws Exception {
|
||||
assertNotEquals(-1, bAsciiString.forEachByteDesc(bAsciiString.length() - 1,
|
||||
1, new IndexOfProcessor(bAsciiString.byteAt(bAsciiString.length() - 1))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void forEachDescWithIndexBeginTest() {
|
||||
public void forEachDescWithIndexBeginTest() throws Exception {
|
||||
assertNotEquals(-1, bAsciiString.forEachByteDesc(0,
|
||||
1, new IndexOfProcessor(bAsciiString.byteAt(0))));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user