thrift-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Nik Clayton (Jira)" <>
Subject [jira] [Created] (THRIFT-5131) i64 maxint decoding panics with integer-encoding >= 1.1.0
Date Wed, 04 Mar 2020 13:17:00 GMT
Nik Clayton created THRIFT-5131:

             Summary: i64 maxint decoding panics with integer-encoding >= 1.1.0
                 Key: THRIFT-5131
             Project: Thrift
          Issue Type: Bug
          Components: Rust - Library
    Affects Versions: 0.13.0
         Environment: % cargo --version --verbose
cargo 1.40.0
release: 1.40.0

% uname -a
Darwin Niks-MacBook-Pro.local 19.3.0 Darwin Kernel Version 19.3.0: Thu Jan 9 20:58:23 PST
2020; root:xnu-6153.81.5~1/RELEASE_X86_64 x86_64 i386 MacBookPro15,1 Darwin
            Reporter: Nik Clayton

The Rust library for Thrift uses the integer-encoding crate. In version 1.1.0 (through at
least 1.1.3, the most recent version) of this crate Thrift's usage appears to be responsible
for a panic in the library when trying to decode i64 numbers in the range 0x4000_0000_0000_0000

The integer-encoding crate does not panic when using it directly to encode / decode numbers
in this range.

To see this, create a scratch crate with "cargo new int_encoding".

Replace the contents of Cargo.toml with the following:

name = "int_encoding"
version = "0.1.0"
authors = ["Nik Clayton <>"]
edition = "2018"

thrift = "0.13.0"
integer-encoding = "=1.0.8"

This pins the integer-encoding library to version 1.0.8.

Put the following in src/

use thrift::protocol::{
    TCompactInputProtocol, TCompactOutputProtocol, TFieldIdentifier, TInputProtocol,
    TOutputProtocol, TType,
use integer_encoding::*;

fn main() {
    let mut field_value = i64::max_value(); // Fails

    // Uncomment the next line to see success
    //field_value = (1i64 << 62) - 1;

    let mut buf;
    println!("Value is: {}, {:X}", field_value, field_value);

    // First check that encoding and decoding works using the integer_encoding
    // library directly.
    buf = field_value.encode_var_vec();
    let (val, _) = VarInt::decode_var(&buf[..]);
    assert_eq!(field_value, val);

    // Clear the buffer, and try encoding the same value using Thrift. This code
    // is almost identical to
    // except that (a) it's an I64, and (b) the channel is a Vec.
    let mut out_protocol = TCompactOutputProtocol::new(&mut buf);


    let mut in_protocol = TCompactInputProtocol::new(&buf[..]);
    assert_eq!(field_value, in_protocol.read_i64().unwrap());

Run this with "cargo run", it should succeed, and print:

Value is: 9223372036854775807, 7FFFFFFFFFFFFFFF

Edit Cargo.toml and change the "integer-encoding" line to

integer-encoding = "=1.1.3"

Run with "RUST_BACKTRACE=1 cargo run" and you will see the following panic (I've elided the
full panic here):

thread 'main' panicked at 'index 11 out of range for slice of length 10', src/libcore/slice/
stack backtrace:
  13: integer_encoding::reader::VarIntProcessor::decode
             at /Users/nik/d/rs/.cargo-home/registry/src/
  14: <R as integer_encoding::reader::VarIntReader>::read_varint
             at /Users/nik/d/rs/.cargo-home/registry/src/
  15: <thrift::protocol::compact::TCompactInputProtocol<T> as thrift::protocol::TInputProtocol>::read_i64
             at /Users/nik/d/rs/.cargo-home/registry/src/
  16: int_encoding::main
             at src/

As you can see, the panic is coming from the call to Thrift's read_i64(). The earlier code
that used integer-encoding directly did not panic. That's why I think the problem is somewhere
in Thrift.

If you edit and uncomment the line

//field_value = (1i64 << 62) - 1;

the panic disappears. I believe this is the largest number that can be used without triggering
the panic.

This message was sent by Atlassian Jira

View raw message