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.
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.
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,
}
}
Wild guess: https://github.com/rust-lang/rust/pull/74748
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.
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.
Most helpful comment