You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@thrift.apache.org by "Jens Geyer (Jira)" <ji...@apache.org> on 2020/03/06 17:43:00 UTC

[jira] [Resolved] (THRIFT-5131) i64 maxint decoding panics with integer-encoding >= 1.1.0

     [ https://issues.apache.org/jira/browse/THRIFT-5131?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Jens Geyer resolved THRIFT-5131.
--------------------------------
    Fix Version/s: THRIFT-5111
         Assignee: Nik Clayton
       Resolution: Duplicate

> i64 maxint decoding panics with integer-encoding >= 1.1.0
> ---------------------------------------------------------
>
>                 Key: THRIFT-5131
>                 URL: https://issues.apache.org/jira/browse/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
>            Assignee: Nik Clayton
>            Priority: Major
>              Labels: crash, encoding, thrift
>             Fix For: THRIFT-5111
>
>          Time Spent: 10m
>  Remaining Estimate: 0h
>
> 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 to 0x7FFF_FFFF_FFFF_FFFF.
> 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:
> {code}
> [package]
> name = "int_encoding"
> version = "0.1.0"
> authors = ["Nik Clayton <ni...@dfinity.org>"]
> edition = "2018"
> [dependencies]
> thrift = "0.13.0"
> integer-encoding = "=1.0.8"
> {code}
> This pins the integer-encoding library to version 1.0.8.
> Put the following in src/main.rs:
> {code}
> 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 https://docs.rs/thrift/0.13.0/thrift/protocol/index.html
>     // except that (a) it's an I64, and (b) the channel is a Vec.
>     buf.clear();
>     let mut out_protocol = TCompactOutputProtocol::new(&mut buf);
>     out_protocol
>         .write_field_begin(&TFieldIdentifier::new(
>             "max_int",
>             TType::I64,
>             1,
>         ))
>         .unwrap();
>     out_protocol.write_i64(field_value).unwrap();
>     out_protocol.write_field_end().unwrap();
>     out_protocol.flush().unwrap();
>     let mut in_protocol = TCompactInputProtocol::new(&buf[..]);
>     in_protocol.read_field_begin().unwrap();
>     assert_eq!(field_value, in_protocol.read_i64().unwrap());
>     in_protocol.read_field_end().unwrap();
> }
> {code}
> Run this with "cargo run", it should succeed, and print:
> {code}
> Value is: 9223372036854775807, 7FFFFFFFFFFFFFFF
> {code}
> Edit Cargo.toml and change the "integer-encoding" line to
> {code}
> integer-encoding = "=1.1.3"
> {code}
> Run with "RUST_BACKTRACE=1 cargo run" and you will see the following panic (I've elided the full panic here):
> {code}
> thread 'main' panicked at 'index 11 out of range for slice of length 10', src/libcore/slice/mod.rs:2664:5
> stack backtrace:
> [...]
>   13: integer_encoding::reader::VarIntProcessor::decode
>              at /Users/nik/d/rs/.cargo-home/registry/src/github.com-1ecc6299db9ec823/integer-encoding-1.1.3/src/reader.rs:56
>   14: <R as integer_encoding::reader::VarIntReader>::read_varint
>              at /Users/nik/d/rs/.cargo-home/registry/src/github.com-1ecc6299db9ec823/integer-encoding-1.1.3/src/reader.rs:104
>   15: <thrift::protocol::compact::TCompactInputProtocol<T> as thrift::protocol::TInputProtocol>::read_i64
>              at /Users/nik/d/rs/.cargo-home/registry/src/github.com-1ecc6299db9ec823/thrift-0.13.0/src/protocol/compact.rs:246
>   16: int_encoding::main
>              at src/main.rs:41
> [...]
> {code}
> 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 main.rs and uncomment the line
> {code}
> //field_value = (1i64 << 62) - 1;
> {code}
> 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
(v8.3.4#803005)