Rust: starting from nightly-2020-08-18 rustls can't connect to some websites

Created on 16 Sep 2020  路  19Comments  路  Source: rust-lang/rust

I tried this code:

use std::io::{self, stdout, Write};
use std::net::TcpStream;
use std::sync::Arc;

use rustls::{ciphersuite, ClientConfig, ClientSession, Session, Stream};
use webpki::DNSNameRef;
use webpki_roots::TLS_SERVER_ROOTS;

fn main() {
    env_logger::init();

    let mut config = ClientConfig::with_ciphersuites(&[&ciphersuite::TLS13_AES_256_GCM_SHA384]);
    config
        .root_store
        .add_server_trust_anchors(&TLS_SERVER_ROOTS);
    // works with TLSv1_2 or with different ciphersuites
    config.versions = vec![rustls::ProtocolVersion::TLSv1_3];
    // this is what gets picked by default when using TLS 1.3
    config.ciphersuites = vec![&rustls::ciphersuite::TLS13_AES_256_GCM_SHA384];

    const DOMAIN: &str = "example.com";

    let dns_name = DNSNameRef::try_from_ascii_str(DOMAIN).unwrap();
    let mut sess = ClientSession::new(&Arc::new(config), dns_name);
    let mut sock = TcpStream::connect((DOMAIN, 443)).unwrap();
    let mut tls = Stream::new(&mut sess, &mut sock);
    tls.write_all(
        [
            "GET / HTTP/1.1\r\n",
            "Host: ",
            DOMAIN,
            "\r\n",
            "Connection: close\r\n",
            "\r\n",
        ]
        .join("")
        .as_bytes(),
    )
    .unwrap(); // fails here
    let ciphersuite = tls.sess.get_negotiated_ciphersuite().unwrap();
    println!("Current ciphersuite: {:?}", ciphersuite.suite);

    let mut out = stdout();
    if let Err(err) = io::copy(&mut tls, &mut out) {
        eprintln!("err: {}", err)
    }
}

With dependencies:

rustls = { version = "0.18.1", features = ["logging"] }
webpki = "0.21.3"
webpki-roots = "0.20.0"
env_logger = "0.7.1"

I expected to see this happen: it establishes a TLS connection, sends the HTTP/1.1 request and prints the entire response

Instead, this happened: fails with Custom { kind: InvalidData, error: DecryptError }

I bisected this to _nightly-2020-08-18_. I couldn't reproduce this issue with other websites.

Meta

rustc --version --verbose:

rustc 1.48.0-nightly (9b4154193 2020-09-14)
binary: rustc
commit-hash: 9b4154193e8471f36b1a9e781f1ef7d492fc6a6c
commit-date: 2020-09-14
host: x86_64-unknown-linux-gnu
release: 1.48.0-nightly
LLVM version: 11.0


Backtrace when running with cargo run

thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Custom { kind: InvalidData, error: DecryptError }', src/main.rs:39:6
stack backtrace:
   0: rust_begin_unwind
             at /rustc/9b4154193e8471f36b1a9e781f1ef7d492fc6a6c/library/std/src/panicking.rs:483
   1: core::panicking::panic_fmt
             at /rustc/9b4154193e8471f36b1a9e781f1ef7d492fc6a6c/library/core/src/panicking.rs:85
   2: core::option::expect_none_failed
             at /rustc/9b4154193e8471f36b1a9e781f1ef7d492fc6a6c/library/core/src/option.rs:1221
   3: core::result::Result<T,E>::unwrap
             at /home/paolo/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/result.rs:973
   4: proxy_bug::main
             at ./src/main.rs:27
   5: core::ops::function::FnOnce::call_once
             at /home/paolo/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ops/function.rs:227
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.

A-mir-opt C-bug I-unsound 馃挜 P-critical T-compiler regression-from-stable-to-beta

Most helpful comment

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(u8)]
pub enum Type {
    A = 1,
    B = 7,
}

impl Type {
    fn encode(&self) -> Type {
        match self {
            Type::A => Type::B,
            _ => *self,
        }
    }
}

fn main() {
    assert_eq!(Type::A.encode(), Type::B);
}
$ rustc -Zmir-opt-level=0 b.rs && ./b
$ rustc -Zmir-opt-level=1 b.rs && ./b
thread 'main' panicked at 'assertion failed: `(left == right)`
  left: `A`,
 right: `B`', b.rs:18:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

All 19 comments

I bisected this to nightly-2020-08-18.

