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];
|
||||
bufs.set(new WeakReference<byte[]>(buf));
|
||||
}
|
||||
int chunkSize;
|
||||
int position = 0;
|
||||
while ((chunkSize = stream.read(buf, position, size - position)) != -1) {
|
||||
position += chunkSize;
|
||||
|
||||
int remaining = size;
|
||||
while (remaining > 0) {
|
||||
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);
|
||||
}
|
||||
cis = CodedInputStream.newInstance(buf, 0, size);
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ import com.google.protobuf.Enum;
|
|||
import com.google.protobuf.InvalidProtocolBufferException;
|
||||
import com.google.protobuf.Type;
|
||||
import io.grpc.Drainable;
|
||||
import io.grpc.KnownLength;
|
||||
import io.grpc.Metadata;
|
||||
import io.grpc.MethodDescriptor.Marshaller;
|
||||
import io.grpc.MethodDescriptor.PrototypeMarshaller;
|
||||
|
|
@ -215,4 +216,36 @@ public class ProtoLiteUtilsTest {
|
|||
|
||||
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