ebkalderon / tower-lsp

Language Server Protocol implementation written in Rust
Apache License 2.0
962 stars 54 forks source link

Regression in parsing small chunked messages in codec #318

Closed ebkalderon closed 2 years ago

ebkalderon commented 2 years ago

As of merging #316, the new LanguageServerCodec implementation is no longer able to parse small chunked messages properly. The following minimal reproducible example succeeds with 0.15.1, but not in master currently:

#[test]
fn decodes_small_chunks() {
    let decoded = r#"{"jsonrpc":"2.0","method":"exit"}"#;
    let content_type = "application/vscode-jsonrpc; charset=utf-8";
    let encoded = encode_message(Some(content_type), decoded);

    let mut codec = LanguageServerCodec::default();
    let mut buffer = BytesMut::from(encoded.as_str());

    let rest = buffer.split_off(40);
    let message = codec.decode(&mut buffer).unwrap();
    assert_eq!(message, None);
    buffer.unsplit(rest);

    let rest = buffer.split_off(80);
    let message = codec.decode(&mut buffer).unwrap();
    assert_eq!(message, None);
    buffer.unsplit(rest);

    let rest = buffer.split_off(96);
    let message = codec.decode(&mut buffer).unwrap();
    assert_eq!(message, None);
    buffer.unsplit(rest);

    let decoded: Value = serde_json::from_str(decoded).unwrap();
    let message = codec.decode(&mut buffer).unwrap();
    assert_eq!(message, Some(decoded));
}
$ cargo test decodes_small_chunks
   Compiling tower-lsp v0.15.1 (/home/ekalderon/Documents/tower-lsp)
    Finished test [unoptimized + debuginfo] target(s) in 18.98s
     Running unittests (target/debug/deps/tower_lsp-db32f97915d141a8)

running 1 test
test codec::tests::decodes_small_chunks ... FAILED

failures:

---- codec::tests::decodes_small_chunks stdout ----
thread 'codec::tests::decodes_small_chunks' panicked at 'range end index 33 out of range for slice of length 1', src/codec.rs:233:28
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

failures:
    codec::tests::decodes_small_chunks

test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 25 filtered out; finished in 0.00s

error: test failed, to rerun pass '--lib'

The issue appears to be caused by src/codec.rs#L233, where previously the length was checked before slicing but is no longer (source).