Which commit is that? (and nightly-2020-08-17)

Ok I got cargo-bisect-rustc to work, here's the output:


searched nightlies: from nightly-2020-08-15 to nightly-2020-08-20
regressed nightly: nightly-2020-08-18
searched commits: from https://github.com/rust-lang/rust/commit/7e6d6e5f535321c2223f044caba16f97b825009c to https://github.com/rust-lang/rust/commit/792c645ca7d11a8d254df307d019c5bf01445c37
regressed commit: https://github.com/rust-lang/rust/commit/33c96b4d9782cf6364e47cb2c904e66b06c22bb4


bisected with cargo-bisect-rustc v0.5.2

Host triple: x86_64-unknown-linux-gnu
Reproduce with:

cargo bisect-rustc --preserve --start=2020-08-15 --end=2020-08-20 -- test 

Great, thanks for the report!

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(u8)]
pub enum Type {
    A = 1,
    B = 7,
}

impl Type {
    fn encode(&self) -> Type {
        match self {
            Type::A => Type::B,
            _ => *self,
        }
    }
}

fn main() {
    assert_eq!(Type::A.encode(), Type::B);
}
$ rustc -Zmir-opt-level=0 b.rs && ./b
$ rustc -Zmir-opt-level=1 b.rs && ./b
thread 'main' panicked at 'assertion failed: `(left == right)`
  left: `A`,
 right: `B`', b.rs:18:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

@tmiasko: Is there a relation to the original example code or to the issue in general?

@Stupremee the code example has different behavior with and without optimizations. Since there's no unsafe in the code, that means the compiler is unsound.

Yea I know, but what does it have to do with the issue / code from paolobarbolini?

It's minimized code from rustls <HandshakeMessagePayload as Codec>::encode.

Marking as P-critical as determined by WG-prioritization.

Ahh okay. Thanks

This looks like a mir-opt bug to me: https://godbolt.org/z/n86G5M

cc @rust-lang/wg-mir-opt

#[derive(Copy, Clone)]
#[repr(u8)]
pub enum Type {
    A = 1,
    B = 7,
}


pub fn encode(v: &Type) -> Type {
    match v {
        Type::A => Type::B,
        _ => *v,
    }
}

with --emit=mir

fn encode(_1: &Type) -> Type {
    debug v => _1;                       // in scope 0 at ./example.rs:9:15: 9:16
    let mut _0: Type;                    // return place in scope 0 at ./example.rs:9:28: 9:32

    bb0: {
        _0 = (*_1);                      // scope 0 at ./example.rs:12:14: 12:16
        return;                          // scope 0 at ./example.rs:14:2: 14:2
    }
}

edit: fn encode(v: Type) has the same bug, so it is not necessarily related to references

simpler repro: https://godbolt.org/z/3cdfa8

pub enum Type {
    A,
    B,
}


pub fn encode(v: Type) -> Type {
    match v {
        Type::A => Type::B,
        _ => v,
    }
}

It was already bisected to that PR in https://github.com/rust-lang/rust/issues/76803#issuecomment-693636886

This repros on beta, so this is a stable-to-beta regression.

https://github.com/rust-lang/rust/blob/33c96b4d9782cf6364e47cb2c904e66b06c22bb4/src/librustc_mir/transform/simplify_try.rs#L661-L671

This fails to consider that the discriminant value assigned in bb1 might not be the discriminant of _1, as happens here.

    bb0: {
        _2 = discriminant(_1);           // scope 0 at src/test/mir-opt/issue-76803.rs:12:9: 12:16
        switchInt(move _2) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at src/test/mir-opt/issue-76803.rs:12:9: 12:16
        //                     ^^^^^^^ not the same value!
    }

    bb1: {
        _0 = move _1;                    // scope 0 at src/test/mir-opt/issue-76803.rs:13:14: 13:15
        goto -> bb3;                     // scope 0 at src/test/mir-opt/issue-76803.rs:11:5: 14:6
    }

    bb2: {
        discriminant(_0) = 1;            // scope 0 at src/test/mir-opt/issue-76803.rs:12:20: 12:27
        //                 ^ not the same value!
        goto -> bb3;                     // scope 0 at src/test/mir-opt/issue-76803.rs:11:5: 14:6
    }

I opened a PR to disable the logic and nominated it for beta backport.

I'm re-opening to track the beta-backport. Once that is completed, we can close this.

The beta backport has landed (#77308). Closing this issue.

Was this page helpful?
0 / 5 - 0 ratings