Reject varint payloads exceeding u64 range

The 10th varint byte (shift=63) can only contribute 1 bit of payload.
Previously, bytes like 0x02 at this position silently truncated the
extra bit and returned a wrong value. Now decode_varint checks
payload > 1 at shift=63 and returns InvalidData.

Add test_varint_above_u64_max_returns_error: [0xFF; 9] + [0x02]
is rejected as exceeding u64.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
diff --git a/core/src/io.rs b/core/src/io.rs
index 4f917a3..5cb491e 100644
--- a/core/src/io.rs
+++ b/core/src/io.rs
@@ -109,12 +109,19 @@
         }
         let b = buf[*pos] as u64;
         *pos += 1;
-        val |= (b & 0x7F) << shift;
+        let payload = b & 0x7F;
+        if shift == 63 && payload > 1 {
+            return Err(io::Error::new(
+                io::ErrorKind::InvalidData,
+                "varint exceeds u64 range",
+            ));
+        }
+        val |= payload << shift;
         if b & 0x80 == 0 {
             break;
         }
         shift += 7;
-        if shift >= 64 {
+        if shift > 63 {
             return Err(io::Error::new(
                 io::ErrorKind::InvalidData,
                 "varint exceeds 64 bits",
@@ -758,6 +765,14 @@
     }
 
     #[test]
+    fn test_varint_above_u64_max_returns_error() {
+        let mut bytes = vec![0xFFu8; 9];
+        bytes.push(0x02); // 10th byte with payload > 1 at shift=63
+        let mut pos = 0;
+        assert!(decode_varint(&bytes, &mut pos).is_err());
+    }
+
+    #[test]
     fn test_delta_varint_ids_roundtrip() {
         let ids = vec![3i64, 7, 12, 15, 23, 100, 200];
         let (base, encoded) = encode_delta_varint_ids(&ids);