mirror of https://github.com/grpc/grpc-java.git
protobuf-lite: ProtoLiteUtils fix infinite loop
InputStream by contract can return zero if requested length equal to zero. ``` If len is zero, then no bytes are read and 0 is returned; otherwise, there is an attempt to read at least one byte. If no byte is available because the stream is at end of file, the value -1 is returned; otherwise, at least one byte is read and stored into b. ``` Close #3323
This commit is contained in:
parent
577bbefd1a
commit
ca7685ef50
|
|
@ -128,12 +128,19 @@ public class ProtoLiteUtils {
|
||||||
buf = new byte[size];
|
buf = new byte[size];
|
||||||
bufs.set(new WeakReference<byte[]>(buf));
|
bufs.set(new WeakReference<byte[]>(buf));
|
||||||
}
|
}
|
||||||
int chunkSize;
|
|
||||||
int position = 0;
|
int remaining = size;
|
||||||
while ((chunkSize = stream.read(buf, position, size - position)) != -1) {
|
while (remaining > 0) {
|
||||||
position += chunkSize;
|
int position = size - remaining;
|
||||||
|
int count = stream.read(buf, position, remaining);
|
||||||
|
if (count == -1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
remaining -= count;
|
||||||
}
|
}
|
||||||
if (size != position) {
|
|
||||||
|
if (remaining != 0) {
|
||||||
|
int position = size - remaining;
|
||||||
throw new RuntimeException("size inaccurate: " + size + " != " + position);
|
throw new RuntimeException("size inaccurate: " + size + " != " + position);
|
||||||
}
|
}
|
||||||
cis = CodedInputStream.newInstance(buf, 0, size);
|
cis = CodedInputStream.newInstance(buf, 0, size);
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ import com.google.protobuf.Enum;
|
||||||
import com.google.protobuf.InvalidProtocolBufferException;
|
import com.google.protobuf.InvalidProtocolBufferException;
|
||||||
import com.google.protobuf.Type;
|
import com.google.protobuf.Type;
|
||||||
import io.grpc.Drainable;
|
import io.grpc.Drainable;
|
||||||
|
import io.grpc.KnownLength;
|
||||||
import io.grpc.Metadata;
|
import io.grpc.Metadata;
|
||||||
import io.grpc.MethodDescriptor.Marshaller;
|
import io.grpc.MethodDescriptor.Marshaller;
|
||||||
import io.grpc.MethodDescriptor.PrototypeMarshaller;
|
import io.grpc.MethodDescriptor.PrototypeMarshaller;
|
||||||
|
|
@ -215,4 +216,36 @@ public class ProtoLiteUtilsTest {
|
||||||
|
|
||||||
ProtoLiteUtils.setExtensionRegistry(null);
|
ProtoLiteUtils.setExtensionRegistry(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void parseFromKnowLengthInputStream() throws Exception {
|
||||||
|
Marshaller<Type> marshaller = ProtoLiteUtils.marshaller(Type.getDefaultInstance());
|
||||||
|
Type expect = Type.newBuilder().setName("expected name").build();
|
||||||
|
|
||||||
|
Type result = marshaller.parse(new CustomKnownLengthInputStream(expect.toByteArray()));
|
||||||
|
assertEquals(expect, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class CustomKnownLengthInputStream extends InputStream implements KnownLength {
|
||||||
|
private int position = 0;
|
||||||
|
private byte[] source;
|
||||||
|
|
||||||
|
private CustomKnownLengthInputStream(byte[] source) {
|
||||||
|
this.source = source;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int available() throws IOException {
|
||||||
|
return source.length - position;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int read() throws IOException {
|
||||||
|
if (position == source.length) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return source[position++];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue