Skip to content

Commit 5010153

Browse files
Fix Varint64 decoding around higher bits.
PiperOrigin-RevId: 824589139
1 parent 772aed3 commit 5010153

File tree

2 files changed

+65
-28
lines changed

2 files changed

+65
-28
lines changed

java/core/src/main/java/com/google/protobuf/CodedInputStream.java

Lines changed: 56 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1166,8 +1166,7 @@ public long readRawVarint64() throws IOException {
11661166
^ (~0L << 35)
11671167
^ (~0L << 42)
11681168
^ (~0L << 49);
1169-
} else {
1170-
x ^= ((long) buffer[tempPos++] << 56);
1169+
} else if ((x ^= ((long) buffer[tempPos++] << 56)) >= 0L) {
11711170
x ^=
11721171
(~0L << 7)
11731172
^ (~0L << 14)
@@ -1177,11 +1176,19 @@ public long readRawVarint64() throws IOException {
11771176
^ (~0L << 42)
11781177
^ (~0L << 49)
11791178
^ (~0L << 56);
1180-
if (x < 0L) {
1181-
if (buffer[tempPos++] < 0L) {
1182-
break fastpath; // Will throw malformedVarint()
1183-
}
1184-
}
1179+
} else if ((x ^= ((long) buffer[tempPos++] << 63)) >= 0L) {
1180+
x ^=
1181+
(~0L << 7)
1182+
^ (~0L << 14)
1183+
^ (~0L << 21)
1184+
^ (~0L << 28)
1185+
^ (~0L << 35)
1186+
^ (~0L << 42)
1187+
^ (~0L << 49)
1188+
^ (~0L << 56)
1189+
^ (~0L << 63);
1190+
} else {
1191+
break fastpath; // Will throw malformedVarint()
11851192
}
11861193
pos = tempPos;
11871194
return x;
@@ -1877,8 +1884,7 @@ public long readRawVarint64() throws IOException {
18771884
^ (~0L << 35)
18781885
^ (~0L << 42)
18791886
^ (~0L << 49);
1880-
} else {
1881-
x ^= ((long) UnsafeUtil.getByte(tempPos++) << 56);
1887+
} else if ((x ^= ((long) UnsafeUtil.getByte(tempPos++) << 56)) >= 0L) {
18821888
x ^=
18831889
(~0L << 7)
18841890
^ (~0L << 14)
@@ -1888,11 +1894,19 @@ public long readRawVarint64() throws IOException {
18881894
^ (~0L << 42)
18891895
^ (~0L << 49)
18901896
^ (~0L << 56);
1891-
if (x < 0L) {
1892-
if (UnsafeUtil.getByte(tempPos++) < 0L) {
1893-
break fastpath; // Will throw malformedVarint()
1894-
}
1895-
}
1897+
} else if ((x ^= ((long) UnsafeUtil.getByte(tempPos++) << 63)) >= 0L) {
1898+
x ^=
1899+
(~0L << 7)
1900+
^ (~0L << 14)
1901+
^ (~0L << 21)
1902+
^ (~0L << 28)
1903+
^ (~0L << 35)
1904+
^ (~0L << 42)
1905+
^ (~0L << 49)
1906+
^ (~0L << 56)
1907+
^ (~0L << 63);
1908+
} else {
1909+
break fastpath; // Will throw malformedVarint()
18961910
}
18971911
pos = tempPos;
18981912
return x;
@@ -2666,8 +2680,7 @@ public long readRawVarint64() throws IOException {
26662680
^ (~0L << 35)
26672681
^ (~0L << 42)
26682682
^ (~0L << 49);
2669-
} else {
2670-
x ^= ((long) buffer[tempPos++] << 56);
2683+
} else if ((x ^= ((long) buffer[tempPos++] << 56)) >= 0L) {
26712684
x ^=
26722685
(~0L << 7)
26732686
^ (~0L << 14)
@@ -2677,11 +2690,19 @@ public long readRawVarint64() throws IOException {
26772690
^ (~0L << 42)
26782691
^ (~0L << 49)
26792692
^ (~0L << 56);
2680-
if (x < 0L) {
2681-
if (buffer[tempPos++] < 0L) {
2682-
break fastpath; // Will throw malformedVarint()
2683-
}
2684-
}
2693+
} else if ((x ^= ((long) buffer[tempPos++] << 63)) >= 0L) {
2694+
x ^=
2695+
(~0L << 7)
2696+
^ (~0L << 14)
2697+
^ (~0L << 21)
2698+
^ (~0L << 28)
2699+
^ (~0L << 35)
2700+
^ (~0L << 42)
2701+
^ (~0L << 49)
2702+
^ (~0L << 56)
2703+
^ (~0L << 63);
2704+
} else {
2705+
break fastpath; // Will throw malformedVarint()
26852706
}
26862707
pos = tempPos;
26872708
return x;
@@ -3756,8 +3777,7 @@ public long readRawVarint64() throws IOException {
37563777
^ (~0L << 35)
37573778
^ (~0L << 42)
37583779
^ (~0L << 49);
3759-
} else {
3760-
x ^= ((long) UnsafeUtil.getByte(tempPos++) << 56);
3780+
} else if ((x ^= ((long) UnsafeUtil.getByte(tempPos++) << 56)) >= 0L) {
37613781
x ^=
37623782
(~0L << 7)
37633783
^ (~0L << 14)
@@ -3767,11 +3787,19 @@ public long readRawVarint64() throws IOException {
37673787
^ (~0L << 42)
37683788
^ (~0L << 49)
37693789
^ (~0L << 56);
3770-
if (x < 0L) {
3771-
if (UnsafeUtil.getByte(tempPos++) < 0L) {
3772-
break fastpath; // Will throw malformedVarint()
3773-
}
3774-
}
3790+
} else if ((x ^= ((long) UnsafeUtil.getByte(tempPos++) << 63)) >= 0L) {
3791+
x ^=
3792+
(~0L << 7)
3793+
^ (~0L << 14)
3794+
^ (~0L << 21)
3795+
^ (~0L << 28)
3796+
^ (~0L << 35)
3797+
^ (~0L << 42)
3798+
^ (~0L << 49)
3799+
^ (~0L << 56)
3800+
^ (~0L << 63);
3801+
} else {
3802+
break fastpath; // Will throw malformedVarint()
37753803
}
37763804
currentByteBufferPos = tempPos;
37773805
return x;

java/core/src/test/java/com/google/protobuf/CodedInputStreamTest.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,15 @@ public void testReadVarint() throws Exception {
303303
| (0x26L << 56)
304304
| (0x01L << 63));
305305

306+
assertReadVarint(bytes(0x85, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00), 5);
307+
assertReadVarint(bytes(0x85, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x02), 5);
308+
309+
// Test that the last bit decides the sign of the long value.
310+
assertReadVarint(
311+
bytes(0x85, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x01), Long.MIN_VALUE + 5L);
312+
assertReadVarint(
313+
bytes(0x85, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x03), Long.MIN_VALUE + 5L);
314+
306315
// Failures
307316
assertReadVarintFailure(
308317
InvalidProtocolBufferException.malformedVarint(),

0 commit comments

Comments
 (0)