You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@teaclave.apache.org by rd...@apache.org on 2022/11/15 01:14:47 UTC

[incubator-teaclave-sgx-sdk] branch master updated (c52d76bc -> c3d82372)

This is an automated email from the ASF dual-hosted git repository.

rduan pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-teaclave-sgx-sdk.git


    from c52d76bc fix libunwind autogen script when mitigations are on
     new e32abc08 Support rust-nightly-2022-10-22 and Bump version to 1.1.6
     new 5346c066 Add epoll_create for sgx_libc
     new c3d82372 Fix mio samplecode

The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 edl/sgx_fd.edl                                     |   10 +
 rust-toolchain                                     |    2 +-
 samplecode/mio/client-go/ca.cert                   |   77 +-
 samplecode/mio/client-java/ca.cert                 |   77 +-
 samplecode/mio/client/bin/ca.cert                  |   77 +-
 samplecode/mio/client/enclave/src/lib.rs           |    5 +-
 samplecode/mio/server/bin/end.fullchain            |  172 +--
 samplecode/mio/server/bin/end.rsa                  |   50 +-
 samplecode/mio/server/enclave/src/lib.rs           |    3 +-
 samplecode/project_template/app/rust-toolchain     |    2 +-
 samplecode/project_template/enclave/rust-toolchain |    2 +-
 samplecode/tls/tlsclient/bin/ca.cert               |   77 +-
 samplecode/tls/tlsserver/bin/end.fullchain         |  172 +--
 samplecode/tls/tlsserver/bin/end.rsa               |   50 +-
 sgx_align_struct_attribute/Cargo.toml              |    2 +-
 sgx_align_struct_attribute/src/layout.rs           |    2 +-
 sgx_alloc/Cargo.toml                               |    2 +-
 sgx_alloc/src/alignalloc.rs                        |    2 +-
 sgx_alloc/src/alignbox.rs                          |    8 +-
 sgx_backtrace/Cargo.toml                           |    2 +-
 sgx_backtrace_sys/Cargo.toml                       |    2 +-
 sgx_build_helper/Cargo.toml                        |    2 +-
 sgx_cov/Cargo.toml                                 |    2 +-
 sgx_crypto_helper/Cargo.toml                       |    2 +-
 sgx_demangle/Cargo.toml                            |    2 +-
 sgx_edl/Cargo.toml                                 |    2 +-
 sgx_edl/edl/sgx_fd.edl                             |   10 +
 sgx_libc/Cargo.toml                                |    2 +-
 sgx_libc/src/android/mod.rs                        |    2 +-
 sgx_libc/src/lib.rs                                |    1 +
 sgx_libc/src/linux/x86_64/mod.rs                   |   23 +-
 sgx_libc/src/linux/x86_64/ocall.rs                 |  217 ++-
 sgx_no_tstd/Cargo.toml                             |    2 +-
 sgx_panic_abort/src/lib.rs                         |   15 +-
 sgx_panic_unwind/src/gcc.rs                        |   78 -
 sgx_panic_unwind/src/lib.rs                        |   16 +-
 sgx_rand/Cargo.toml                                |    2 +-
 sgx_rand_derive/Cargo.toml                         |    2 +-
 sgx_serialize/Cargo.toml                           |    2 +-
 sgx_serialize_derive/Cargo.toml                    |    2 +-
 sgx_serialize_derive_internals/Cargo.toml          |    2 +-
 sgx_signal/Cargo.toml                              |    2 +-
 sgx_signal/src/exception.rs                        |   28 +-
 sgx_signal/src/manager.rs                          |   31 +-
 sgx_tcrypto/Cargo.toml                             |    2 +-
 sgx_tcrypto_helper/Cargo.toml                      |    2 +-
 sgx_tdh/Cargo.toml                                 |    2 +-
 sgx_tkey_exchange/Cargo.toml                       |    2 +-
 sgx_tprotected_fs/Cargo.toml                       |    2 +-
 sgx_trts/Cargo.toml                                |    2 +-
 sgx_trts/src/c_str.rs                              | 1533 +-------------------
 sgx_trts/src/lib.rs                                |    1 -
 sgx_tse/Cargo.toml                                 |    2 +-
 sgx_tseal/Cargo.toml                               |    2 +-
 sgx_tstd/Cargo.toml                                |    2 +-
 sgx_tstd/src/alloc.rs                              |   29 +-
 sgx_tstd/src/backtrace.rs                          |   15 +-
 sgx_tstd/src/collections/hash/map.rs               |  258 +++-
 sgx_tstd/src/collections/hash/set.rs               |  107 +-
 sgx_tstd/src/collections/mod.rs                    |    9 +-
 sgx_tstd/src/enclave.rs                            |    2 +-
 sgx_tstd/src/env.rs                                |   73 +-
 sgx_tstd/src/error.rs                              |  886 +----------
 sgx_tstd/src/f32.rs                                |   68 +-
 sgx_tstd/src/f64.rs                                |   70 +-
 sgx_tstd/src/ffi/c_str.rs                          |   55 -
 sgx_tstd/src/ffi/mod.rs                            |   15 +-
 sgx_tstd/src/ffi/os_str.rs                         |   84 +-
 sgx_tstd/src/fs.rs                                 |  169 ++-
 sgx_tstd/src/io/buffered/bufreader.rs              |  105 +-
 sgx_tstd/src/io/buffered/bufreader/buffer.rs       |  139 ++
 sgx_tstd/src/io/buffered/bufwriter.rs              |    4 +-
 sgx_tstd/src/io/buffered/linewriter.rs             |    4 +-
 sgx_tstd/src/io/copy.rs                            |   46 +-
 sgx_tstd/src/io/cursor.rs                          |  182 ++-
 sgx_tstd/src/io/error.rs                           |  108 +-
 sgx_tstd/src/io/error/repr_unpacked.rs             |    6 +-
 sgx_tstd/src/io/impls.rs                           |   62 +-
 sgx_tstd/src/io/mod.rs                             |  194 ++-
 sgx_tstd/src/io/readbuf.rs                         |  316 ++--
 sgx_tstd/src/io/stdio.rs                           |  478 +++---
 sgx_tstd/src/io/util.rs                            |   14 +-
 sgx_tstd/src/lib.rs                                |  140 +-
 sgx_tstd/src/macros.rs                             |   66 +-
 sgx_tstd/src/net/display_buffer.rs                 |   57 +
 sgx_tstd/src/net/{ip.rs => ip_addr.rs}             |  413 +++---
 sgx_tstd/src/net/mod.rs                            |   22 +-
 sgx_tstd/src/net/parser.rs                         |  158 +-
 sgx_tstd/src/net/{addr.rs => socket_addr.rs}       |  236 ++-
 sgx_tstd/src/net/tcp.rs                            |   15 +-
 sgx_tstd/src/net/udp.rs                            |   14 +-
 sgx_tstd/src/os/fd/mod.rs                          |   12 +-
 sgx_tstd/src/os/fd/owned.rs                        |  130 +-
 sgx_tstd/src/os/fd/raw.rs                          |   87 +-
 sgx_tstd/src/os/linux/fs.rs                        |   26 +-
 sgx_tstd/src/os/linux/mod.rs                       |    2 +
 sgx_tstd/src/os/linux/{mod.rs => net.rs}           |    5 +-
 sgx_tstd/src/os/linux/raw.rs                       |    4 +-
 sgx_tstd/src/os/mod.rs                             |    4 +-
 sgx_tstd/src/os/{unix/io/fd.rs => net/mod.rs}      |    5 +-
 sgx_tstd/src/os/net/tcp.rs                         |   82 ++
 sgx_tstd/src/os/raw/mod.rs                         |   89 +-
 sgx_tstd/src/os/unix/fs.rs                         |    4 +-
 sgx_tstd/src/os/unix/io/mod.rs                     |   70 +-
 sgx_tstd/src/os/unix/io/raw.rs                     |   20 -
 sgx_tstd/src/os/unix/net/addr.rs                   |   37 +-
 sgx_tstd/src/os/unix/net/ancillary.rs              |   16 +-
 sgx_tstd/src/os/unix/net/datagram.rs               |   40 +-
 sgx_tstd/src/os/unix/net/listener.rs               |   10 +-
 sgx_tstd/src/os/unix/net/stream.rs                 |   34 +-
 sgx_tstd/src/panicking.rs                          |  184 ++-
 sgx_tstd/src/path.rs                               |   76 +-
 .../src/lib.rs => sgx_tstd/src/personality.rs      |   19 +-
 .../src => sgx_tstd/src/personality}/dwarf/eh.rs   |   32 +-
 .../src => sgx_tstd/src/personality}/dwarf/mod.rs  |   19 +-
 .../src => sgx_tstd/src/personality}/gcc.rs        |   89 +-
 sgx_tstd/src/prelude/mod.rs                        |   11 +
 sgx_tstd/src/rt.rs                                 |   17 +-
 sgx_tstd/src/sync/condvar.rs                       |   53 +-
 sgx_tstd/src/sync/lazy_lock.rs                     |  129 ++
 sgx_tstd/src/sync/mod.rs                           |   15 +-
 sgx_tstd/src/sync/mpsc/blocking.rs                 |   13 +-
 sgx_tstd/src/sync/mpsc/mod.rs                      |   20 +-
 sgx_tstd/src/sync/mpsc/oneshot.rs                  |   24 +-
 sgx_tstd/src/sync/mpsc/shared.rs                   |   33 +-
 sgx_tstd/src/sync/mpsc/stream.rs                   |   31 +-
 sgx_tstd/src/sync/mpsc/sync.rs                     |    1 +
 sgx_tstd/src/sync/mutex.rs                         |   91 +-
 sgx_tstd/src/sync/once.rs                          |  301 +---
 sgx_tstd/src/{lazy.rs => sync/once_lock.rs}        |  374 ++---
 sgx_tstd/src/sync/poison.rs                        |   17 +-
 sgx_tstd/src/sync/rwlock.rs                        |  198 ++-
 sgx_tstd/src/sys/backtrace/mod.rs                  |    3 +-
 .../src/lib.rs => sgx_tstd/src/sys/common/mod.rs   |    2 +-
 sgx_tstd/src/sys/common/small_c_string.rs          |   70 +
 sgx_tstd/src/sys/fd.rs                             |   17 +-
 sgx_tstd/src/sys/fs.rs                             |  288 ++--
 sgx_tstd/src/sys/io.rs                             |   18 +-
 sgx_tstd/src/sys/kernel_copy.rs                    |  669 +++++++++
 sgx_tstd/src/sys/{ => locks}/condvar.rs            |  143 +-
 .../src/{collections/hash => sys/locks}/mod.rs     |   10 +-
 sgx_tstd/src/sys/{ => locks}/mutex.rs              |  490 ++++---
 sgx_tstd/src/sys/{ => locks}/rwlock.rs             |  233 +--
 sgx_tstd/src/sys/mod.rs                            |   10 +-
 sgx_tstd/src/sys/net.rs                            |   22 +-
 sgx_tstd/src/sys/os.rs                             |   74 +-
 sgx_tstd/src/sys/os_str.rs                         |   40 +-
 sgx_tstd/src/sys/path.rs                           |    3 +-
 sgx_tstd/src/sys/sgxfs.rs                          |    4 +-
 sgx_tstd/src/sys/stdio.rs                          |   46 +-
 sgx_tstd/src/sys/thread_local_dtor.rs              |   10 +-
 sgx_tstd/src/sys/thread_local_key.rs               |    5 -
 sgx_tstd/src/sys/time.rs                           |  206 +--
 sgx_tstd/src/sys_common/at_exit_imp.rs             |   21 +-
 sgx_tstd/src/sys_common/backtrace.rs               |   21 +-
 sgx_tstd/src/sys_common/condvar.rs                 |  107 +-
 sgx_tstd/src/sys_common/condvar/check.rs           |   48 +-
 sgx_tstd/src/sys_common/lazy_box.rs                |  107 ++
 sgx_tstd/src/sys_common/mod.rs                     |    2 +
 sgx_tstd/src/sys_common/mutex.rs                   |  251 +---
 sgx_tstd/src/sys_common/net.rs                     |  143 +-
 sgx_tstd/src/sys_common/once/generic.rs            |  298 ++++
 sgx_tstd/src/sys_common/once/mod.rs                |   46 +
 sgx_tstd/src/sys_common/remutex.rs                 |   79 +-
 sgx_tstd/src/sys_common/rwlock.rs                  |  149 +-
 sgx_tstd/src/sys_common/thread_info.rs             |    2 +-
 sgx_tstd/src/sys_common/thread_local_dtor.rs       |   14 +-
 sgx_tstd/src/sys_common/thread_local_key.rs        |   27 +-
 sgx_tstd/src/sys_common/thread_parker/generic.rs   |   27 +-
 sgx_tstd/src/sys_common/wtf8.rs                    |  101 +-
 sgx_tstd/src/thread/local.rs                       |  495 ++++++-
 sgx_tstd/src/thread/mod.rs                         |  264 +++-
 sgx_tstd/src/thread/scoped.rs                      |   94 +-
 sgx_tstd/src/time.rs                               |   29 +-
 sgx_tstd/src/untrusted/time.rs                     |   10 +-
 sgx_tunittest/Cargo.toml                           |    2 +-
 sgx_types/Cargo.toml                               |    2 +-
 sgx_types/src/error.rs                             |    8 +
 sgx_types/src/lib.rs                               |    1 +
 sgx_types/src/macros.rs                            |   75 +-
 sgx_types/src/types.rs                             |    5 +-
 sgx_ucrypto/Cargo.toml                             |    2 +-
 sgx_unwind/Cargo.toml                              |    2 +-
 sgx_unwind/src/lib.rs                              |    1 -
 sgx_urts/Cargo.toml                                |    2 +-
 sgx_urts/src/fd.rs                                 |  139 +-
 sgx_ustdc/fd.c                                     |   72 +-
 187 files changed, 7859 insertions(+), 6988 deletions(-)
 delete mode 100644 sgx_tstd/src/ffi/c_str.rs
 create mode 100644 sgx_tstd/src/io/buffered/bufreader/buffer.rs
 create mode 100644 sgx_tstd/src/net/display_buffer.rs
 rename sgx_tstd/src/net/{ip.rs => ip_addr.rs} (84%)
 rename sgx_tstd/src/net/{addr.rs => socket_addr.rs} (83%)
 copy sgx_tstd/src/os/linux/{mod.rs => net.rs} (88%)
 rename sgx_tstd/src/os/{unix/io/fd.rs => net/mod.rs} (91%)
 create mode 100644 sgx_tstd/src/os/net/tcp.rs
 delete mode 100644 sgx_tstd/src/os/unix/io/raw.rs
 copy sgx_serialize_derive_internals/src/lib.rs => sgx_tstd/src/personality.rs (61%)
 rename {sgx_panic_unwind/src => sgx_tstd/src/personality}/dwarf/eh.rs (85%)
 rename {sgx_panic_unwind/src => sgx_tstd/src/personality}/dwarf/mod.rs (69%)
 copy {sgx_panic_unwind/src => sgx_tstd/src/personality}/gcc.rs (71%)
 create mode 100644 sgx_tstd/src/sync/lazy_lock.rs
 rename sgx_tstd/src/{lazy.rs => sync/once_lock.rs} (57%)
 copy sgx_edl/src/lib.rs => sgx_tstd/src/sys/common/mod.rs (97%)
 create mode 100644 sgx_tstd/src/sys/common/small_c_string.rs
 create mode 100644 sgx_tstd/src/sys/kernel_copy.rs
 rename sgx_tstd/src/sys/{ => locks}/condvar.rs (77%)
 copy sgx_tstd/src/{collections/hash => sys/locks}/mod.rs (75%)
 rename sgx_tstd/src/sys/{ => locks}/mutex.rs (71%)
 rename sgx_tstd/src/sys/{ => locks}/rwlock.rs (81%)
 create mode 100644 sgx_tstd/src/sys_common/lazy_box.rs
 create mode 100644 sgx_tstd/src/sys_common/once/generic.rs
 create mode 100644 sgx_tstd/src/sys_common/once/mod.rs


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@teaclave.apache.org
For additional commands, e-mail: commits-help@teaclave.apache.org


[incubator-teaclave-sgx-sdk] 03/03: Fix mio samplecode

Posted by rd...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rduan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-teaclave-sgx-sdk.git

commit c3d82372dff81e5bafb07f71bc8ad532d06b504e
Author: volcano0dr <vo...@163.com>
AuthorDate: Sat Nov 5 22:16:19 2022 +0800

    Fix mio samplecode
---
 samplecode/mio/client/enclave/src/lib.rs | 5 +++--
 samplecode/mio/server/enclave/src/lib.rs | 3 ++-
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/samplecode/mio/client/enclave/src/lib.rs b/samplecode/mio/client/enclave/src/lib.rs
index 6e1381c6..a539db42 100644
--- a/samplecode/mio/client/enclave/src/lib.rs
+++ b/samplecode/mio/client/enclave/src/lib.rs
@@ -27,7 +27,7 @@ extern crate sgx_tstd as std;
 
 use std::collections;
 use std::untrusted::fs;
-use std::net::SocketAddr;
+use std::net::{self, SocketAddr};
 use std::str;
 use std::io;
 use std::string::String;
@@ -337,7 +337,8 @@ pub extern "C" fn run_client() {
     let flag_http = true;
 
     let config = make_config(cert);
-    let sock = TcpStream::connect(&addr).unwrap();
+    let stream = net::TcpStream::connect(&addr).expect("connect failed");
+    let sock = TcpStream::from_stream(stream).unwrap();
 
     let dns_name = webpki::DNSNameRef::try_from_ascii_str(hostname).unwrap();
     let mut tlsclient = TlsClient::new(sock, dns_name, config);
diff --git a/samplecode/mio/server/enclave/src/lib.rs b/samplecode/mio/server/enclave/src/lib.rs
index 4013e3ed..2560d59c 100644
--- a/samplecode/mio/server/enclave/src/lib.rs
+++ b/samplecode/mio/server/enclave/src/lib.rs
@@ -439,7 +439,8 @@ pub extern "C" fn run_server(max_conn: uint8_t) {
 
     let config = make_config(cert, key);
 
-    let listener = TcpListener::bind(&addr).expect("cannot listen on port");
+    let listener = net::TcpListener::bind(&addr).expect("cannot listen on port");
+    let listener = TcpListener::from_std(listener).unwrap();
     let mut poll = mio::Poll::new()
         .unwrap();
     poll.register(&listener,


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@teaclave.apache.org
For additional commands, e-mail: commits-help@teaclave.apache.org


[incubator-teaclave-sgx-sdk] 01/03: Support rust-nightly-2022-10-22 and Bump version to 1.1.6

Posted by rd...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rduan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-teaclave-sgx-sdk.git

commit e32abc08c0a902d71cb4d93c34a6cab3dc2278ac
Author: volcano <vo...@163.com>
AuthorDate: Sun Oct 23 00:48:29 2022 +0800

    Support rust-nightly-2022-10-22 and Bump version to 1.1.6
---
 edl/sgx_fd.edl                                     |   10 +
 rust-toolchain                                     |    2 +-
 samplecode/mio/client-go/ca.cert                   |   77 +-
 samplecode/mio/client-java/ca.cert                 |   77 +-
 samplecode/mio/client/bin/ca.cert                  |   77 +-
 samplecode/mio/server/bin/end.fullchain            |  172 +--
 samplecode/mio/server/bin/end.rsa                  |   50 +-
 samplecode/project_template/app/rust-toolchain     |    2 +-
 samplecode/project_template/enclave/rust-toolchain |    2 +-
 samplecode/tls/tlsclient/bin/ca.cert               |   77 +-
 samplecode/tls/tlsserver/bin/end.fullchain         |  172 +--
 samplecode/tls/tlsserver/bin/end.rsa               |   50 +-
 sgx_align_struct_attribute/Cargo.toml              |    2 +-
 sgx_align_struct_attribute/src/layout.rs           |    2 +-
 sgx_alloc/Cargo.toml                               |    2 +-
 sgx_alloc/src/alignalloc.rs                        |    2 +-
 sgx_alloc/src/alignbox.rs                          |    8 +-
 sgx_backtrace/Cargo.toml                           |    2 +-
 sgx_backtrace_sys/Cargo.toml                       |    2 +-
 sgx_build_helper/Cargo.toml                        |    2 +-
 sgx_cov/Cargo.toml                                 |    2 +-
 sgx_crypto_helper/Cargo.toml                       |    2 +-
 sgx_demangle/Cargo.toml                            |    2 +-
 sgx_edl/Cargo.toml                                 |    2 +-
 sgx_edl/edl/sgx_fd.edl                             |   10 +
 sgx_libc/Cargo.toml                                |    2 +-
 sgx_libc/src/lib.rs                                |    1 +
 sgx_libc/src/linux/x86_64/mod.rs                   |   21 +-
 sgx_libc/src/linux/x86_64/ocall.rs                 |  209 ++-
 sgx_no_tstd/Cargo.toml                             |    2 +-
 sgx_panic_abort/src/lib.rs                         |   15 +-
 sgx_panic_unwind/src/gcc.rs                        |   78 -
 sgx_panic_unwind/src/lib.rs                        |   16 +-
 sgx_rand/Cargo.toml                                |    2 +-
 sgx_rand_derive/Cargo.toml                         |    2 +-
 sgx_serialize/Cargo.toml                           |    2 +-
 sgx_serialize_derive/Cargo.toml                    |    2 +-
 sgx_serialize_derive_internals/Cargo.toml          |    2 +-
 sgx_signal/Cargo.toml                              |    2 +-
 sgx_signal/src/exception.rs                        |   28 +-
 sgx_signal/src/manager.rs                          |   31 +-
 sgx_tcrypto/Cargo.toml                             |    2 +-
 sgx_tcrypto_helper/Cargo.toml                      |    2 +-
 sgx_tdh/Cargo.toml                                 |    2 +-
 sgx_tkey_exchange/Cargo.toml                       |    2 +-
 sgx_tprotected_fs/Cargo.toml                       |    2 +-
 sgx_trts/Cargo.toml                                |    2 +-
 sgx_trts/src/c_str.rs                              | 1533 +-------------------
 sgx_trts/src/lib.rs                                |    1 -
 sgx_tse/Cargo.toml                                 |    2 +-
 sgx_tseal/Cargo.toml                               |    2 +-
 sgx_tstd/Cargo.toml                                |    2 +-
 sgx_tstd/src/alloc.rs                              |   29 +-
 sgx_tstd/src/backtrace.rs                          |   15 +-
 sgx_tstd/src/collections/hash/map.rs               |  258 +++-
 sgx_tstd/src/collections/hash/set.rs               |  107 +-
 sgx_tstd/src/collections/mod.rs                    |    9 +-
 sgx_tstd/src/enclave.rs                            |    2 +-
 sgx_tstd/src/env.rs                                |   73 +-
 sgx_tstd/src/error.rs                              |  886 +----------
 sgx_tstd/src/f32.rs                                |   68 +-
 sgx_tstd/src/f64.rs                                |   70 +-
 sgx_tstd/src/ffi/c_str.rs                          |   55 -
 sgx_tstd/src/ffi/mod.rs                            |   15 +-
 sgx_tstd/src/ffi/os_str.rs                         |   84 +-
 sgx_tstd/src/fs.rs                                 |  169 ++-
 sgx_tstd/src/io/buffered/bufreader.rs              |  105 +-
 sgx_tstd/src/io/buffered/bufreader/buffer.rs       |  139 ++
 sgx_tstd/src/io/buffered/bufwriter.rs              |    4 +-
 sgx_tstd/src/io/buffered/linewriter.rs             |    4 +-
 sgx_tstd/src/io/copy.rs                            |   46 +-
 sgx_tstd/src/io/cursor.rs                          |  182 ++-
 sgx_tstd/src/io/error.rs                           |  108 +-
 sgx_tstd/src/io/error/repr_unpacked.rs             |    6 +-
 sgx_tstd/src/io/impls.rs                           |   62 +-
 sgx_tstd/src/io/mod.rs                             |  194 ++-
 sgx_tstd/src/io/readbuf.rs                         |  316 ++--
 sgx_tstd/src/io/stdio.rs                           |  478 +++---
 sgx_tstd/src/io/util.rs                            |   14 +-
 sgx_tstd/src/lib.rs                                |  140 +-
 sgx_tstd/src/macros.rs                             |   66 +-
 sgx_tstd/src/net/display_buffer.rs                 |   57 +
 sgx_tstd/src/net/{ip.rs => ip_addr.rs}             |  413 +++---
 sgx_tstd/src/net/mod.rs                            |   22 +-
 sgx_tstd/src/net/parser.rs                         |  158 +-
 sgx_tstd/src/net/{addr.rs => socket_addr.rs}       |  236 ++-
 sgx_tstd/src/net/tcp.rs                            |   15 +-
 sgx_tstd/src/net/udp.rs                            |   14 +-
 sgx_tstd/src/os/fd/mod.rs                          |   12 +-
 sgx_tstd/src/os/fd/owned.rs                        |  130 +-
 sgx_tstd/src/os/fd/raw.rs                          |   87 +-
 sgx_tstd/src/os/linux/fs.rs                        |   26 +-
 sgx_tstd/src/os/linux/mod.rs                       |    2 +
 sgx_tstd/src/os/{unix/io/fd.rs => linux/net.rs}    |    4 +-
 sgx_tstd/src/os/linux/raw.rs                       |    4 +-
 sgx_tstd/src/os/mod.rs                             |    4 +-
 sgx_tstd/src/os/{unix/io/raw.rs => net/mod.rs}     |    5 +-
 sgx_tstd/src/os/net/tcp.rs                         |   82 ++
 sgx_tstd/src/os/raw/mod.rs                         |   89 +-
 sgx_tstd/src/os/unix/fs.rs                         |    4 +-
 sgx_tstd/src/os/unix/io/mod.rs                     |   70 +-
 sgx_tstd/src/os/unix/net/addr.rs                   |   37 +-
 sgx_tstd/src/os/unix/net/ancillary.rs              |   16 +-
 sgx_tstd/src/os/unix/net/datagram.rs               |   40 +-
 sgx_tstd/src/os/unix/net/listener.rs               |   10 +-
 sgx_tstd/src/os/unix/net/stream.rs                 |   34 +-
 sgx_tstd/src/panicking.rs                          |  184 ++-
 sgx_tstd/src/path.rs                               |   76 +-
 sgx_tstd/src/{os/fd/mod.rs => personality.rs}      |   25 +-
 .../src => sgx_tstd/src/personality}/dwarf/eh.rs   |   32 +-
 .../src => sgx_tstd/src/personality}/dwarf/mod.rs  |   19 +-
 .../src => sgx_tstd/src/personality}/gcc.rs        |   89 +-
 sgx_tstd/src/prelude/mod.rs                        |   11 +
 sgx_tstd/src/rt.rs                                 |   17 +-
 sgx_tstd/src/sync/condvar.rs                       |   53 +-
 sgx_tstd/src/sync/lazy_lock.rs                     |  129 ++
 sgx_tstd/src/sync/mod.rs                           |   15 +-
 sgx_tstd/src/sync/mpsc/blocking.rs                 |   13 +-
 sgx_tstd/src/sync/mpsc/mod.rs                      |   20 +-
 sgx_tstd/src/sync/mpsc/oneshot.rs                  |   24 +-
 sgx_tstd/src/sync/mpsc/shared.rs                   |   33 +-
 sgx_tstd/src/sync/mpsc/stream.rs                   |   31 +-
 sgx_tstd/src/sync/mpsc/sync.rs                     |    1 +
 sgx_tstd/src/sync/mutex.rs                         |   91 +-
 sgx_tstd/src/sync/once.rs                          |  301 +---
 sgx_tstd/src/{lazy.rs => sync/once_lock.rs}        |  374 ++---
 sgx_tstd/src/sync/poison.rs                        |   17 +-
 sgx_tstd/src/sync/rwlock.rs                        |  198 ++-
 sgx_tstd/src/sys/backtrace/mod.rs                  |    3 +-
 .../src/{os/unix/io/fd.rs => sys/common/mod.rs}    |    4 +-
 sgx_tstd/src/sys/common/small_c_string.rs          |   70 +
 sgx_tstd/src/sys/fd.rs                             |   17 +-
 sgx_tstd/src/sys/fs.rs                             |  288 ++--
 sgx_tstd/src/sys/io.rs                             |   18 +-
 sgx_tstd/src/sys/kernel_copy.rs                    |  669 +++++++++
 sgx_tstd/src/sys/{ => locks}/condvar.rs            |  143 +-
 sgx_tstd/src/{os => sys/locks}/mod.rs              |   13 +-
 sgx_tstd/src/sys/{ => locks}/mutex.rs              |  490 ++++---
 sgx_tstd/src/sys/{ => locks}/rwlock.rs             |  233 +--
 sgx_tstd/src/sys/mod.rs                            |   10 +-
 sgx_tstd/src/sys/net.rs                            |   22 +-
 sgx_tstd/src/sys/os.rs                             |   74 +-
 sgx_tstd/src/sys/os_str.rs                         |   40 +-
 sgx_tstd/src/sys/path.rs                           |    3 +-
 sgx_tstd/src/sys/sgxfs.rs                          |    4 +-
 sgx_tstd/src/sys/stdio.rs                          |   46 +-
 sgx_tstd/src/sys/thread_local_dtor.rs              |   10 +-
 sgx_tstd/src/sys/thread_local_key.rs               |    5 -
 sgx_tstd/src/sys/time.rs                           |  206 +--
 sgx_tstd/src/sys_common/at_exit_imp.rs             |   21 +-
 sgx_tstd/src/sys_common/backtrace.rs               |   21 +-
 sgx_tstd/src/sys_common/condvar.rs                 |  107 +-
 sgx_tstd/src/sys_common/condvar/check.rs           |   48 +-
 sgx_tstd/src/sys_common/lazy_box.rs                |  107 ++
 sgx_tstd/src/sys_common/mod.rs                     |    2 +
 sgx_tstd/src/sys_common/mutex.rs                   |  251 +---
 sgx_tstd/src/sys_common/net.rs                     |  143 +-
 sgx_tstd/src/sys_common/once/generic.rs            |  298 ++++
 sgx_tstd/src/sys_common/once/mod.rs                |   46 +
 sgx_tstd/src/sys_common/remutex.rs                 |   79 +-
 sgx_tstd/src/sys_common/rwlock.rs                  |  149 +-
 sgx_tstd/src/sys_common/thread_info.rs             |    2 +-
 sgx_tstd/src/sys_common/thread_local_dtor.rs       |   14 +-
 sgx_tstd/src/sys_common/thread_local_key.rs        |   27 +-
 sgx_tstd/src/sys_common/thread_parker/generic.rs   |   27 +-
 sgx_tstd/src/sys_common/wtf8.rs                    |  101 +-
 sgx_tstd/src/thread/local.rs                       |  495 ++++++-
 sgx_tstd/src/thread/mod.rs                         |  264 +++-
 sgx_tstd/src/thread/scoped.rs                      |   94 +-
 sgx_tstd/src/time.rs                               |   29 +-
 sgx_tstd/src/untrusted/time.rs                     |   10 +-
 sgx_tunittest/Cargo.toml                           |    2 +-
 sgx_types/Cargo.toml                               |    2 +-
 sgx_types/src/error.rs                             |    8 +
 sgx_types/src/lib.rs                               |    1 +
 sgx_types/src/macros.rs                            |   75 +-
 sgx_types/src/types.rs                             |    5 +-
 sgx_ucrypto/Cargo.toml                             |    2 +-
 sgx_unwind/Cargo.toml                              |    2 +-
 sgx_unwind/src/lib.rs                              |    1 -
 sgx_urts/Cargo.toml                                |    2 +-
 sgx_urts/src/fd.rs                                 |  139 +-
 sgx_ustdc/fd.c                                     |   72 +-
 183 files changed, 7848 insertions(+), 6969 deletions(-)

diff --git a/edl/sgx_fd.edl b/edl/sgx_fd.edl
index 8cfc822e..cd668b71 100644
--- a/edl/sgx_fd.edl
+++ b/edl/sgx_fd.edl
@@ -19,6 +19,7 @@ enclave {
 
     include "inc/stat.h"
     include "sys/uio.h"
+    include "time.h"
 
     from "sgx_mem.edl" import *;
 
@@ -37,11 +38,20 @@ enclave {
         size_t u_writev_ocall([out] int *error, int fd, [in, count=iovcnt] const struct iovec *iov, int iovcnt);
         size_t u_pwritev64_ocall([out] int *error, int fd, [in, count=iovcnt] const struct iovec *iov, int iovcnt, int64_t offset);
 
+        size_t u_sendfile_ocall([out] int *error, int out_fd, int in_fd, [in, out] int64_t *offset, size_t count);
+        size_t u_copy_file_range_ocall([out] int *error, int fd_in, [in, out] int64_t *off_in, int fd_out, [in, out] int64_t *off_out, size_t len, unsigned int flags);
+        size_t u_splice_ocall([out] int *error, int fd_in, [in, out] int64_t *off_in, int fd_out, [in, out] int64_t *off_out, size_t len, unsigned int flags);
+
         int u_fcntl_arg0_ocall([out] int *error, int fd, int cmd);
         int u_fcntl_arg1_ocall([out] int *error, int fd, int cmd, int arg);
         int u_ioctl_arg0_ocall([out] int *error, int fd, int request);
         int u_ioctl_arg1_ocall([out] int *error, int fd, int request, [in, out] int *arg);
 
         int u_close_ocall([out] int *error, int fd);
+        int u_isatty_ocall([out] int *error, int fd);
+        int u_dup_ocall([out] int *error, int oldfd);
+        int u_eventfd_ocall([out] int *error, unsigned int initval, int flags);
+
+        int u_futimens_ocall([out] int *error, int fd, [in, count=2] const struct timespec *times);
     };
 };
diff --git a/rust-toolchain b/rust-toolchain
index 4e7e21b0..0f99c85c 100644
--- a/rust-toolchain
+++ b/rust-toolchain
@@ -1 +1 @@
-nightly-2022-02-23
\ No newline at end of file
+nightly-2022-10-22
\ No newline at end of file
diff --git a/samplecode/mio/client-go/ca.cert b/samplecode/mio/client-go/ca.cert
index a18fb02c..3a84cbe6 100644
--- a/samplecode/mio/client-go/ca.cert
+++ b/samplecode/mio/client-go/ca.cert
@@ -1,51 +1,30 @@
 -----BEGIN CERTIFICATE-----
-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
-9Xpi4ds6s2cT8zZGDKI=
+MIIFFTCCAv2gAwIBAgIUGXgsGl4sGhiPwUPOme5w5jJscVQwDQYJKoZIhvcNAQEL
+BQAwGjEYMBYGA1UEAwwPcG9ueXRvd24gUlNBIENBMB4XDTE5MDYwOTE3MTUxMVoX
+DTI5MDYwNjE3MTUxMVowGjEYMBYGA1UEAwwPcG9ueXRvd24gUlNBIENBMIICIjAN
+BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEArpW4WHfSmTCMvnDJaCRL5BR2knDc
+C+T4/wv7i//zsBL3q0YVdBpllWCZx8TSfuXT/1o/Zxdt+H1ZjnH8yuwuHOToE3W0
++Y/912hAPiD+d79A+MtqVX1gayjHDy9HybznTN2Onh1ZhWyks0FLL5SB0vVCLwXP
+W7tcyY0w6wn3RTw4nBu7co5a280cHgHv5V3XeNgteQrnkXE9TfuqqUZwVt0v1jr1
+bk1KaDDD+36wfeO70Q6CeLwKPhN0mPDHdj/lecj4efl0l1B0ehHxLkLuztqtkCF6
++yMoBrEyzJjO6TGMSTMsnw4F9bA15jkIIEQs5FhwVHFOTmu5BG+j37umoy27k5As
+5cV0/djr3r8WhBZ6w2+XjvbAdJPgqc+Xobnx1i5GI4noRC4G4Cl0Vx+iRru1/nsE
+xPazz9UVkiUsDlN9n49f1pik9z74Box6CD6IZVb8h4vV7um+0R4/eErVf/Cyf1Xe
+axVaOgA/CD0ucLdSfDz61O/2PG3P7YjWY1R9zr35e8pakgyFPXnWMbsfniuGkM0X
+6lG743Q7yVt38/HuAqi1AGq+r/AKisrezt97UNm0CryuEk02y4SVLbhuG/V6mBCh
+4Va3KD1ZOgfJcTZbuxebIz6W+5jL80hE0YwBBs8vSv8Fo5N7dYNSNvyMxkoPh8Gw
+CAFyqt5zBLGCEvkCAwEAAaNTMFEwHQYDVR0OBBYEFDjj6hEpDZdjAIdvd9Moe3un
+RvJWMB8GA1UdIwQYMBaAFDjj6hEpDZdjAIdvd9Moe3unRvJWMA8GA1UdEwEB/wQF
+MAMBAf8wDQYJKoZIhvcNAQELBQADggIBACu+Ct6J+Dh3EXFOgjW3gN3CaD0UK0kW
+03u7znNAJBAYhi+MXSTPBdrxYGOPkHF1Jl15qb2fc58+0nakf8bvah8kgxi2ujX8
+vrPBjsAv/ixPvUrcol9ZGrseP5DdFS8pw1FoDR/JdgNCdSM4xC3GSk2SLYs+QSJx
+YG3nQLOAZEvnbiZ4zBZ0wVct4w9jrxtqdq2eS8cLoRVx715MzKPBCGEccYu/py5a
+gkyclr16s0mb+wN49of34AQ+xXguHZGNZzCy6PTbx0IC+sRVe82+RZkj21JG+AFM
+9s+vLgRdtWIEZW1AIYbUUbhuvsne+sidZW5XQuFp1V4LlQbO49oEhrPMBn+oHKg5
+MWIe68bjkqDSnDzG+TEBTWiAhyyGyZcebfCs72DGbYrfKt1uTyi+groumPnvQfJB
+y3kqy2pUFeEkNJkx4BfYL+N7I07s9WTy8UMoqn/OLuyqoFaYMd9XMaOOx3xTy8aw
+pUJ69c3VI66W/Ii1ypk2EPUImWpG/n89Y/8Mk1NbesaZLk9feTDfbM4VNPkQU+7T
+3DNQxPSswSh4nXGURwC46SOu2s1lRA98ZXkP5XhUvTuvfg/e4suq26OqjORHQ5zI
+57NP+uHRrfHGlrQ196j1Maw7W7vkocbEv8/06v6s54CG8ezzD2nt1QrLJqSpUqHo
+qolvgn/PK+gg
 -----END CERTIFICATE-----
diff --git a/samplecode/mio/client-java/ca.cert b/samplecode/mio/client-java/ca.cert
index a18fb02c..3a84cbe6 100644
--- a/samplecode/mio/client-java/ca.cert
+++ b/samplecode/mio/client-java/ca.cert
@@ -1,51 +1,30 @@
 -----BEGIN CERTIFICATE-----
-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
-9Xpi4ds6s2cT8zZGDKI=
+MIIFFTCCAv2gAwIBAgIUGXgsGl4sGhiPwUPOme5w5jJscVQwDQYJKoZIhvcNAQEL
+BQAwGjEYMBYGA1UEAwwPcG9ueXRvd24gUlNBIENBMB4XDTE5MDYwOTE3MTUxMVoX
+DTI5MDYwNjE3MTUxMVowGjEYMBYGA1UEAwwPcG9ueXRvd24gUlNBIENBMIICIjAN
+BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEArpW4WHfSmTCMvnDJaCRL5BR2knDc
+C+T4/wv7i//zsBL3q0YVdBpllWCZx8TSfuXT/1o/Zxdt+H1ZjnH8yuwuHOToE3W0
++Y/912hAPiD+d79A+MtqVX1gayjHDy9HybznTN2Onh1ZhWyks0FLL5SB0vVCLwXP
+W7tcyY0w6wn3RTw4nBu7co5a280cHgHv5V3XeNgteQrnkXE9TfuqqUZwVt0v1jr1
+bk1KaDDD+36wfeO70Q6CeLwKPhN0mPDHdj/lecj4efl0l1B0ehHxLkLuztqtkCF6
++yMoBrEyzJjO6TGMSTMsnw4F9bA15jkIIEQs5FhwVHFOTmu5BG+j37umoy27k5As
+5cV0/djr3r8WhBZ6w2+XjvbAdJPgqc+Xobnx1i5GI4noRC4G4Cl0Vx+iRru1/nsE
+xPazz9UVkiUsDlN9n49f1pik9z74Box6CD6IZVb8h4vV7um+0R4/eErVf/Cyf1Xe
+axVaOgA/CD0ucLdSfDz61O/2PG3P7YjWY1R9zr35e8pakgyFPXnWMbsfniuGkM0X
+6lG743Q7yVt38/HuAqi1AGq+r/AKisrezt97UNm0CryuEk02y4SVLbhuG/V6mBCh
+4Va3KD1ZOgfJcTZbuxebIz6W+5jL80hE0YwBBs8vSv8Fo5N7dYNSNvyMxkoPh8Gw
+CAFyqt5zBLGCEvkCAwEAAaNTMFEwHQYDVR0OBBYEFDjj6hEpDZdjAIdvd9Moe3un
+RvJWMB8GA1UdIwQYMBaAFDjj6hEpDZdjAIdvd9Moe3unRvJWMA8GA1UdEwEB/wQF
+MAMBAf8wDQYJKoZIhvcNAQELBQADggIBACu+Ct6J+Dh3EXFOgjW3gN3CaD0UK0kW
+03u7znNAJBAYhi+MXSTPBdrxYGOPkHF1Jl15qb2fc58+0nakf8bvah8kgxi2ujX8
+vrPBjsAv/ixPvUrcol9ZGrseP5DdFS8pw1FoDR/JdgNCdSM4xC3GSk2SLYs+QSJx
+YG3nQLOAZEvnbiZ4zBZ0wVct4w9jrxtqdq2eS8cLoRVx715MzKPBCGEccYu/py5a
+gkyclr16s0mb+wN49of34AQ+xXguHZGNZzCy6PTbx0IC+sRVe82+RZkj21JG+AFM
+9s+vLgRdtWIEZW1AIYbUUbhuvsne+sidZW5XQuFp1V4LlQbO49oEhrPMBn+oHKg5
+MWIe68bjkqDSnDzG+TEBTWiAhyyGyZcebfCs72DGbYrfKt1uTyi+groumPnvQfJB
+y3kqy2pUFeEkNJkx4BfYL+N7I07s9WTy8UMoqn/OLuyqoFaYMd9XMaOOx3xTy8aw
+pUJ69c3VI66W/Ii1ypk2EPUImWpG/n89Y/8Mk1NbesaZLk9feTDfbM4VNPkQU+7T
+3DNQxPSswSh4nXGURwC46SOu2s1lRA98ZXkP5XhUvTuvfg/e4suq26OqjORHQ5zI
+57NP+uHRrfHGlrQ196j1Maw7W7vkocbEv8/06v6s54CG8ezzD2nt1QrLJqSpUqHo
+qolvgn/PK+gg
 -----END CERTIFICATE-----
diff --git a/samplecode/mio/client/bin/ca.cert b/samplecode/mio/client/bin/ca.cert
index a18fb02c..3a84cbe6 100644
--- a/samplecode/mio/client/bin/ca.cert
+++ b/samplecode/mio/client/bin/ca.cert
@@ -1,51 +1,30 @@
 -----BEGIN CERTIFICATE-----
-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
-9Xpi4ds6s2cT8zZGDKI=
+MIIFFTCCAv2gAwIBAgIUGXgsGl4sGhiPwUPOme5w5jJscVQwDQYJKoZIhvcNAQEL
+BQAwGjEYMBYGA1UEAwwPcG9ueXRvd24gUlNBIENBMB4XDTE5MDYwOTE3MTUxMVoX
+DTI5MDYwNjE3MTUxMVowGjEYMBYGA1UEAwwPcG9ueXRvd24gUlNBIENBMIICIjAN
+BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEArpW4WHfSmTCMvnDJaCRL5BR2knDc
+C+T4/wv7i//zsBL3q0YVdBpllWCZx8TSfuXT/1o/Zxdt+H1ZjnH8yuwuHOToE3W0
++Y/912hAPiD+d79A+MtqVX1gayjHDy9HybznTN2Onh1ZhWyks0FLL5SB0vVCLwXP
+W7tcyY0w6wn3RTw4nBu7co5a280cHgHv5V3XeNgteQrnkXE9TfuqqUZwVt0v1jr1
+bk1KaDDD+36wfeO70Q6CeLwKPhN0mPDHdj/lecj4efl0l1B0ehHxLkLuztqtkCF6
++yMoBrEyzJjO6TGMSTMsnw4F9bA15jkIIEQs5FhwVHFOTmu5BG+j37umoy27k5As
+5cV0/djr3r8WhBZ6w2+XjvbAdJPgqc+Xobnx1i5GI4noRC4G4Cl0Vx+iRru1/nsE
+xPazz9UVkiUsDlN9n49f1pik9z74Box6CD6IZVb8h4vV7um+0R4/eErVf/Cyf1Xe
+axVaOgA/CD0ucLdSfDz61O/2PG3P7YjWY1R9zr35e8pakgyFPXnWMbsfniuGkM0X
+6lG743Q7yVt38/HuAqi1AGq+r/AKisrezt97UNm0CryuEk02y4SVLbhuG/V6mBCh
+4Va3KD1ZOgfJcTZbuxebIz6W+5jL80hE0YwBBs8vSv8Fo5N7dYNSNvyMxkoPh8Gw
+CAFyqt5zBLGCEvkCAwEAAaNTMFEwHQYDVR0OBBYEFDjj6hEpDZdjAIdvd9Moe3un
+RvJWMB8GA1UdIwQYMBaAFDjj6hEpDZdjAIdvd9Moe3unRvJWMA8GA1UdEwEB/wQF
+MAMBAf8wDQYJKoZIhvcNAQELBQADggIBACu+Ct6J+Dh3EXFOgjW3gN3CaD0UK0kW
+03u7znNAJBAYhi+MXSTPBdrxYGOPkHF1Jl15qb2fc58+0nakf8bvah8kgxi2ujX8
+vrPBjsAv/ixPvUrcol9ZGrseP5DdFS8pw1FoDR/JdgNCdSM4xC3GSk2SLYs+QSJx
+YG3nQLOAZEvnbiZ4zBZ0wVct4w9jrxtqdq2eS8cLoRVx715MzKPBCGEccYu/py5a
+gkyclr16s0mb+wN49of34AQ+xXguHZGNZzCy6PTbx0IC+sRVe82+RZkj21JG+AFM
+9s+vLgRdtWIEZW1AIYbUUbhuvsne+sidZW5XQuFp1V4LlQbO49oEhrPMBn+oHKg5
+MWIe68bjkqDSnDzG+TEBTWiAhyyGyZcebfCs72DGbYrfKt1uTyi+groumPnvQfJB
+y3kqy2pUFeEkNJkx4BfYL+N7I07s9WTy8UMoqn/OLuyqoFaYMd9XMaOOx3xTy8aw
+pUJ69c3VI66W/Ii1ypk2EPUImWpG/n89Y/8Mk1NbesaZLk9feTDfbM4VNPkQU+7T
+3DNQxPSswSh4nXGURwC46SOu2s1lRA98ZXkP5XhUvTuvfg/e4suq26OqjORHQ5zI
+57NP+uHRrfHGlrQ196j1Maw7W7vkocbEv8/06v6s54CG8ezzD2nt1QrLJqSpUqHo
+qolvgn/PK+gg
 -----END CERTIFICATE-----
diff --git a/samplecode/mio/server/bin/end.fullchain b/samplecode/mio/server/bin/end.fullchain
index 2ea11e48..380ec768 100644
--- a/samplecode/mio/server/bin/end.fullchain
+++ b/samplecode/mio/server/bin/end.fullchain
@@ -1,113 +1,81 @@
 -----BEGIN CERTIFICATE-----
 MIIEADCCAmigAwIBAgICAcgwDQYJKoZIhvcNAQELBQAwLDEqMCgGA1UEAwwhcG9u
-eXRvd24gUlNBIGxldmVsIDIgaW50ZXJtZWRpYXRlMB4XDTE3MDQxMDIwNTYyN1oX
-DTIyMTAwMTIwNTYyN1owGTEXMBUGA1UEAwwOdGVzdHNlcnZlci5jb20wggEiMA0G
-CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCa4nonCxArES+kBBf9mZoaQ2GBMg74
-Pj2ve4RKJSIBt9A7EgJ4hFznFQ11O11Xvb3dVQGOK+pFRxh2xg0DJvV3lJytpvKe
-mviyT5KSGvp6Hybqmx66B2V3iDfrXhhySqG5tKEeczFBIq+62dAp0+r0oSdpZKGT
-1YDtXonjcbnDb93K7g8arEadFKYN3MAjBGQ3m5fsWJJuq4hLU1+dpmAfxmYH1dlc
-n89LyPhYh0I7R5v17VrGlNCWIWD1emLtM8vTS94eMtp8R6MuMIZTOKgBTrIpU4G5
-GPcR3flDzzLsCxEttjjMa41zStKXzieUIwirRAzPv48V4JlkCCUPv97pAgMBAAGj
-gb4wgbswDAYDVR0TAQH/BAIwADALBgNVHQ8EBAMCBsAwHQYDVR0OBBYEFNn77YZg
-4AGguHBKVggK00dtRvhCMEIGA1UdIwQ7MDmAFGuwcG2Zfyr92yAiXU9HP9rBYC6/
+eXRvd24gUlNBIGxldmVsIDIgaW50ZXJtZWRpYXRlMB4XDTE5MDYwOTE3MTUxMloX
+DTI0MTEyOTE3MTUxMlowGTEXMBUGA1UEAwwOdGVzdHNlcnZlci5jb20wggEiMA0G
+CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDdwbEc6ZKih4mQA916JwctBZgnRmzO
+KERrzlHjfzy8ZfsUJLENQBN8s3RVRwPThReHdp8bpiVRrNmMRxyXoa5oqxWDjXOu
+5W4hoISIMbOAq4Kj8G+eS0UKwypKHwJ1aUzEjWQGKxNpIYvcGqwYpN1Yi1+qTgLg
+2qw1ENtBhrWHhmQruGqDtQTQLe2tbcOuGhIL0cyWIRtEWHWL/wb1Akzhm31WQF+m
+URtYvYonA/Ta7ErONXCxsEXndTR4iT/XognnOhTJ+uIinNwn52y9Te7MYix6SDBE
+VeKZx9v3iOYU81zXf+WaxNqZvTfbPjkLsXiymOgVfGQcO4hiQeLoJIHXAgMBAAGj
+gb4wgbswDAYDVR0TAQH/BAIwADALBgNVHQ8EBAMCBsAwHQYDVR0OBBYEFEweXJqS
+BzVcf/00QeOC29OwBQszMEIGA1UdIwQ7MDmAFEKPy8hHZVazpvIsxFcGo4YrkEkw
 oR6kHDAaMRgwFgYDVQQDDA9wb255dG93biBSU0EgQ0GCAXswOwYDVR0RBDQwMoIO
 dGVzdHNlcnZlci5jb22CFXNlY29uZC50ZXN0c2VydmVyLmNvbYIJbG9jYWxob3N0
-MA0GCSqGSIb3DQEBCwUAA4IBgQB4xB9IPNxkJIA8QtngQZCCSPH5SjfAibcLfwi2
-NLHe4hO4HvoIVv0ru7CODfq45qNfH7sUj8a/JBU8BwcJ3xPewWFdavtCP8+dapmd
-pr831+Xx6p9tNIdW16WrCXEV8i9bHy43Y4pWbNdXQy5meI0qvSM/ExedZqqVeJJT
-oXL/aCtMsBixlwlKvrsG9ZvIAl1ics0wA5kqQWVufe95loI+HUcPc9s9689H+/ON
-lH8rTLPwyufk9h2dTb9Wzw3qewlDIqgoyX7k9cOwrJqA4D6typCvb5dWfQlK9c72
-4rGbqHSx7mrlaZ4typfAMdEbynRlDSgIIZGXb7RaoV3NT2XuVFd8+lcXgBiJMvPk
-STejz77EPR2+uKvQ1gMJXpEHCBUvMMyDqhpcNzb0DaXgf4eYI9RqfxU1pkgYnfxe
-DGDGI2SdmO43NwSDyEQVSlRpCIBj4ZDay3IP7mbdi8MLxR9H1BCHnN7D04UrTnuA
-c/cl0RMWL+iHtKU2cCxltEQQ9qQ=
+MA0GCSqGSIb3DQEBCwUAA4IBgQCViHp2pLcIMzl/wN+sULznLYZvrlynU4AHnL8/
+ba6iSAM6EMlrcu11+UBQglHIN2BEn+Jjas+HT1sQOIOixMgjrMBgirLez8n5DN66
+o5aK5bu23GjQvzq5JEh0skQDHtSFX0YRwqXIhi1spGtObsnoupxJNBQbdAcDv50/
+m6/8WXcPbXBnR+wRywFmjb6+OSVNgCRtBFTbR5XRVHMPEwvSk4hVj4jimlnPHZYL
+3VatCPtZr6iaLZl9E64BbS+J4vPQ0Z/2JMUjtXCuj19k8LO2TTTBz54QVoMF5jrZ
+xotneq+wmPH3lmozEOmyj4+4CmoyNz+RDhrlok84x3g4YEKUQyK1V4ROi9DtL1CV
+VoLfHSwS9SiDdD/Qn2n7RICn6DP2lHozICyHX0Op4W+vETHho7Flsw21bMisAGrl
+wwQ7UYU4XfPOC9hQoCvU60uVe7z+uZvlBY8RwmcW4iFIbfCcPT6Hrom5F1X4Z/dm
+zDW8ZhLDsjUY/D4lUeWjbO1RCHI=
 -----END CERTIFICATE-----
 -----BEGIN CERTIFICATE-----
-MIIGnzCCAoegAwIBAgIBezANBgkqhkiG9w0BAQsFADAaMRgwFgYDVQQDDA9wb255
-dG93biBSU0EgQ0EwHhcNMTcwNDEwMjA1NjI3WhcNMjcwNDA4MjA1NjI3WjAsMSow
+MIIEnzCCAoegAwIBAgIBezANBgkqhkiG9w0BAQsFADAaMRgwFgYDVQQDDA9wb255
+dG93biBSU0EgQ0EwHhcNMTkwNjA5MTcxNTEyWhcNMjkwNjA2MTcxNTEyWjAsMSow
 KAYDVQQDDCFwb255dG93biBSU0EgbGV2ZWwgMiBpbnRlcm1lZGlhdGUwggGiMA0G
-CSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQDCX7V0gKGQBS64QKntjDlBslbQJaxq
-EL8Yyq+qjF6nkOoqENKWSzeNyQ76kPVlzeV03UCaIgTF4+FeQrUr7wauEz0FGmDh
-yx/B4xy9ZXdBIftPB8iz8Q/KrKO6YM6tkj7ijvL8hP3MfssBkA+VoAxamPSIikfM
-9kyttemjYizgM0ywebzKmQGJbEINZ80Kp63ayR/Uo/cORjlH3xbmtTsL3pd+k6Ro
-xOMZKm1RIwOwGgxDW4ea294A4lXHwfwHGMsP0/xmqTZ0R/EpxLKeqJAQffTiVsBK
-YEFzANn3nol1IYrdcZcgcs16KTnc5+XyL87KSdIgDgG3wmQvRCdLX5G6GChyP03Z
-qQSYMkwGSNgCD1v4m14Z5XT2su7iilHfjsucvT4OukCe63nqeXIZ+w63YqbjTp/a
-HMgrXVg1wMlSncl0OIKcjLOgJ5vbPOGk9DvF93JbRFp/9sAZmK89Ur4gBmgpq2Zn
-bknK0LVt+aerP7rf8CPYE89olPVUW0owwrkCAwEAAaNeMFwwHQYDVR0OBBYEFGuw
-cG2Zfyr92yAiXU9HP9rBYC6/MCAGA1UdJQEB/wQWMBQGCCsGAQUFBwMBBggrBgEF
+CSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQCj/tOFeSW3WB+TtuLCR1L/84lZytFw
+zbpzOTGB1kPEKNbrMsv3lHXm5bHa8Bl3k113k7Hi7OAt/nkMm05s8LcUoovhaG5C
+G7tjzL+ld1nO74gNS3IQHCzxRdRwIgaDZHyICfBQBfB9/m+9z3yRtOKWJl6i/MT9
+HRN6yADW/8gHFlMzRkCKBjIKXehKsu8cbtB+5MukwtXI4rKf9aYXZQOEUn1kEwQJ
+ZIKBXR0eyloQiZervUE7meRCTBvzXT9VoSEX49/mempp4hnfdHlRNzre4/tphBf1
+fRUdpVXZ3DvmzoHdXRVzxx3X5LvDpf7Eb3ViGkXDFwkSfHEhkRnAl4lIzTH/1F25
+stmT8a0PA/lCNMrzJBzkLcuem1G1uMHoQZo1f3OpslJ8gHbE9ZlIbIKmpmJS9oop
+Vh1BH+aOy5doCrF8uOLTQ3d5CqA/EZMGahDHy7IkeNYmG/RXUKNltv+r95gwuRP+
+9UIJ9FTa4REQbIpGWP5XibI6x4LqLTJj+VsCAwEAAaNeMFwwHQYDVR0OBBYEFEKP
+y8hHZVazpvIsxFcGo4YrkEkwMCAGA1UdJQEB/wQWMBQGCCsGAQUFBwMBBggrBgEF
 BQcDAjAMBgNVHRMEBTADAQH/MAsGA1UdDwQEAwIB/jANBgkqhkiG9w0BAQsFAAOC
-BAEARD9wwIHsAFWlzrRLw3JcAUDB906Ks7KZzdqe3n6FkbyHHP1N5JG25wXwgADS
-qux6sZU7h6+q209IEqXWbw+nbxJs/3D1hLN6X2tVgsfkSflGsd3DfNPZI8qKUyOD
-VYlql/EPEMBixXOeVpwxXc48rX/yVjxqCvhY/A7eIiAc+bzQtwozLppChyVitQGI
-MViXRdGdFiybwTKoJMYXl6ztamk9TWhdvJ9znirol12b06Z3J0Kz0c/kqY7VVZqL
-ba76+IAJjvWQE7PYEOqpFHOLpilv9j5d/0kBR4AgJaooFwcYnr6aJKfNUgGWEmdn
-ELYmfa0qORllAM/yGoewRfWGLZBNgT0QFYg2IFjnp0W0wIXFRd7xVqldN+cTmMqk
-szpVV7bqGvuk6SQNFjIZ8VIVc/mXua4WlwBODDRzKqU3bIgBTODgVq1edwqp6UjN
-ECLAOe1p03GGMr4WSPDoFjlQlHy+NLUwZg3RI+HsAkow9WfP7KqGN4vFDC4ru9Pg
-2uD28oTrOgYQpzKjQJSH3kC5feOUdrsET7zic75XO1J33CAlgbIZ2TSQDqnH2cY5
-bQsWSNA2Lle3wBbeHlCy7ACiaoeJS23TJV9n8PcsRwSmHA9NgT4WSavXwtZ0lBhI
-60GY80VXo9ziQjvVTMZNymZ4FEqCvULHGhFI08Jqd1jOXjnPLY4WEARqkicBJvI1
-3t4sBLDU+PEqH7m8k3lCZd6D7XVDcc8bJock+DjXZIMbZY79UMuzyHocXNJpRfRT
-cqS0qneltFe6Pea7y0PN2IDttGBLb1CVQpXhRkpFU8jtyXh3ulSZSJEeqLVRFgdv
-PVwHWAhLPewVGDkgTrlWVNfiXxp1LWVTFzQFas9xWiY4byQk/DNQaaFwHpGoZgVc
-qAzUVk20Msm2u9xvSbPcBGk0dL4fdlnOkyeq/k/fnNrGdRHJWuJe7QR73/N0u6fy
-7H76xUXvcwwrxL8ma8nV9K+A7oM7YUiR1wagD9cnoDDBgQmH9Izvfw0PxJgqnLOe
-lQGPVGRhmXNtLLG57dqgjrvERGy9u5NMxBlkH0giZTFyQXPQ+N75ouM4S3RL75PM
-UaTOBtnyCj++5ysnDFlGqEXgy08rrtkCbbNfd9dnO568juXS6ExC6TEL/pUMhy+Z
-ooIJ69Tt7R5dOLaKRrkX/nKHfCfLfXXnjyDmdRHRYrXvTWusF038OsqY89tb0F0u
-S4Szv4/Bl1bhzx/XYMZv/y7XL0va8FQLiRTuvqJ9hTsE/Xkd4ZFrP1LaP6HzVR1g
-tsFs2Gc8j7H299U3WLjNon0TL2uPXa77Vu+9h7QCi1W9Uzsv0xMvZ/KMEnXyaEBd
-W1lqo85ih1nnfxcW+lmAz8QNGQ==
+AgEAMzTRDLBExVFlw98AuX+pM+/R2Gjw5KFHvSYLKLbMRfuuZK1yNYYaYtNrtF+V
+a53OFgaZj56o7tXc2PB8kw4MELD0ViR8Do2bvZieFcEe4DwhdjGCjuLehVLT29qI
+7T3N/JkJ5daemKZcRB6Ne0F4+6QlVVNck28HUKbQThl88RdwLUImmSAfgKSt6uJ5
+wlH7wiYQR2vPXwSuEYzwot+L/91eBwuQr4Lovx9+TCKTbwQOKYjX4KfcOOQ1rx0M
+IMrvwWqnabc6m1F0O6//ibL0kuFkJYEgOH2uJA12FBHO+/q2tcytejkOWKWMJj6Y
+2etwIHcpzXaEP7fZ75cFGqcE3s7XGsweBIPLjMP1bKxEcFKzygURm/auUuXBCFBl
+E16PB6JEAeCKe/8VFeyucvjPuQDWB49aq+r2SbpbI4IeZdz/QgEIOb0MpwStrvhH
+9f/DtGMbjvuAEkRoOorK4m5k4GY3LsWTR2bey27AXk8N7pKarpu2N7ChBPm+EV0Y
+H+tAI/OfdZuNUCES00F5UAFdU8zBUZo19ao2ZqfEADimE7Epk2s0bUe4GSqEXJp6
+68oVSMhZmMf/RCSNlr97f34sNiUA1YJ0JbCRZmw8KWNm9H1PARLbrgeRBZ/k31Li
+WLDr3fiEVk7SGxj3zo94cS6AT55DyXLiSD/bFmL1QXgZweA=
 -----END CERTIFICATE-----
 -----BEGIN CERTIFICATE-----
-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
-9Xpi4ds6s2cT8zZGDKI=
+MIIFFTCCAv2gAwIBAgIUGXgsGl4sGhiPwUPOme5w5jJscVQwDQYJKoZIhvcNAQEL
+BQAwGjEYMBYGA1UEAwwPcG9ueXRvd24gUlNBIENBMB4XDTE5MDYwOTE3MTUxMVoX
+DTI5MDYwNjE3MTUxMVowGjEYMBYGA1UEAwwPcG9ueXRvd24gUlNBIENBMIICIjAN
+BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEArpW4WHfSmTCMvnDJaCRL5BR2knDc
+C+T4/wv7i//zsBL3q0YVdBpllWCZx8TSfuXT/1o/Zxdt+H1ZjnH8yuwuHOToE3W0
++Y/912hAPiD+d79A+MtqVX1gayjHDy9HybznTN2Onh1ZhWyks0FLL5SB0vVCLwXP
+W7tcyY0w6wn3RTw4nBu7co5a280cHgHv5V3XeNgteQrnkXE9TfuqqUZwVt0v1jr1
+bk1KaDDD+36wfeO70Q6CeLwKPhN0mPDHdj/lecj4efl0l1B0ehHxLkLuztqtkCF6
++yMoBrEyzJjO6TGMSTMsnw4F9bA15jkIIEQs5FhwVHFOTmu5BG+j37umoy27k5As
+5cV0/djr3r8WhBZ6w2+XjvbAdJPgqc+Xobnx1i5GI4noRC4G4Cl0Vx+iRru1/nsE
+xPazz9UVkiUsDlN9n49f1pik9z74Box6CD6IZVb8h4vV7um+0R4/eErVf/Cyf1Xe
+axVaOgA/CD0ucLdSfDz61O/2PG3P7YjWY1R9zr35e8pakgyFPXnWMbsfniuGkM0X
+6lG743Q7yVt38/HuAqi1AGq+r/AKisrezt97UNm0CryuEk02y4SVLbhuG/V6mBCh
+4Va3KD1ZOgfJcTZbuxebIz6W+5jL80hE0YwBBs8vSv8Fo5N7dYNSNvyMxkoPh8Gw
+CAFyqt5zBLGCEvkCAwEAAaNTMFEwHQYDVR0OBBYEFDjj6hEpDZdjAIdvd9Moe3un
+RvJWMB8GA1UdIwQYMBaAFDjj6hEpDZdjAIdvd9Moe3unRvJWMA8GA1UdEwEB/wQF
+MAMBAf8wDQYJKoZIhvcNAQELBQADggIBACu+Ct6J+Dh3EXFOgjW3gN3CaD0UK0kW
+03u7znNAJBAYhi+MXSTPBdrxYGOPkHF1Jl15qb2fc58+0nakf8bvah8kgxi2ujX8
+vrPBjsAv/ixPvUrcol9ZGrseP5DdFS8pw1FoDR/JdgNCdSM4xC3GSk2SLYs+QSJx
+YG3nQLOAZEvnbiZ4zBZ0wVct4w9jrxtqdq2eS8cLoRVx715MzKPBCGEccYu/py5a
+gkyclr16s0mb+wN49of34AQ+xXguHZGNZzCy6PTbx0IC+sRVe82+RZkj21JG+AFM
+9s+vLgRdtWIEZW1AIYbUUbhuvsne+sidZW5XQuFp1V4LlQbO49oEhrPMBn+oHKg5
+MWIe68bjkqDSnDzG+TEBTWiAhyyGyZcebfCs72DGbYrfKt1uTyi+groumPnvQfJB
+y3kqy2pUFeEkNJkx4BfYL+N7I07s9WTy8UMoqn/OLuyqoFaYMd9XMaOOx3xTy8aw
+pUJ69c3VI66W/Ii1ypk2EPUImWpG/n89Y/8Mk1NbesaZLk9feTDfbM4VNPkQU+7T
+3DNQxPSswSh4nXGURwC46SOu2s1lRA98ZXkP5XhUvTuvfg/e4suq26OqjORHQ5zI
+57NP+uHRrfHGlrQ196j1Maw7W7vkocbEv8/06v6s54CG8ezzD2nt1QrLJqSpUqHo
+qolvgn/PK+gg
 -----END CERTIFICATE-----
diff --git a/samplecode/mio/server/bin/end.rsa b/samplecode/mio/server/bin/end.rsa
index 47deca38..4ba9c7a9 100644
--- a/samplecode/mio/server/bin/end.rsa
+++ b/samplecode/mio/server/bin/end.rsa
@@ -1,27 +1,27 @@
 -----BEGIN RSA PRIVATE KEY-----
-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
+MIIEpAIBAAKCAQEA3cGxHOmSooeJkAPdeicHLQWYJ0ZszihEa85R4388vGX7FCSx
+DUATfLN0VUcD04UXh3afG6YlUazZjEccl6GuaKsVg41zruVuIaCEiDGzgKuCo/Bv
+nktFCsMqSh8CdWlMxI1kBisTaSGL3BqsGKTdWItfqk4C4NqsNRDbQYa1h4ZkK7hq
+g7UE0C3trW3DrhoSC9HMliEbRFh1i/8G9QJM4Zt9VkBfplEbWL2KJwP02uxKzjVw
+sbBF53U0eIk/16IJ5zoUyfriIpzcJ+dsvU3uzGIsekgwRFXimcfb94jmFPNc13/l
+msTamb032z45C7F4spjoFXxkHDuIYkHi6CSB1wIDAQABAoIBAExZd8Vgld/nknFH
+I2X/MfVKS8yZ7rQ8IPKNIpyVHjAvXHbe+yZ4vTzd/FuwC50z4Zn+OWGnnom0XWJy
+yWFbhVT8MngMp5u72mMxhO/vTMIsStpu2b9CYw8FivXiH1KVYpz5oUqOYix8JE8v
+z7jcamkl81YLbepE362VlCfHXZC/DGzEE70iwcrKcmav/Z+l6uHMtZLppq2IJbhi
+q4evm/t/33+ME3xfbcZXnDPrXtLqCJ7uY00RhkqLiiojliy5EDTwqq0psv1X0C5G
+nLN5fGPPRaOE5QVOjBG9NrvnwkP+fKtRPGOydf2I79lU8Gr/atRF/f53APG9gtCt
+WJYIfUECgYEA9m2cCNN8+GaaNU58VHeK9KllRMWO3z/QXyTxJ9yhOM5T124ojWsz
+Ka3RaCFBLSjXJe+2WFXLzSwlAzls45mmLVSZu8LlD3CUFNm3nLsOje8mSXfZn1zz
+ogVpr/A3+QCScpnVHF6jMkovXha9ZksBYa7BUU7PBaNGxq8PFEzDO9kCgYEA5l7B
+7fNPhe2LlVK1TLoU06/w6sB4KsgkNc0F7jnhg2hT0mM4JOlxDzyVPiopfmxSGOw2
+jKJFR1rySfXvYhfH435Up6dqadQVmrdw/iN831/kgoqA/Cl3BYjH6B/W6iHwc2kH
+3jDYKjG0dH6bH/5dJ/3MCUUOChlO7Kbl6mNGjS8CgYBGtpFN3xI/XYHmxgzbWCph
+prJOl7o1yeQLSViCLcd9u4dHjG7KlfZqgVxT2ycOxGdolW7nzkbbK027rSDX9uE+
+pMYwoO6GDbIQgaE0smCszfFYp7GlD1FCLvdy6yXEqCteA1Kp/2YpKiyJfVEAJ4nP
+9Au5PzoczgujO9zB4H0tkQKBgQDNDsvQ4yOGM0xsPpLjGUAwrgvk6i4M5tpUiYsd
+4qe6MMNsIqV3NdRNm7+89gq5XfI1/Q0RYeAJBAtnimLrDf//oBP6qCswyHfyoBcU
+IMKmktT03hSyYLZxVq+bD7xd7Jf8IyG9xfykklnu2EN81w5U6rUUC0PT+XMnc+h0
+GqpSQQKBgQC98TX5krWlBVeJqJrOuH2e+eS6kMDea8I2S8ZkU7DoFSPyjxIOOMb2
+3BvPOXjVviYWEj1Mr5Kz+kG/iPDxDanTD1IE3rTq5wOE/cn+/lP8R4IQ0m9wRECs
+hpa20Tthgf4hmt8Rw/et1qMw83gH0Lsay61GkIz7H9gBIax5PLJYDA==
 -----END RSA PRIVATE KEY-----
diff --git a/samplecode/project_template/app/rust-toolchain b/samplecode/project_template/app/rust-toolchain
index 4e7e21b0..0f99c85c 100644
--- a/samplecode/project_template/app/rust-toolchain
+++ b/samplecode/project_template/app/rust-toolchain
@@ -1 +1 @@
-nightly-2022-02-23
\ No newline at end of file
+nightly-2022-10-22
\ No newline at end of file
diff --git a/samplecode/project_template/enclave/rust-toolchain b/samplecode/project_template/enclave/rust-toolchain
index 4e7e21b0..0f99c85c 100644
--- a/samplecode/project_template/enclave/rust-toolchain
+++ b/samplecode/project_template/enclave/rust-toolchain
@@ -1 +1 @@
-nightly-2022-02-23
\ No newline at end of file
+nightly-2022-10-22
\ No newline at end of file
diff --git a/samplecode/tls/tlsclient/bin/ca.cert b/samplecode/tls/tlsclient/bin/ca.cert
index a18fb02c..3a84cbe6 100644
--- a/samplecode/tls/tlsclient/bin/ca.cert
+++ b/samplecode/tls/tlsclient/bin/ca.cert
@@ -1,51 +1,30 @@
 -----BEGIN CERTIFICATE-----
-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
-9Xpi4ds6s2cT8zZGDKI=
+MIIFFTCCAv2gAwIBAgIUGXgsGl4sGhiPwUPOme5w5jJscVQwDQYJKoZIhvcNAQEL
+BQAwGjEYMBYGA1UEAwwPcG9ueXRvd24gUlNBIENBMB4XDTE5MDYwOTE3MTUxMVoX
+DTI5MDYwNjE3MTUxMVowGjEYMBYGA1UEAwwPcG9ueXRvd24gUlNBIENBMIICIjAN
+BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEArpW4WHfSmTCMvnDJaCRL5BR2knDc
+C+T4/wv7i//zsBL3q0YVdBpllWCZx8TSfuXT/1o/Zxdt+H1ZjnH8yuwuHOToE3W0
++Y/912hAPiD+d79A+MtqVX1gayjHDy9HybznTN2Onh1ZhWyks0FLL5SB0vVCLwXP
+W7tcyY0w6wn3RTw4nBu7co5a280cHgHv5V3XeNgteQrnkXE9TfuqqUZwVt0v1jr1
+bk1KaDDD+36wfeO70Q6CeLwKPhN0mPDHdj/lecj4efl0l1B0ehHxLkLuztqtkCF6
++yMoBrEyzJjO6TGMSTMsnw4F9bA15jkIIEQs5FhwVHFOTmu5BG+j37umoy27k5As
+5cV0/djr3r8WhBZ6w2+XjvbAdJPgqc+Xobnx1i5GI4noRC4G4Cl0Vx+iRru1/nsE
+xPazz9UVkiUsDlN9n49f1pik9z74Box6CD6IZVb8h4vV7um+0R4/eErVf/Cyf1Xe
+axVaOgA/CD0ucLdSfDz61O/2PG3P7YjWY1R9zr35e8pakgyFPXnWMbsfniuGkM0X
+6lG743Q7yVt38/HuAqi1AGq+r/AKisrezt97UNm0CryuEk02y4SVLbhuG/V6mBCh
+4Va3KD1ZOgfJcTZbuxebIz6W+5jL80hE0YwBBs8vSv8Fo5N7dYNSNvyMxkoPh8Gw
+CAFyqt5zBLGCEvkCAwEAAaNTMFEwHQYDVR0OBBYEFDjj6hEpDZdjAIdvd9Moe3un
+RvJWMB8GA1UdIwQYMBaAFDjj6hEpDZdjAIdvd9Moe3unRvJWMA8GA1UdEwEB/wQF
+MAMBAf8wDQYJKoZIhvcNAQELBQADggIBACu+Ct6J+Dh3EXFOgjW3gN3CaD0UK0kW
+03u7znNAJBAYhi+MXSTPBdrxYGOPkHF1Jl15qb2fc58+0nakf8bvah8kgxi2ujX8
+vrPBjsAv/ixPvUrcol9ZGrseP5DdFS8pw1FoDR/JdgNCdSM4xC3GSk2SLYs+QSJx
+YG3nQLOAZEvnbiZ4zBZ0wVct4w9jrxtqdq2eS8cLoRVx715MzKPBCGEccYu/py5a
+gkyclr16s0mb+wN49of34AQ+xXguHZGNZzCy6PTbx0IC+sRVe82+RZkj21JG+AFM
+9s+vLgRdtWIEZW1AIYbUUbhuvsne+sidZW5XQuFp1V4LlQbO49oEhrPMBn+oHKg5
+MWIe68bjkqDSnDzG+TEBTWiAhyyGyZcebfCs72DGbYrfKt1uTyi+groumPnvQfJB
+y3kqy2pUFeEkNJkx4BfYL+N7I07s9WTy8UMoqn/OLuyqoFaYMd9XMaOOx3xTy8aw
+pUJ69c3VI66W/Ii1ypk2EPUImWpG/n89Y/8Mk1NbesaZLk9feTDfbM4VNPkQU+7T
+3DNQxPSswSh4nXGURwC46SOu2s1lRA98ZXkP5XhUvTuvfg/e4suq26OqjORHQ5zI
+57NP+uHRrfHGlrQ196j1Maw7W7vkocbEv8/06v6s54CG8ezzD2nt1QrLJqSpUqHo
+qolvgn/PK+gg
 -----END CERTIFICATE-----
diff --git a/samplecode/tls/tlsserver/bin/end.fullchain b/samplecode/tls/tlsserver/bin/end.fullchain
index 2ea11e48..380ec768 100644
--- a/samplecode/tls/tlsserver/bin/end.fullchain
+++ b/samplecode/tls/tlsserver/bin/end.fullchain
@@ -1,113 +1,81 @@
 -----BEGIN CERTIFICATE-----
 MIIEADCCAmigAwIBAgICAcgwDQYJKoZIhvcNAQELBQAwLDEqMCgGA1UEAwwhcG9u
-eXRvd24gUlNBIGxldmVsIDIgaW50ZXJtZWRpYXRlMB4XDTE3MDQxMDIwNTYyN1oX
-DTIyMTAwMTIwNTYyN1owGTEXMBUGA1UEAwwOdGVzdHNlcnZlci5jb20wggEiMA0G
-CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCa4nonCxArES+kBBf9mZoaQ2GBMg74
-Pj2ve4RKJSIBt9A7EgJ4hFznFQ11O11Xvb3dVQGOK+pFRxh2xg0DJvV3lJytpvKe
-mviyT5KSGvp6Hybqmx66B2V3iDfrXhhySqG5tKEeczFBIq+62dAp0+r0oSdpZKGT
-1YDtXonjcbnDb93K7g8arEadFKYN3MAjBGQ3m5fsWJJuq4hLU1+dpmAfxmYH1dlc
-n89LyPhYh0I7R5v17VrGlNCWIWD1emLtM8vTS94eMtp8R6MuMIZTOKgBTrIpU4G5
-GPcR3flDzzLsCxEttjjMa41zStKXzieUIwirRAzPv48V4JlkCCUPv97pAgMBAAGj
-gb4wgbswDAYDVR0TAQH/BAIwADALBgNVHQ8EBAMCBsAwHQYDVR0OBBYEFNn77YZg
-4AGguHBKVggK00dtRvhCMEIGA1UdIwQ7MDmAFGuwcG2Zfyr92yAiXU9HP9rBYC6/
+eXRvd24gUlNBIGxldmVsIDIgaW50ZXJtZWRpYXRlMB4XDTE5MDYwOTE3MTUxMloX
+DTI0MTEyOTE3MTUxMlowGTEXMBUGA1UEAwwOdGVzdHNlcnZlci5jb20wggEiMA0G
+CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDdwbEc6ZKih4mQA916JwctBZgnRmzO
+KERrzlHjfzy8ZfsUJLENQBN8s3RVRwPThReHdp8bpiVRrNmMRxyXoa5oqxWDjXOu
+5W4hoISIMbOAq4Kj8G+eS0UKwypKHwJ1aUzEjWQGKxNpIYvcGqwYpN1Yi1+qTgLg
+2qw1ENtBhrWHhmQruGqDtQTQLe2tbcOuGhIL0cyWIRtEWHWL/wb1Akzhm31WQF+m
+URtYvYonA/Ta7ErONXCxsEXndTR4iT/XognnOhTJ+uIinNwn52y9Te7MYix6SDBE
+VeKZx9v3iOYU81zXf+WaxNqZvTfbPjkLsXiymOgVfGQcO4hiQeLoJIHXAgMBAAGj
+gb4wgbswDAYDVR0TAQH/BAIwADALBgNVHQ8EBAMCBsAwHQYDVR0OBBYEFEweXJqS
+BzVcf/00QeOC29OwBQszMEIGA1UdIwQ7MDmAFEKPy8hHZVazpvIsxFcGo4YrkEkw
 oR6kHDAaMRgwFgYDVQQDDA9wb255dG93biBSU0EgQ0GCAXswOwYDVR0RBDQwMoIO
 dGVzdHNlcnZlci5jb22CFXNlY29uZC50ZXN0c2VydmVyLmNvbYIJbG9jYWxob3N0
-MA0GCSqGSIb3DQEBCwUAA4IBgQB4xB9IPNxkJIA8QtngQZCCSPH5SjfAibcLfwi2
-NLHe4hO4HvoIVv0ru7CODfq45qNfH7sUj8a/JBU8BwcJ3xPewWFdavtCP8+dapmd
-pr831+Xx6p9tNIdW16WrCXEV8i9bHy43Y4pWbNdXQy5meI0qvSM/ExedZqqVeJJT
-oXL/aCtMsBixlwlKvrsG9ZvIAl1ics0wA5kqQWVufe95loI+HUcPc9s9689H+/ON
-lH8rTLPwyufk9h2dTb9Wzw3qewlDIqgoyX7k9cOwrJqA4D6typCvb5dWfQlK9c72
-4rGbqHSx7mrlaZ4typfAMdEbynRlDSgIIZGXb7RaoV3NT2XuVFd8+lcXgBiJMvPk
-STejz77EPR2+uKvQ1gMJXpEHCBUvMMyDqhpcNzb0DaXgf4eYI9RqfxU1pkgYnfxe
-DGDGI2SdmO43NwSDyEQVSlRpCIBj4ZDay3IP7mbdi8MLxR9H1BCHnN7D04UrTnuA
-c/cl0RMWL+iHtKU2cCxltEQQ9qQ=
+MA0GCSqGSIb3DQEBCwUAA4IBgQCViHp2pLcIMzl/wN+sULznLYZvrlynU4AHnL8/
+ba6iSAM6EMlrcu11+UBQglHIN2BEn+Jjas+HT1sQOIOixMgjrMBgirLez8n5DN66
+o5aK5bu23GjQvzq5JEh0skQDHtSFX0YRwqXIhi1spGtObsnoupxJNBQbdAcDv50/
+m6/8WXcPbXBnR+wRywFmjb6+OSVNgCRtBFTbR5XRVHMPEwvSk4hVj4jimlnPHZYL
+3VatCPtZr6iaLZl9E64BbS+J4vPQ0Z/2JMUjtXCuj19k8LO2TTTBz54QVoMF5jrZ
+xotneq+wmPH3lmozEOmyj4+4CmoyNz+RDhrlok84x3g4YEKUQyK1V4ROi9DtL1CV
+VoLfHSwS9SiDdD/Qn2n7RICn6DP2lHozICyHX0Op4W+vETHho7Flsw21bMisAGrl
+wwQ7UYU4XfPOC9hQoCvU60uVe7z+uZvlBY8RwmcW4iFIbfCcPT6Hrom5F1X4Z/dm
+zDW8ZhLDsjUY/D4lUeWjbO1RCHI=
 -----END CERTIFICATE-----
 -----BEGIN CERTIFICATE-----
-MIIGnzCCAoegAwIBAgIBezANBgkqhkiG9w0BAQsFADAaMRgwFgYDVQQDDA9wb255
-dG93biBSU0EgQ0EwHhcNMTcwNDEwMjA1NjI3WhcNMjcwNDA4MjA1NjI3WjAsMSow
+MIIEnzCCAoegAwIBAgIBezANBgkqhkiG9w0BAQsFADAaMRgwFgYDVQQDDA9wb255
+dG93biBSU0EgQ0EwHhcNMTkwNjA5MTcxNTEyWhcNMjkwNjA2MTcxNTEyWjAsMSow
 KAYDVQQDDCFwb255dG93biBSU0EgbGV2ZWwgMiBpbnRlcm1lZGlhdGUwggGiMA0G
-CSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQDCX7V0gKGQBS64QKntjDlBslbQJaxq
-EL8Yyq+qjF6nkOoqENKWSzeNyQ76kPVlzeV03UCaIgTF4+FeQrUr7wauEz0FGmDh
-yx/B4xy9ZXdBIftPB8iz8Q/KrKO6YM6tkj7ijvL8hP3MfssBkA+VoAxamPSIikfM
-9kyttemjYizgM0ywebzKmQGJbEINZ80Kp63ayR/Uo/cORjlH3xbmtTsL3pd+k6Ro
-xOMZKm1RIwOwGgxDW4ea294A4lXHwfwHGMsP0/xmqTZ0R/EpxLKeqJAQffTiVsBK
-YEFzANn3nol1IYrdcZcgcs16KTnc5+XyL87KSdIgDgG3wmQvRCdLX5G6GChyP03Z
-qQSYMkwGSNgCD1v4m14Z5XT2su7iilHfjsucvT4OukCe63nqeXIZ+w63YqbjTp/a
-HMgrXVg1wMlSncl0OIKcjLOgJ5vbPOGk9DvF93JbRFp/9sAZmK89Ur4gBmgpq2Zn
-bknK0LVt+aerP7rf8CPYE89olPVUW0owwrkCAwEAAaNeMFwwHQYDVR0OBBYEFGuw
-cG2Zfyr92yAiXU9HP9rBYC6/MCAGA1UdJQEB/wQWMBQGCCsGAQUFBwMBBggrBgEF
+CSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQCj/tOFeSW3WB+TtuLCR1L/84lZytFw
+zbpzOTGB1kPEKNbrMsv3lHXm5bHa8Bl3k113k7Hi7OAt/nkMm05s8LcUoovhaG5C
+G7tjzL+ld1nO74gNS3IQHCzxRdRwIgaDZHyICfBQBfB9/m+9z3yRtOKWJl6i/MT9
+HRN6yADW/8gHFlMzRkCKBjIKXehKsu8cbtB+5MukwtXI4rKf9aYXZQOEUn1kEwQJ
+ZIKBXR0eyloQiZervUE7meRCTBvzXT9VoSEX49/mempp4hnfdHlRNzre4/tphBf1
+fRUdpVXZ3DvmzoHdXRVzxx3X5LvDpf7Eb3ViGkXDFwkSfHEhkRnAl4lIzTH/1F25
+stmT8a0PA/lCNMrzJBzkLcuem1G1uMHoQZo1f3OpslJ8gHbE9ZlIbIKmpmJS9oop
+Vh1BH+aOy5doCrF8uOLTQ3d5CqA/EZMGahDHy7IkeNYmG/RXUKNltv+r95gwuRP+
+9UIJ9FTa4REQbIpGWP5XibI6x4LqLTJj+VsCAwEAAaNeMFwwHQYDVR0OBBYEFEKP
+y8hHZVazpvIsxFcGo4YrkEkwMCAGA1UdJQEB/wQWMBQGCCsGAQUFBwMBBggrBgEF
 BQcDAjAMBgNVHRMEBTADAQH/MAsGA1UdDwQEAwIB/jANBgkqhkiG9w0BAQsFAAOC
-BAEARD9wwIHsAFWlzrRLw3JcAUDB906Ks7KZzdqe3n6FkbyHHP1N5JG25wXwgADS
-qux6sZU7h6+q209IEqXWbw+nbxJs/3D1hLN6X2tVgsfkSflGsd3DfNPZI8qKUyOD
-VYlql/EPEMBixXOeVpwxXc48rX/yVjxqCvhY/A7eIiAc+bzQtwozLppChyVitQGI
-MViXRdGdFiybwTKoJMYXl6ztamk9TWhdvJ9znirol12b06Z3J0Kz0c/kqY7VVZqL
-ba76+IAJjvWQE7PYEOqpFHOLpilv9j5d/0kBR4AgJaooFwcYnr6aJKfNUgGWEmdn
-ELYmfa0qORllAM/yGoewRfWGLZBNgT0QFYg2IFjnp0W0wIXFRd7xVqldN+cTmMqk
-szpVV7bqGvuk6SQNFjIZ8VIVc/mXua4WlwBODDRzKqU3bIgBTODgVq1edwqp6UjN
-ECLAOe1p03GGMr4WSPDoFjlQlHy+NLUwZg3RI+HsAkow9WfP7KqGN4vFDC4ru9Pg
-2uD28oTrOgYQpzKjQJSH3kC5feOUdrsET7zic75XO1J33CAlgbIZ2TSQDqnH2cY5
-bQsWSNA2Lle3wBbeHlCy7ACiaoeJS23TJV9n8PcsRwSmHA9NgT4WSavXwtZ0lBhI
-60GY80VXo9ziQjvVTMZNymZ4FEqCvULHGhFI08Jqd1jOXjnPLY4WEARqkicBJvI1
-3t4sBLDU+PEqH7m8k3lCZd6D7XVDcc8bJock+DjXZIMbZY79UMuzyHocXNJpRfRT
-cqS0qneltFe6Pea7y0PN2IDttGBLb1CVQpXhRkpFU8jtyXh3ulSZSJEeqLVRFgdv
-PVwHWAhLPewVGDkgTrlWVNfiXxp1LWVTFzQFas9xWiY4byQk/DNQaaFwHpGoZgVc
-qAzUVk20Msm2u9xvSbPcBGk0dL4fdlnOkyeq/k/fnNrGdRHJWuJe7QR73/N0u6fy
-7H76xUXvcwwrxL8ma8nV9K+A7oM7YUiR1wagD9cnoDDBgQmH9Izvfw0PxJgqnLOe
-lQGPVGRhmXNtLLG57dqgjrvERGy9u5NMxBlkH0giZTFyQXPQ+N75ouM4S3RL75PM
-UaTOBtnyCj++5ysnDFlGqEXgy08rrtkCbbNfd9dnO568juXS6ExC6TEL/pUMhy+Z
-ooIJ69Tt7R5dOLaKRrkX/nKHfCfLfXXnjyDmdRHRYrXvTWusF038OsqY89tb0F0u
-S4Szv4/Bl1bhzx/XYMZv/y7XL0va8FQLiRTuvqJ9hTsE/Xkd4ZFrP1LaP6HzVR1g
-tsFs2Gc8j7H299U3WLjNon0TL2uPXa77Vu+9h7QCi1W9Uzsv0xMvZ/KMEnXyaEBd
-W1lqo85ih1nnfxcW+lmAz8QNGQ==
+AgEAMzTRDLBExVFlw98AuX+pM+/R2Gjw5KFHvSYLKLbMRfuuZK1yNYYaYtNrtF+V
+a53OFgaZj56o7tXc2PB8kw4MELD0ViR8Do2bvZieFcEe4DwhdjGCjuLehVLT29qI
+7T3N/JkJ5daemKZcRB6Ne0F4+6QlVVNck28HUKbQThl88RdwLUImmSAfgKSt6uJ5
+wlH7wiYQR2vPXwSuEYzwot+L/91eBwuQr4Lovx9+TCKTbwQOKYjX4KfcOOQ1rx0M
+IMrvwWqnabc6m1F0O6//ibL0kuFkJYEgOH2uJA12FBHO+/q2tcytejkOWKWMJj6Y
+2etwIHcpzXaEP7fZ75cFGqcE3s7XGsweBIPLjMP1bKxEcFKzygURm/auUuXBCFBl
+E16PB6JEAeCKe/8VFeyucvjPuQDWB49aq+r2SbpbI4IeZdz/QgEIOb0MpwStrvhH
+9f/DtGMbjvuAEkRoOorK4m5k4GY3LsWTR2bey27AXk8N7pKarpu2N7ChBPm+EV0Y
+H+tAI/OfdZuNUCES00F5UAFdU8zBUZo19ao2ZqfEADimE7Epk2s0bUe4GSqEXJp6
+68oVSMhZmMf/RCSNlr97f34sNiUA1YJ0JbCRZmw8KWNm9H1PARLbrgeRBZ/k31Li
+WLDr3fiEVk7SGxj3zo94cS6AT55DyXLiSD/bFmL1QXgZweA=
 -----END CERTIFICATE-----
 -----BEGIN CERTIFICATE-----
-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
-9Xpi4ds6s2cT8zZGDKI=
+MIIFFTCCAv2gAwIBAgIUGXgsGl4sGhiPwUPOme5w5jJscVQwDQYJKoZIhvcNAQEL
+BQAwGjEYMBYGA1UEAwwPcG9ueXRvd24gUlNBIENBMB4XDTE5MDYwOTE3MTUxMVoX
+DTI5MDYwNjE3MTUxMVowGjEYMBYGA1UEAwwPcG9ueXRvd24gUlNBIENBMIICIjAN
+BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEArpW4WHfSmTCMvnDJaCRL5BR2knDc
+C+T4/wv7i//zsBL3q0YVdBpllWCZx8TSfuXT/1o/Zxdt+H1ZjnH8yuwuHOToE3W0
++Y/912hAPiD+d79A+MtqVX1gayjHDy9HybznTN2Onh1ZhWyks0FLL5SB0vVCLwXP
+W7tcyY0w6wn3RTw4nBu7co5a280cHgHv5V3XeNgteQrnkXE9TfuqqUZwVt0v1jr1
+bk1KaDDD+36wfeO70Q6CeLwKPhN0mPDHdj/lecj4efl0l1B0ehHxLkLuztqtkCF6
++yMoBrEyzJjO6TGMSTMsnw4F9bA15jkIIEQs5FhwVHFOTmu5BG+j37umoy27k5As
+5cV0/djr3r8WhBZ6w2+XjvbAdJPgqc+Xobnx1i5GI4noRC4G4Cl0Vx+iRru1/nsE
+xPazz9UVkiUsDlN9n49f1pik9z74Box6CD6IZVb8h4vV7um+0R4/eErVf/Cyf1Xe
+axVaOgA/CD0ucLdSfDz61O/2PG3P7YjWY1R9zr35e8pakgyFPXnWMbsfniuGkM0X
+6lG743Q7yVt38/HuAqi1AGq+r/AKisrezt97UNm0CryuEk02y4SVLbhuG/V6mBCh
+4Va3KD1ZOgfJcTZbuxebIz6W+5jL80hE0YwBBs8vSv8Fo5N7dYNSNvyMxkoPh8Gw
+CAFyqt5zBLGCEvkCAwEAAaNTMFEwHQYDVR0OBBYEFDjj6hEpDZdjAIdvd9Moe3un
+RvJWMB8GA1UdIwQYMBaAFDjj6hEpDZdjAIdvd9Moe3unRvJWMA8GA1UdEwEB/wQF
+MAMBAf8wDQYJKoZIhvcNAQELBQADggIBACu+Ct6J+Dh3EXFOgjW3gN3CaD0UK0kW
+03u7znNAJBAYhi+MXSTPBdrxYGOPkHF1Jl15qb2fc58+0nakf8bvah8kgxi2ujX8
+vrPBjsAv/ixPvUrcol9ZGrseP5DdFS8pw1FoDR/JdgNCdSM4xC3GSk2SLYs+QSJx
+YG3nQLOAZEvnbiZ4zBZ0wVct4w9jrxtqdq2eS8cLoRVx715MzKPBCGEccYu/py5a
+gkyclr16s0mb+wN49of34AQ+xXguHZGNZzCy6PTbx0IC+sRVe82+RZkj21JG+AFM
+9s+vLgRdtWIEZW1AIYbUUbhuvsne+sidZW5XQuFp1V4LlQbO49oEhrPMBn+oHKg5
+MWIe68bjkqDSnDzG+TEBTWiAhyyGyZcebfCs72DGbYrfKt1uTyi+groumPnvQfJB
+y3kqy2pUFeEkNJkx4BfYL+N7I07s9WTy8UMoqn/OLuyqoFaYMd9XMaOOx3xTy8aw
+pUJ69c3VI66W/Ii1ypk2EPUImWpG/n89Y/8Mk1NbesaZLk9feTDfbM4VNPkQU+7T
+3DNQxPSswSh4nXGURwC46SOu2s1lRA98ZXkP5XhUvTuvfg/e4suq26OqjORHQ5zI
+57NP+uHRrfHGlrQ196j1Maw7W7vkocbEv8/06v6s54CG8ezzD2nt1QrLJqSpUqHo
+qolvgn/PK+gg
 -----END CERTIFICATE-----
diff --git a/samplecode/tls/tlsserver/bin/end.rsa b/samplecode/tls/tlsserver/bin/end.rsa
index 47deca38..4ba9c7a9 100644
--- a/samplecode/tls/tlsserver/bin/end.rsa
+++ b/samplecode/tls/tlsserver/bin/end.rsa
@@ -1,27 +1,27 @@
 -----BEGIN RSA PRIVATE KEY-----
-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
+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
 -----END RSA PRIVATE KEY-----
diff --git a/sgx_align_struct_attribute/Cargo.toml b/sgx_align_struct_attribute/Cargo.toml
index 5cadf18e..5403d72b 100644
--- a/sgx_align_struct_attribute/Cargo.toml
+++ b/sgx_align_struct_attribute/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "sgx_align_struct_attribute"
-version = "1.1.5"
+version = "1.1.6"
 authors = ["The Teaclave Authors"]
 repository = "https://github.com/apache/teaclave-sgx-sdk"
 license-file = "LICENSE"
diff --git a/sgx_align_struct_attribute/src/layout.rs b/sgx_align_struct_attribute/src/layout.rs
index 861f9eee..356885a5 100644
--- a/sgx_align_struct_attribute/src/layout.rs
+++ b/sgx_align_struct_attribute/src/layout.rs
@@ -124,7 +124,7 @@ fn check_align_req(size: usize, align_req: &[AlignReq]) -> bool {
 
 fn gen_alignmask(al: usize, a: usize, m: u64) -> i64 {
     if a > al {
-        gen_alignmask(al, (a >> 1) as usize, m | (m >> (a >> 1)))
+        gen_alignmask(al, a >> 1, m | (m >> (a >> 1)))
     } else {
         m as i64
     }
diff --git a/sgx_alloc/Cargo.toml b/sgx_alloc/Cargo.toml
index f0d1f1c2..58ce519f 100644
--- a/sgx_alloc/Cargo.toml
+++ b/sgx_alloc/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "sgx_alloc"
-version = "1.1.5"
+version = "1.1.6"
 authors = ["The Teaclave Authors"]
 repository = "https://github.com/apache/teaclave-sgx-sdk"
 license-file = "LICENSE"
diff --git a/sgx_alloc/src/alignalloc.rs b/sgx_alloc/src/alignalloc.rs
index b83c130c..ffd292d7 100644
--- a/sgx_alloc/src/alignalloc.rs
+++ b/sgx_alloc/src/alignalloc.rs
@@ -308,7 +308,7 @@ mod platform {
 
     fn gen_alignmask(al: usize, a: usize, m: u64) -> i64 {
         if a > al {
-            gen_alignmask(al, (a >> 1) as usize, m | (m >> (a >> 1)))
+            gen_alignmask(al, a >> 1, m | (m >> (a >> 1)))
         } else {
             m as i64
         }
diff --git a/sgx_alloc/src/alignbox.rs b/sgx_alloc/src/alignbox.rs
index 5a888b2d..594f1004 100644
--- a/sgx_alloc/src/alignbox.rs
+++ b/sgx_alloc/src/alignbox.rs
@@ -60,25 +60,25 @@ impl<T> DerefMut for AlignBox<T> {
 
 impl<T> AsRef<T> for AlignBox<T> {
     fn as_ref(&self) -> &T {
-        &**self
+        self
     }
 }
 
 impl<T> AsMut<T> for AlignBox<T> {
     fn as_mut(&mut self) -> &mut T {
-        &mut **self
+        self
     }
 }
 
 impl<T> borrow::Borrow<T> for AlignBox<T> {
     fn borrow(&self) -> &T {
-        &**self
+        self
     }
 }
 
 impl<T> borrow::BorrowMut<T> for AlignBox<T> {
     fn borrow_mut(&mut self) -> &mut T {
-        &mut **self
+        self
     }
 }
 
diff --git a/sgx_backtrace/Cargo.toml b/sgx_backtrace/Cargo.toml
index cab06623..3aa45670 100644
--- a/sgx_backtrace/Cargo.toml
+++ b/sgx_backtrace/Cargo.toml
@@ -1,7 +1,7 @@
 
 [package]
 name = "sgx_backtrace"
-version = "1.1.5"
+version = "1.1.6"
 authors = ["The Teaclave Authors"]
 repository = "https://github.com/apache/teaclave-sgx-sdk"
 license-file = "LICENSE"
diff --git a/sgx_backtrace_sys/Cargo.toml b/sgx_backtrace_sys/Cargo.toml
index e7669112..cc3425a5 100644
--- a/sgx_backtrace_sys/Cargo.toml
+++ b/sgx_backtrace_sys/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "sgx_backtrace_sys"
-version = "1.1.5"
+version = "1.1.6"
 authors = ["The Teaclave Authors"]
 repository = "https://github.com/apache/teaclave-sgx-sdk"
 license-file = "LICENSE"
diff --git a/sgx_build_helper/Cargo.toml b/sgx_build_helper/Cargo.toml
index dc23478c..49649ef6 100644
--- a/sgx_build_helper/Cargo.toml
+++ b/sgx_build_helper/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "sgx_build_helper"
-version = "1.1.5"
+version = "1.1.6"
 authors = ["The Teaclave Authors"]
 repository = "https://github.com/apache/teaclave-sgx-sdk"
 license-file = "LICENSE"
diff --git a/sgx_cov/Cargo.toml b/sgx_cov/Cargo.toml
index e53df42f..78ec10a0 100644
--- a/sgx_cov/Cargo.toml
+++ b/sgx_cov/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "sgx_cov"
-version = "1.1.5"
+version = "1.1.6"
 authors = ["The Teaclave Authors"]
 repository = "https://github.com/apache/teaclave-sgx-sdk"
 license-file = "LICENSE"
diff --git a/sgx_crypto_helper/Cargo.toml b/sgx_crypto_helper/Cargo.toml
index c4967401..1f37036b 100644
--- a/sgx_crypto_helper/Cargo.toml
+++ b/sgx_crypto_helper/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "sgx_crypto_helper"
-version = "1.1.5"
+version = "1.1.6"
 authors = ["The Teaclave Authors"]
 repository = "https://github.com/apache/teaclave-sgx-sdk"
 license-file = "LICENSE"
diff --git a/sgx_demangle/Cargo.toml b/sgx_demangle/Cargo.toml
index f2578e1e..e836f4ea 100644
--- a/sgx_demangle/Cargo.toml
+++ b/sgx_demangle/Cargo.toml
@@ -1,7 +1,7 @@
 
 [package]
 name = "sgx_demangle"
-version = "1.1.5"
+version = "1.1.6"
 authors = ["The Teaclave Authors"]
 repository = "https://github.com/apache/teaclave-sgx-sdk"
 license-file = "LICENSE"
diff --git a/sgx_edl/Cargo.toml b/sgx_edl/Cargo.toml
index e0adf67f..8956085b 100644
--- a/sgx_edl/Cargo.toml
+++ b/sgx_edl/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "sgx_edl"
-version = "1.1.5"
+version = "1.1.6"
 authors = ["The Teaclave Authors"]
 repository = "https://github.com/apache/teaclave-sgx-sdk"
 license-file = "LICENSE"
diff --git a/sgx_edl/edl/sgx_fd.edl b/sgx_edl/edl/sgx_fd.edl
index 8cfc822e..cd668b71 100644
--- a/sgx_edl/edl/sgx_fd.edl
+++ b/sgx_edl/edl/sgx_fd.edl
@@ -19,6 +19,7 @@ enclave {
 
     include "inc/stat.h"
     include "sys/uio.h"
+    include "time.h"
 
     from "sgx_mem.edl" import *;
 
@@ -37,11 +38,20 @@ enclave {
         size_t u_writev_ocall([out] int *error, int fd, [in, count=iovcnt] const struct iovec *iov, int iovcnt);
         size_t u_pwritev64_ocall([out] int *error, int fd, [in, count=iovcnt] const struct iovec *iov, int iovcnt, int64_t offset);
 
+        size_t u_sendfile_ocall([out] int *error, int out_fd, int in_fd, [in, out] int64_t *offset, size_t count);
+        size_t u_copy_file_range_ocall([out] int *error, int fd_in, [in, out] int64_t *off_in, int fd_out, [in, out] int64_t *off_out, size_t len, unsigned int flags);
+        size_t u_splice_ocall([out] int *error, int fd_in, [in, out] int64_t *off_in, int fd_out, [in, out] int64_t *off_out, size_t len, unsigned int flags);
+
         int u_fcntl_arg0_ocall([out] int *error, int fd, int cmd);
         int u_fcntl_arg1_ocall([out] int *error, int fd, int cmd, int arg);
         int u_ioctl_arg0_ocall([out] int *error, int fd, int request);
         int u_ioctl_arg1_ocall([out] int *error, int fd, int request, [in, out] int *arg);
 
         int u_close_ocall([out] int *error, int fd);
+        int u_isatty_ocall([out] int *error, int fd);
+        int u_dup_ocall([out] int *error, int oldfd);
+        int u_eventfd_ocall([out] int *error, unsigned int initval, int flags);
+
+        int u_futimens_ocall([out] int *error, int fd, [in, count=2] const struct timespec *times);
     };
 };
diff --git a/sgx_libc/Cargo.toml b/sgx_libc/Cargo.toml
index 1a46645a..749f059a 100644
--- a/sgx_libc/Cargo.toml
+++ b/sgx_libc/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "sgx_libc"
-version = "1.1.5"
+version = "1.1.6"
 authors = ["The Teaclave Authors"]
 repository = "https://github.com/apache/teaclave-sgx-sdk"
 license-file = "LICENSE"
diff --git a/sgx_libc/src/lib.rs b/sgx_libc/src/lib.rs
index 01d2dd1d..4ec71889 100644
--- a/sgx_libc/src/lib.rs
+++ b/sgx_libc/src/lib.rs
@@ -22,6 +22,7 @@
 #![allow(overflowing_literals)]
 #![allow(non_snake_case)]
 #![allow(unused_macros)]
+#![allow(unused_imports)]
 #![allow(clippy::cmp_null)]
 #![allow(unused_assignments)]
 #![allow(clippy::missing_safety_doc)]
diff --git a/sgx_libc/src/linux/x86_64/mod.rs b/sgx_libc/src/linux/x86_64/mod.rs
index dc55613b..213c2064 100644
--- a/sgx_libc/src/linux/x86_64/mod.rs
+++ b/sgx_libc/src/linux/x86_64/mod.rs
@@ -110,7 +110,7 @@ extern "C" {
 
 /// Get the last error number.
 pub fn errno() -> i32 {
-    unsafe { (*errno_location()) as i32 }
+    unsafe { *errno_location() }
 }
 
 /// Set the last error number.
@@ -121,7 +121,7 @@ pub fn set_errno(e: i32) {
 /// Gets a detailed string description for the given error number.
 pub unsafe fn error_string(errno: i32, buf: &mut [i8]) -> i32 {
     let p = buf.as_mut_ptr();
-    strerror_r(errno as c_int, p as *mut c_char, buf.len()) as i32
+    strerror_r(errno as c_int, p as *mut c_char, buf.len())
 }
 
 pub unsafe fn memchr(s: *const u8, c: u8, n: usize) -> *const u8 {
@@ -512,6 +512,9 @@ pub const AT_SYMLINK_NOFOLLOW: c_int = 0x100;
 pub const AT_REMOVEDIR: c_int = 0x200;
 pub const AT_SYMLINK_FOLLOW: c_int = 0x400;
 
+pub const UTIME_OMIT: c_long = 1073741822;
+pub const UTIME_NOW: c_long = 1073741823;
+
 pub const CLOCK_REALTIME: clockid_t = 0;
 pub const CLOCK_MONOTONIC: clockid_t = 1;
 pub const CLOCK_PROCESS_CPUTIME_ID: clockid_t = 2;
@@ -1420,7 +1423,7 @@ pub const SA_NOCLDWAIT: c_int = 0x00000002;
 
 pub const SIG_DFL: sighandler_t = 0_usize;
 pub const SIG_IGN: sighandler_t = 1_usize;
-pub const SIG_ERR: sighandler_t = !0 as usize;
+pub const SIG_ERR: sighandler_t = !0_usize;
 
 pub const SIGTRAP: c_int = 5;
 pub const SIGCHLD: c_int = 17;
@@ -1562,7 +1565,7 @@ unsafe fn __sigdelset(set: *mut sigset_t, sig: c_int) {
 unsafe fn __sigismember(set: *const sigset_t, sig: c_int) -> c_int {
     let mask: u64 = __sigmask(sig);
     let word: u64 = __sigword(sig);
-    let val = if mask != 0 { 1 } else { 0 };
+    let val = u64::from(mask != 0);
     ((*set).__val[word as usize] & val) as c_int
 }
 
@@ -1617,7 +1620,7 @@ pub const fn CMSG_ALIGN(len: usize) -> usize {
 
 #[inline]
 pub unsafe fn CMSG_FIRSTHDR(mhdr: *const msghdr) -> *mut cmsghdr {
-    if (*mhdr).msg_controllen as usize >= mem::size_of::<cmsghdr>() {
+    if (*mhdr).msg_controllen >= mem::size_of::<cmsghdr>() {
         (*mhdr).msg_control as *mut cmsghdr
     } else {
         ptr::null_mut::<cmsghdr>()
@@ -1641,13 +1644,13 @@ pub unsafe fn CMSG_LEN(length: c_uint) -> c_uint {
 
 #[inline]
 pub unsafe fn CMSG_NXTHDR(mhdr: *const msghdr, cmsg: *const cmsghdr) -> *mut cmsghdr {
-    if ((*cmsg).cmsg_len as usize) < mem::size_of::<cmsghdr>() {
+    if ((*cmsg).cmsg_len) < mem::size_of::<cmsghdr>() {
         return ptr::null_mut::<cmsghdr>();
     };
-    let next = (cmsg as usize + CMSG_ALIGN((*cmsg).cmsg_len as usize)) as *mut cmsghdr;
-    let max = (*mhdr).msg_control as usize + (*mhdr).msg_controllen as usize;
+    let next = (cmsg as usize + CMSG_ALIGN((*cmsg).cmsg_len)) as *mut cmsghdr;
+    let max = (*mhdr).msg_control as usize + (*mhdr).msg_controllen;
     if (next.offset(1)) as usize > max
-        || next as usize + CMSG_ALIGN((*next).cmsg_len as usize) > max
+        || next as usize + CMSG_ALIGN((*next).cmsg_len) > max
     {
         ptr::null_mut::<cmsghdr>()
     } else {
diff --git a/sgx_libc/src/linux/x86_64/ocall.rs b/sgx_libc/src/linux/x86_64/ocall.rs
index c6a0c826..422a5f82 100644
--- a/sgx_libc/src/linux/x86_64/ocall.rs
+++ b/sgx_libc/src/linux/x86_64/ocall.rs
@@ -351,6 +351,34 @@ extern "C" {
         iovcnt: c_int,
         offset: off64_t,
     ) -> sgx_status_t;
+    pub fn u_sendfile_ocall(
+        result: *mut ssize_t,
+        errno: *mut c_int,
+        out_fd: c_int,
+        in_fd: c_int,
+        offset: *mut off_t,
+        count: size_t,
+    ) -> sgx_status_t;
+    pub fn u_copy_file_range_ocall(
+        result: *mut ssize_t,
+        errno: *mut c_int,
+        fd_in: c_int,
+        off_in: *mut loff_t,
+        fd_out: c_int,
+        off_out: *mut loff_t,
+        len: size_t,
+        flags: c_uint,
+    ) -> sgx_status_t;
+    pub fn u_splice_ocall(
+        result: *mut ssize_t,
+        errno: *mut c_int,
+        fd_in: c_int,
+        off_in: *mut loff_t,
+        fd_out: c_int,
+        off_out: *mut loff_t,
+        len: size_t,
+        flags: c_uint,
+    ) -> sgx_status_t;
     pub fn u_fcntl_arg0_ocall(
         result: *mut c_int,
         errno: *mut c_int,
@@ -378,6 +406,20 @@ extern "C" {
         arg: *mut c_int,
     ) -> sgx_status_t;
     pub fn u_close_ocall(result: *mut c_int, errno: *mut c_int, fd: c_int) -> sgx_status_t;
+    pub fn u_isatty_ocall(result: *mut c_int, errno: *mut c_int, fd: c_int) -> sgx_status_t;
+    pub fn u_dup_ocall(result: *mut c_int, errno: *mut c_int, oldfd: c_int) -> sgx_status_t;
+    pub fn u_eventfd_ocall(
+        result: *mut c_int,
+        errno: *mut c_int,
+        initval: c_uint,
+        flags: c_int,
+    ) -> sgx_status_t;
+    pub fn u_futimens_ocall(
+        result: *mut c_int,
+        errno: *mut c_int,
+        fd: c_int,
+        times: *const timespec,
+    ) -> sgx_status_t;
     // time
     pub fn u_clock_gettime_ocall(
         result: *mut c_int,
@@ -2173,7 +2215,7 @@ pub unsafe fn writev(fd: c_int, iov: *const iovec, iovcnt: c_int) -> ssize_t {
         ptr::copy_nonoverlapping(
             io.iov_base as *const u8,
             tmpiov.iov_base as *mut u8,
-            io.iov_len as usize,
+            io.iov_len,
         );
         tmpiovec.push(tmpiov);
         ptr = ptr.add(io.iov_len);
@@ -2260,7 +2302,7 @@ pub unsafe fn pwritev64(fd: c_int, iov: *const iovec, iovcnt: c_int, offset: off
         ptr::copy_nonoverlapping(
             io.iov_base as *const u8,
             tmpiov.iov_base as *mut u8,
-            io.iov_len as usize,
+            io.iov_len,
         );
         tmpiovec.push(tmpiov);
         ptr = ptr.add(io.iov_len);
@@ -2292,6 +2334,95 @@ pub unsafe fn pwritev64(fd: c_int, iov: *const iovec, iovcnt: c_int, offset: off
     result
 }
 
+pub unsafe fn sendfile(out_fd: c_int, in_fd: c_int, offset: *mut off_t, count: size_t) -> ssize_t {
+    let mut result: ssize_t = 0;
+    let mut error: c_int = 0;
+    let status = u_sendfile_ocall(
+        &mut result as *mut ssize_t,
+        &mut error as *mut c_int,
+        out_fd,
+        in_fd,
+        offset,
+        count,
+    );
+
+    if status == sgx_status_t::SGX_SUCCESS {
+        if result == -1 {
+            set_errno(error);
+        }
+    } else {
+        set_errno(ESGX);
+        result = -1;
+    }
+    result
+}
+
+pub unsafe fn copy_file_range(
+    fd_in: c_int,
+    off_in: *mut loff_t,
+    fd_out: c_int,
+    off_out: *mut loff_t,
+    len: size_t,
+    flags: c_uint,
+) -> ssize_t {
+    let mut result: ssize_t = 0;
+    let mut error: c_int = 0;
+
+    let status = u_copy_file_range_ocall(
+        &mut result as *mut ssize_t,
+        &mut error as *mut c_int,
+        fd_in,
+        off_in,
+        fd_out,
+        off_out,
+        len,
+        flags,
+    );
+
+    if status == sgx_status_t::SGX_SUCCESS {
+        if result == -1 {
+            set_errno(error);
+        }
+    } else {
+        set_errno(ESGX);
+        result = -1;
+    }
+    result
+}
+
+pub unsafe fn splice(
+    fd_in: c_int,
+    off_in: *mut loff_t,
+    fd_out: c_int,
+    off_out: *mut loff_t,
+    len: size_t,
+    flags: c_uint,
+) -> ssize_t {
+    let mut result: ssize_t = 0;
+    let mut error: c_int = 0;
+
+    let status = u_splice_ocall(
+        &mut result as *mut ssize_t,
+        &mut error as *mut c_int,
+        fd_in,
+        off_in,
+        fd_out,
+        off_out,
+        len,
+        flags,
+    );
+
+    if status == sgx_status_t::SGX_SUCCESS {
+        if result == -1 {
+            set_errno(error);
+        }
+    } else {
+        set_errno(ESGX);
+        result = -1;
+    }
+    result
+}
+
 pub unsafe fn fcntl_arg0(fd: c_int, cmd: c_int) -> c_int {
     let mut result: c_int = 0;
     let mut error: c_int = 0;
@@ -2389,6 +2520,78 @@ pub unsafe fn close(fd: c_int) -> c_int {
     result
 }
 
+pub unsafe fn isatty(fd: c_int) -> c_int {
+    let mut result: c_int = 0;
+    let mut error: c_int = 0;
+    let status = u_isatty_ocall(&mut result as *mut c_int, &mut error as *mut c_int, fd);
+    if status == sgx_status_t::SGX_SUCCESS {
+        if result == 0 {
+            set_errno(error);
+        }
+    } else {
+        set_errno(ESGX);
+        result = 0;
+    }
+    result
+}
+
+pub unsafe fn dup(oldfd: c_int) -> c_int {
+    let mut result: c_int = 0;
+    let mut error: c_int = 0;
+    let status = u_dup_ocall(&mut result as *mut c_int, &mut error as *mut c_int, oldfd);
+    if status == sgx_status_t::SGX_SUCCESS {
+        if result < 0 {
+            set_errno(error);
+        }
+    } else {
+        set_errno(ESGX);
+        result = -1;
+    }
+    result
+}
+
+pub unsafe fn eventfd(initval: c_uint, flags: c_int) -> c_int {
+    let mut result: c_int = 0;
+    let mut error: c_int = 0;
+    let status = u_eventfd_ocall(
+        &mut result as *mut c_int,
+        &mut error as *mut c_int,
+        initval,
+        flags,
+    );
+    if status == sgx_status_t::SGX_SUCCESS {
+        if result < 0 {
+            set_errno(error);
+        }
+    } else {
+        set_errno(ESGX);
+        result = -1;
+    }
+    result
+}
+
+pub unsafe fn futimens(fd: c_int, times: *const timespec) -> c_int {
+    let mut result: c_int = 0;
+    let mut error: c_int = 0;
+
+    let status = u_futimens_ocall(
+        &mut result as *mut c_int,
+        &mut error as *mut c_int,
+        fd,
+        times,
+    );
+
+    if status == sgx_status_t::SGX_SUCCESS {
+        if result < 0 {
+            set_errno(error);
+        }
+    } else {
+        set_errno(ESGX);
+        result = -1;
+    }
+    result
+}
+
 // time
 pub unsafe fn clock_gettime(clk_id: clockid_t, tp: *mut timespec) -> c_int {
     let mut result: c_int = 0;
@@ -3041,7 +3244,7 @@ pub unsafe fn recvmsg(sockfd: c_int, msg: *mut msghdr, flags: c_int) -> ssize_t
             }
         }
 
-        mhdr.msg_namelen = msg_namelen_out as u32;
+        mhdr.msg_namelen = msg_namelen_out;
         mhdr.msg_controllen = msg_controllen_out;
         mhdr.msg_flags = msg_flags;
     }
diff --git a/sgx_no_tstd/Cargo.toml b/sgx_no_tstd/Cargo.toml
index d85aab82..e5f116f5 100644
--- a/sgx_no_tstd/Cargo.toml
+++ b/sgx_no_tstd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "sgx_no_tstd"
-version = "1.1.5"
+version = "1.1.6"
 authors = ["The Teaclave Authors"]
 build = "build.rs"
 repository = "https://github.com/apache/teaclave-sgx-sdk"
diff --git a/sgx_panic_abort/src/lib.rs b/sgx_panic_abort/src/lib.rs
index 86925c36..b4b90016 100644
--- a/sgx_panic_abort/src/lib.rs
+++ b/sgx_panic_abort/src/lib.rs
@@ -8,7 +8,6 @@
 #![panic_runtime]
 #![allow(unused_features)]
 #![feature(core_intrinsics)]
-#![feature(nll)]
 #![feature(panic_runtime)]
 #![feature(std_internals)]
 #![feature(staged_api)]
@@ -18,12 +17,14 @@
 use core::any::Any;
 use core::panic::BoxMeUp;
 
+/// # Safety
 #[rustc_std_internal_symbol]
 #[allow(improper_ctypes_definitions)]
 pub unsafe extern "C" fn __rust_panic_cleanup(_: *mut u8) -> *mut (dyn Any + Send + 'static) {
     unreachable!()
 }
 
+/// # Safety
 // "Leak" the payload and shim to the relevant abort on the platform in question.
 #[rustc_std_internal_symbol]
 pub unsafe extern "C-unwind" fn __rust_start_panic(_payload: *mut &mut dyn BoxMeUp) -> u32 {
@@ -66,6 +67,14 @@ pub unsafe extern "C-unwind" fn __rust_start_panic(_payload: *mut &mut dyn BoxMe
 // binaries, but it should never be called as we don't link in an unwinding
 // runtime at all.
 pub mod personalities {
-    #[rustc_std_internal_symbol]
-    pub extern "C" fn rust_eh_personality() {}
+    // In the past this module used to contain stubs for the personality
+    // functions of various platforms, but these where removed when personality
+    // functions were moved to std.
+
+    // This corresponds to the `eh_catch_typeinfo` lang item
+    // that's only used on Emscripten currently.
+    //
+    // Since panics don't generate exceptions and foreign exceptions are
+    // currently UB with -C panic=abort (although this may be subject to
+    // change), any catch_unwind calls will never use this typeinfo.
 }
diff --git a/sgx_panic_unwind/src/gcc.rs b/sgx_panic_unwind/src/gcc.rs
index 56d95ea3..a539b590 100644
--- a/sgx_panic_unwind/src/gcc.rs
+++ b/sgx_panic_unwind/src/gcc.rs
@@ -39,8 +39,6 @@
 use alloc::boxed::Box;
 use core::any::Any;
 
-use crate::dwarf::eh::{self, EHAction, EHContext};
-use sgx_libc::{c_int, uintptr_t};
 use sgx_unwind as uw;
 
 #[repr(C)]
@@ -89,79 +87,3 @@ fn rust_exception_class() -> uw::_Unwind_Exception_Class {
     // M O Z \0  R U S T -- vendor, language
     0x4d4f_5a00_5255_5354
 }
-
-// Register ids were lifted from LLVM's TargetLowering::getExceptionPointerRegister()
-// and TargetLowering::getExceptionSelectorRegister() for each architecture,
-// then mapped to DWARF register numbers via register definition tables
-// (typically <arch>RegisterInfo.td, search for "DwarfRegNum").
-// See also https://llvm.org/docs/WritingAnLLVMBackend.html#defining-a-register.
-
-#[cfg(target_arch = "x86")]
-const UNWIND_DATA_REG: (i32, i32) = (0, 2); // EAX, EDX
-
-#[cfg(target_arch = "x86_64")]
-const UNWIND_DATA_REG: (i32, i32) = (0, 1); // RAX, RDX
-
-// The following code is based on GCC's C and C++ personality routines.  For reference, see:
-// https://github.com/gcc-mirror/gcc/blob/master/libstdc++-v3/libsupc++/eh_personality.cc
-// https://github.com/gcc-mirror/gcc/blob/trunk/libgcc/unwind-c.c
-
-unsafe extern "C" fn rust_eh_personality_impl(
-    version: c_int,
-    actions: uw::_Unwind_Action,
-    _exception_class: uw::_Unwind_Exception_Class,
-    exception_object: *mut uw::_Unwind_Exception,
-    context: *mut uw::_Unwind_Context,
-) -> uw::_Unwind_Reason_Code {
-    if version != 1 {
-        return uw::_URC_FATAL_PHASE1_ERROR;
-    }
-    let eh_action = match find_eh_action(context) {
-        Ok(action) => action,
-        Err(_) => return uw::_URC_FATAL_PHASE1_ERROR,
-    };
-    if actions as i32 & uw::_UA_SEARCH_PHASE as i32 != 0 {
-        match eh_action {
-            EHAction::None | EHAction::Cleanup(_) => uw::_URC_CONTINUE_UNWIND,
-            EHAction::Catch(_) => uw::_URC_HANDLER_FOUND,
-            EHAction::Terminate => uw::_URC_FATAL_PHASE1_ERROR,
-        }
-    } else {
-        match eh_action {
-            EHAction::None => uw::_URC_CONTINUE_UNWIND,
-            EHAction::Cleanup(lpad) | EHAction::Catch(lpad) => {
-                uw::_Unwind_SetGR(context, UNWIND_DATA_REG.0, exception_object as uintptr_t);
-                uw::_Unwind_SetGR(context, UNWIND_DATA_REG.1, 0);
-                uw::_Unwind_SetIP(context, lpad);
-                uw::_URC_INSTALL_CONTEXT
-            }
-            EHAction::Terminate => uw::_URC_FATAL_PHASE2_ERROR,
-        }
-    }
-}
-
-#[lang = "eh_personality"]
-unsafe extern "C" fn rust_eh_personality(
-    version: c_int,
-    actions: uw::_Unwind_Action,
-    exception_class: uw::_Unwind_Exception_Class,
-    exception_object: *mut uw::_Unwind_Exception,
-    context: *mut uw::_Unwind_Context,
-) -> uw::_Unwind_Reason_Code {
-    rust_eh_personality_impl(version, actions, exception_class, exception_object, context)
-}
-
-unsafe fn find_eh_action(context: *mut uw::_Unwind_Context) -> Result<EHAction, ()> {
-    let lsda = uw::_Unwind_GetLanguageSpecificData(context) as *const u8;
-    let mut ip_before_instr: c_int = 0;
-    let ip = uw::_Unwind_GetIPInfo(context, &mut ip_before_instr);
-    let eh_context = EHContext {
-        // The return address points 1 byte past the call instruction,
-        // which could be in the next IP range in LSDA range table.
-        ip: if ip_before_instr != 0 { ip } else { ip - 1 },
-        func_start: uw::_Unwind_GetRegionStart(context),
-        get_text_start: &|| uw::_Unwind_GetTextRelBase(context),
-        get_data_start: &|| uw::_Unwind_GetDataRelBase(context),
-    };
-    eh::find_eh_action(lsda, &eh_context)
-}
diff --git a/sgx_panic_unwind/src/lib.rs b/sgx_panic_unwind/src/lib.rs
index 3e2e111b..6d0ba761 100644
--- a/sgx_panic_unwind/src/lib.rs
+++ b/sgx_panic_unwind/src/lib.rs
@@ -1,7 +1,15 @@
 //! Implementation of panics via stack unwinding
 //!
 //! This crate is an implementation of panics in Rust using "most native" stack
-//! unwinding mechanism of the platform this is being compiled for.
+//! unwinding mechanism of the platform this is being compiled for. This
+//! essentially gets categorized into three buckets currently:
+//!
+//! 1. MSVC targets use SEH in the `seh.rs` file.
+//! 2. Emscripten uses C++ exceptions in the `emcc.rs` file.
+//! 3. All other targets use libunwind/libgcc in the `gcc.rs` file.
+//!
+//! More documentation about each implementation can be found in the respective
+//! module.
 
 #![no_std]
 #![unstable(feature = "panic_unwind", issue = "32837")]
@@ -12,7 +20,6 @@
 
 #![feature(core_intrinsics)]
 #![feature(lang_items)]
-#![feature(nll)]
 #![feature(panic_unwind)]
 #![feature(staged_api)]
 #![feature(std_internals)]
@@ -23,7 +30,6 @@
 #![feature(c_unwind)]
 
 extern crate alloc;
-extern crate sgx_libc;
 extern crate sgx_unwind;
 
 use alloc::boxed::Box;
@@ -42,8 +48,6 @@ extern "C" {
     fn __rust_foreign_exception() -> !;
 }
 
-mod dwarf;
-
 /// # Safety
 #[rustc_std_internal_symbol]
 #[allow(improper_ctypes_definitions)]
@@ -55,7 +59,7 @@ pub unsafe extern "C" fn __rust_panic_cleanup(payload: *mut u8) -> *mut (dyn Any
 // Entry point for raising an exception, just delegates to the platform-specific
 // implementation.
 #[rustc_std_internal_symbol]
-pub unsafe extern "C-unwind" fn __rust_start_panic(payload: *mut &mut dyn BoxMeUp) -> u32 {
+pub unsafe fn __rust_start_panic(payload: *mut &mut dyn BoxMeUp) -> u32 {
     let payload = Box::from_raw((*payload).take_box());
 
     imp::panic(payload)
diff --git a/sgx_rand/Cargo.toml b/sgx_rand/Cargo.toml
index bdd11ffb..5eda5362 100644
--- a/sgx_rand/Cargo.toml
+++ b/sgx_rand/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "sgx_rand"
-version = "1.1.5"
+version = "1.1.6"
 authors = ["The Teaclave Authors"]
 repository = "https://github.com/apache/teaclave-sgx-sdk"
 license-file = "LICENSE"
diff --git a/sgx_rand_derive/Cargo.toml b/sgx_rand_derive/Cargo.toml
index 442abfeb..c4a04b40 100644
--- a/sgx_rand_derive/Cargo.toml
+++ b/sgx_rand_derive/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "sgx_rand_derive"
-version = "1.1.5"
+version = "1.1.6"
 authors = ["The Teaclave Authors"]
 repository = "https://github.com/apache/teaclave-sgx-sdk"
 license-file = "LICENSE"
diff --git a/sgx_serialize/Cargo.toml b/sgx_serialize/Cargo.toml
index 457e0093..ccbf57af 100644
--- a/sgx_serialize/Cargo.toml
+++ b/sgx_serialize/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "sgx_serialize"
-version = "1.1.5"
+version = "1.1.6"
 authors = ["The Teaclave Authors"]
 repository = "https://github.com/apache/teaclave-sgx-sdk"
 license-file = "LICENSE"
diff --git a/sgx_serialize_derive/Cargo.toml b/sgx_serialize_derive/Cargo.toml
index a9f40849..c9aff5a7 100644
--- a/sgx_serialize_derive/Cargo.toml
+++ b/sgx_serialize_derive/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "sgx_serialize_derive"
-version = "1.1.5"
+version = "1.1.6"
 authors = ["The Teaclave Authors"]
 repository = "https://github.com/apache/teaclave-sgx-sdk"
 license-file = "LICENSE"
diff --git a/sgx_serialize_derive_internals/Cargo.toml b/sgx_serialize_derive_internals/Cargo.toml
index 499039d8..7ef5a874 100644
--- a/sgx_serialize_derive_internals/Cargo.toml
+++ b/sgx_serialize_derive_internals/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "sgx_serialize_derive_internals"
-version = "1.1.5"
+version = "1.1.6"
 authors = ["The Teaclave Authors"]
 repository = "https://github.com/apache/teaclave-sgx-sdk"
 license-file = "LICENSE"
diff --git a/sgx_signal/Cargo.toml b/sgx_signal/Cargo.toml
index 2502991e..84b1eef4 100644
--- a/sgx_signal/Cargo.toml
+++ b/sgx_signal/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "sgx_signal"
-version = "1.1.5"
+version = "1.1.6"
 authors = ["The Teaclave Authors"]
 repository = "https://github.com/apache/teaclave-sgx-sdk"
 license-file = "LICENSE"
diff --git a/sgx_signal/src/exception.rs b/sgx_signal/src/exception.rs
index daa541ed..dfeb0627 100644
--- a/sgx_signal/src/exception.rs
+++ b/sgx_signal/src/exception.rs
@@ -26,7 +26,7 @@ use std::collections::LinkedList;
 use std::convert::From;
 use std::num::NonZeroU64;
 use std::ops::Drop;
-use std::sync::{Arc, Once, SgxRwLock, SgxThreadMutex, ONCE_INIT};
+use std::sync::{Arc, Once, SgxRwLock, SgxMutex, PoisonError, ONCE_INIT};
 use std::u64;
 
 #[repr(u32)]
@@ -53,19 +53,21 @@ pub struct HandlerId(NonZeroU64);
 
 impl HandlerId {
     fn new() -> HandlerId {
-        static GUARD: SgxThreadMutex = SgxThreadMutex::new();
-        static mut COUNTER: u64 = 1;
-
-        unsafe {
-            let _guard = GUARD.lock();
-            if COUNTER == u64::MAX {
-                panic!("failed to generate unique HandlerId : bitspace exhausted");
-            }
-            let id = COUNTER;
-            COUNTER += 1;
-            let _ = GUARD.unlock();
-            HandlerId(NonZeroU64::new(id).unwrap())
+        #[cold]
+        fn exhausted() -> ! {
+            panic!("failed to generate unique Handler ID: bitspace exhausted")
         }
+        static COUNTER: SgxMutex<u64> = SgxMutex::new(0);
+
+        let mut counter = COUNTER.lock().unwrap_or_else(PoisonError::into_inner);
+        let Some(id) = counter.checked_add(1) else {
+            drop(counter);
+            exhausted();
+        };
+
+        *counter = id;
+        drop(counter);
+        HandlerId(NonZeroU64::new(id).unwrap())
     }
 }
 
diff --git a/sgx_signal/src/manager.rs b/sgx_signal/src/manager.rs
index 9484e2db..bbf67991 100644
--- a/sgx_signal/src/manager.rs
+++ b/sgx_signal/src/manager.rs
@@ -25,7 +25,7 @@ use std::mem;
 use std::num::NonZeroU64;
 use std::sync::Arc;
 #[allow(deprecated)]
-use std::sync::{SgxMutex, SgxThreadMutex};
+use std::sync::{SgxMutex, PoisonError};
 use std::u64;
 
 thread_local! { static SIGNAL_MASK: Cell<SigSet> = Cell::new(SigSet::new()) }
@@ -145,20 +145,25 @@ pub struct ActionId(NonZeroU64);
 
 impl ActionId {
     fn new() -> Self {
-        static GUARD: SgxThreadMutex = SgxThreadMutex::new();
-        static mut COUNTER: u64 = 1;
-
-        unsafe {
-            let _guard = GUARD.lock();
-            if COUNTER == u64::MAX {
-                panic!("failed to generate unique ActionId : bitspace exhausted");
-            }
-            let id = COUNTER;
-            COUNTER += 1;
-            let _ = GUARD.unlock();
-            ActionId(NonZeroU64::new(id).unwrap())
+        #[cold]
+        fn exhausted() -> ! {
+            panic!("failed to generate unique Action ID: bitspace exhausted")
         }
+
+        static COUNTER: SgxMutex<u64> = SgxMutex::new(0);
+
+        let mut counter = COUNTER.lock().unwrap_or_else(PoisonError::into_inner);
+        let Some(id) = counter.checked_add(1) else {
+            drop(counter);
+            exhausted();
+        };
+
+        *counter = id;
+        drop(counter);
+        ActionId(NonZeroU64::new(id).unwrap())
     }
+
+    
 }
 
 pub type Action = dyn Fn(&siginfo_t) + Send + Sync;
diff --git a/sgx_tcrypto/Cargo.toml b/sgx_tcrypto/Cargo.toml
index 24e88205..7aa6a4ad 100644
--- a/sgx_tcrypto/Cargo.toml
+++ b/sgx_tcrypto/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "sgx_tcrypto"
-version = "1.1.5"
+version = "1.1.6"
 authors = ["The Teaclave Authors"]
 repository = "https://github.com/apache/teaclave-sgx-sdk"
 license-file = "LICENSE"
diff --git a/sgx_tcrypto_helper/Cargo.toml b/sgx_tcrypto_helper/Cargo.toml
index 2498690f..6e252fba 100644
--- a/sgx_tcrypto_helper/Cargo.toml
+++ b/sgx_tcrypto_helper/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "sgx_tcrypto_helper"
-version = "1.1.5"
+version = "1.1.6"
 authors = ["The Teaclave Authors"]
 repository = "https://github.com/apache/teaclave-sgx-sdk"
 license-file = "LICENSE"
diff --git a/sgx_tdh/Cargo.toml b/sgx_tdh/Cargo.toml
index 2283440c..c417be8a 100644
--- a/sgx_tdh/Cargo.toml
+++ b/sgx_tdh/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "sgx_tdh"
-version = "1.1.5"
+version = "1.1.6"
 authors = ["The Teaclave Authors"]
 repository = "https://github.com/apache/teaclave-sgx-sdk"
 license-file = "LICENSE"
diff --git a/sgx_tkey_exchange/Cargo.toml b/sgx_tkey_exchange/Cargo.toml
index 9f670260..f3234128 100644
--- a/sgx_tkey_exchange/Cargo.toml
+++ b/sgx_tkey_exchange/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "sgx_tkey_exchange"
-version = "1.1.5"
+version = "1.1.6"
 authors = ["The Teaclave Authors"]
 repository = "https://github.com/apache/teaclave-sgx-sdk"
 license-file = "LICENSE"
diff --git a/sgx_tprotected_fs/Cargo.toml b/sgx_tprotected_fs/Cargo.toml
index 2db16b69..d6b3e0bf 100644
--- a/sgx_tprotected_fs/Cargo.toml
+++ b/sgx_tprotected_fs/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "sgx_tprotected_fs"
-version = "1.1.5"
+version = "1.1.6"
 authors = ["The Teaclave Authors"]
 repository = "https://github.com/apache/teaclave-sgx-sdk"
 license-file = "LICENSE"
diff --git a/sgx_trts/Cargo.toml b/sgx_trts/Cargo.toml
index 385801a1..a8df5226 100644
--- a/sgx_trts/Cargo.toml
+++ b/sgx_trts/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "sgx_trts"
-version = "1.1.5"
+version = "1.1.6"
 authors = ["The Teaclave Authors"]
 repository = "https://github.com/apache/teaclave-sgx-sdk"
 license-file = "LICENSE"
diff --git a/sgx_trts/src/c_str.rs b/sgx_trts/src/c_str.rs
index da052e16..7c9b0f77 100644
--- a/sgx_trts/src/c_str.rs
+++ b/sgx_trts/src/c_str.rs
@@ -15,1534 +15,5 @@
 // specific language governing permissions and limitations
 // under the License..
 
-use crate::ascii;
-use crate::libc;
-use crate::memchr;
-use alloc::borrow::{Borrow, Cow, ToOwned};
-use alloc::boxed::Box;
-use alloc::rc::Rc;
-use alloc::slice;
-use alloc::str::{self, Utf8Error};
-use alloc::string::String;
-use alloc::sync::Arc;
-use alloc::vec::Vec;
-use core::cmp::Ordering;
-use core::fmt::{self, Write};
-use core::mem;
-use core::num::NonZeroU8;
-use core::ops;
-use core::ptr;
-use sgx_types::c_char;
-
-/// A type representing an owned, C-compatible, nul-terminated string with no nul bytes in the
-/// middle.
-///
-/// This type serves the purpose of being able to safely generate a
-/// C-compatible string from a Rust byte slice or vector. An instance of this
-/// type is a static guarantee that the underlying bytes contain no interior 0
-/// bytes ("nul characters") and that the final byte is 0 ("nul terminator").
-///
-/// `CString` is to <code>&[CStr]</code> as [`String`] is to <code>&[str]</code>: the former
-/// in each pair are owned strings; the latter are borrowed
-/// references.
-///
-/// # Creating a `CString`
-///
-/// A `CString` is created from either a byte slice or a byte vector,
-/// or anything that implements <code>[Into]<[Vec]<[u8]>></code> (for
-/// example, you can build a `CString` straight out of a [`String`] or
-/// a <code>&[str]</code>, since both implement that trait).
-///
-/// The [`CString::new`] method will actually check that the provided <code>&[[u8]]</code>
-/// does not have 0 bytes in the middle, and return an error if it
-/// finds one.
-///
-/// # Extracting a raw pointer to the whole C string
-///
-/// `CString` implements an [`as_ptr`][`CStr::as_ptr`] method through the [`Deref`]
-/// trait. This method will give you a `*const c_char` which you can
-/// feed directly to extern functions that expect a nul-terminated
-/// string, like C's `strdup()`. Notice that [`as_ptr`][`CStr::as_ptr`] returns a
-/// read-only pointer; if the C code writes to it, that causes
-/// undefined behavior.
-///
-/// # Extracting a slice of the whole C string
-///
-/// Alternatively, you can obtain a <code>&[[u8]]</code> slice from a
-/// `CString` with the [`CString::as_bytes`] method. Slices produced in this
-/// way do *not* contain the trailing nul terminator. This is useful
-/// when you will be calling an extern function that takes a `*const
-/// u8` argument which is not necessarily nul-terminated, plus another
-/// argument with the length of the string — like C's `strndup()`.
-/// You can of course get the slice's length with its
-/// [`len`][slice::len] method.
-///
-/// If you need a <code>&[[u8]]</code> slice *with* the nul terminator, you
-/// can use [`CString::as_bytes_with_nul`] instead.
-///
-/// Once you have the kind of slice you need (with or without a nul
-/// terminator), you can call the slice's own
-/// [`as_ptr`][slice::as_ptr] method to get a read-only raw pointer to pass to
-/// extern functions. See the documentation for that function for a
-/// discussion on ensuring the lifetime of the raw pointer.
-///
-/// [str]: prim@str "str"
-/// [`Deref`]: ops::Deref
-///
-/// # Examples
-///
-/// ```ignore (extern-declaration)
-/// # fn main() {
-/// use std::ffi::CString;
-/// use std::os::raw::c_char;
-///
-/// extern "C" {
-///     fn my_printer(s: *const c_char);
-/// }
-///
-/// // We are certain that our string doesn't have 0 bytes in the middle,
-/// // so we can .expect()
-/// let c_to_print = CString::new("Hello, world!").expect("CString::new failed");
-/// unsafe {
-///     my_printer(c_to_print.as_ptr());
-/// }
-/// # }
-/// ```
-///
-/// # Safety
-///
-/// `CString` is intended for working with traditional C-style strings
-/// (a sequence of non-nul bytes terminated by a single nul byte); the
-/// primary use case for these kinds of strings is interoperating with C-like
-/// code. Often you will need to transfer ownership to/from that external
-/// code. It is strongly recommended that you thoroughly read through the
-/// documentation of `CString` before use, as improper ownership management
-/// of `CString` instances can lead to invalid memory accesses, memory leaks,
-/// and other memory errors.
-#[derive(PartialEq, PartialOrd, Eq, Ord, Hash, Clone)]
-#[cfg_attr(not(test), rustc_diagnostic_item = "cstring_type")]
-pub struct CString {
-    // Invariant 1: the slice ends with a zero byte and has a length of at least one.
-    // Invariant 2: the slice contains only one zero byte.
-    // Improper usage of unsafe function can break Invariant 2, but not Invariant 1.
-    inner: Box<[u8]>,
-}
-
-/// Representation of a borrowed C string.
-///
-/// This type represents a borrowed reference to a nul-terminated
-/// array of bytes. It can be constructed safely from a <code>&[[u8]]</code>
-/// slice, or unsafely from a raw `*const c_char`. It can then be
-/// converted to a Rust <code>&[str]</code> by performing UTF-8 validation, or
-/// into an owned [`CString`].
-///
-/// `&CStr` is to [`CString`] as <code>&[str]</code> is to [`String`]: the former
-/// in each pair are borrowed references; the latter are owned
-/// strings.
-///
-/// Note that this structure is **not** `repr(C)` and is not recommended to be
-/// placed in the signatures of FFI functions. Instead, safe wrappers of FFI
-/// functions may leverage the unsafe [`CStr::from_ptr`] constructor to provide
-/// a safe interface to other consumers.
-///
-/// # Examples
-///
-/// Inspecting a foreign C string:
-///
-/// ```ignore (extern-declaration)
-/// use std::ffi::CStr;
-/// use std::os::raw::c_char;
-///
-/// extern "C" { fn my_string() -> *const c_char; }
-///
-/// unsafe {
-///     let slice = CStr::from_ptr(my_string());
-///     println!("string buffer size without nul terminator: {}", slice.to_bytes().len());
-/// }
-/// ```
-///
-/// Passing a Rust-originating C string:
-///
-/// ```ignore (extern-declaration)
-/// use std::ffi::{CString, CStr};
-/// use std::os::raw::c_char;
-///
-/// fn work(data: &CStr) {
-///     extern "C" { fn work_with(data: *const c_char); }
-///
-///     unsafe { work_with(data.as_ptr()) }
-/// }
-///
-/// let s = CString::new("data data data data").expect("CString::new failed");
-/// work(&s);
-/// ```
-///
-/// Converting a foreign C string into a Rust [`String`]:
-///
-/// ```ignore (extern-declaration)
-/// use std::ffi::CStr;
-/// use std::os::raw::c_char;
-///
-/// extern "C" { fn my_string() -> *const c_char; }
-///
-/// fn my_string_safe() -> String {
-///     unsafe {
-///         CStr::from_ptr(my_string()).to_string_lossy().into_owned()
-///     }
-/// }
-///
-/// println!("string: {}", my_string_safe());
-/// ```
-///
-/// [str]: prim@str "str"
-#[derive(Hash)]
-#[cfg_attr(not(test), rustc_diagnostic_item = "CStr")]
-// FIXME:
-// `fn from` in `impl From<&CStr> for Box<CStr>` current implementation relies
-// on `CStr` being layout-compatible with `[u8]`.
-// When attribute privacy is implemented, `CStr` should be annotated as `#[repr(transparent)]`.
-// Anyway, `CStr` representation and layout are considered implementation detail, are
-// not documented and must not be relied upon.
-pub struct CStr {
-    // FIXME: this should not be represented with a DST slice but rather with
-    //        just a raw `c_char` along with some form of marker to make
-    //        this an unsized type. Essentially `sizeof(&CStr)` should be the
-    //        same as `sizeof(&c_char)` but `CStr` should be an unsized type.
-    inner: [c_char],
-}
-
-/// An error indicating that an interior nul byte was found.
-///
-/// While Rust strings may contain nul bytes in the middle, C strings
-/// can't, as that byte would effectively truncate the string.
-///
-/// This error is created by the [`new`][`CString::new`] method on
-/// [`CString`]. See its documentation for more.
-///
-/// # Examples
-///
-/// ```
-/// use std::ffi::{CString, NulError};
-///
-/// let _: NulError = CString::new(b"f\0oo".to_vec()).unwrap_err();
-/// ```
-#[derive(Clone, PartialEq, Eq, Debug)]
-pub struct NulError(usize, Vec<u8>);
-
-impl fmt::Display for NulError {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "nul byte found in provided data at position: {}", self.0)
-    }
-}
-
-/// An error indicating that a nul byte was not in the expected position.
-///
-/// The slice used to create a [`CStr`] must have one and only one nul byte,
-/// positioned at the end.
-///
-/// This error is created by the [`CStr::from_bytes_with_nul`] method.
-/// See its documentation for more.
-///
-/// # Examples
-///
-/// ```
-/// use std::ffi::{CStr, FromBytesWithNulError};
-///
-/// let _: FromBytesWithNulError = CStr::from_bytes_with_nul(b"f\0oo").unwrap_err();
-/// ```
-#[derive(Clone, PartialEq, Eq, Debug)]
-pub struct FromBytesWithNulError {
-    kind: FromBytesWithNulErrorKind,
-}
-
-impl fmt::Display for FromBytesWithNulError {
-    #[allow(deprecated, deprecated_in_future)]
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.write_str(self.__description())?;
-        if let FromBytesWithNulErrorKind::InteriorNul(pos) = self.kind {
-            write!(f, " at byte pos {}", pos)?;
-        }
-        Ok(())
-    }
-}
-
-impl FromBytesWithNulError {
-    fn interior_nul(pos: usize) -> FromBytesWithNulError {
-        FromBytesWithNulError {
-            kind: FromBytesWithNulErrorKind::InteriorNul(pos),
-        }
-    }
-
-    fn not_nul_terminated() -> FromBytesWithNulError {
-        FromBytesWithNulError {
-            kind: FromBytesWithNulErrorKind::NotNulTerminated,
-        }
-    }
-
-    pub fn __description(&self) -> &str {
-        match self.kind {
-            FromBytesWithNulErrorKind::InteriorNul(..) => {
-                "data provided contains an interior nul byte"
-            }
-            FromBytesWithNulErrorKind::NotNulTerminated => "data provided is not nul terminated",
-        }
-    }
-}
-
-/// An error indicating that a nul byte was not in the expected position.
-///
-/// The vector used to create a [`CString`] must have one and only one nul byte,
-/// positioned at the end.
-///
-/// This error is created by the [`CString::from_vec_with_nul`] method.
-/// See its documentation for more.
-///
-/// # Examples
-///
-/// ```
-/// use std::ffi::{CString, FromVecWithNulError};
-///
-/// let _: FromVecWithNulError = CString::from_vec_with_nul(b"f\0oo".to_vec()).unwrap_err();
-/// ```
-#[derive(Clone, PartialEq, Eq, Debug)]
-pub struct FromVecWithNulError {
-    error_kind: FromBytesWithNulErrorKind,
-    bytes: Vec<u8>,
-}
-
-impl fmt::Display for FromVecWithNulError {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self.error_kind {
-            FromBytesWithNulErrorKind::InteriorNul(pos) => {
-                write!(
-                    f,
-                    "data provided contains an interior nul byte at pos {}",
-                    pos
-                )
-            }
-            FromBytesWithNulErrorKind::NotNulTerminated => {
-                write!(f, "data provided is not nul terminated")
-            }
-        }
-    }
-}
-
-#[derive(Clone, PartialEq, Eq, Debug)]
-enum FromBytesWithNulErrorKind {
-    InteriorNul(usize),
-    NotNulTerminated,
-}
-
-impl FromVecWithNulError {
-    /// Returns a slice of [`u8`]s bytes that were attempted to convert to a [`CString`].
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// use std::ffi::CString;
-    ///
-    /// // Some invalid bytes in a vector
-    /// let bytes = b"f\0oo".to_vec();
-    ///
-    /// let value = CString::from_vec_with_nul(bytes.clone());
-    ///
-    /// assert_eq!(&bytes[..], value.unwrap_err().as_bytes());
-    /// ```
-    #[must_use]
-    pub fn as_bytes(&self) -> &[u8] {
-        &self.bytes[..]
-    }
-
-    /// Returns the bytes that were attempted to convert to a [`CString`].
-    ///
-    /// This method is carefully constructed to avoid allocation. It will
-    /// consume the error, moving out the bytes, so that a copy of the bytes
-    /// does not need to be made.
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// use std::ffi::CString;
-    ///
-    /// // Some invalid bytes in a vector
-    /// let bytes = b"f\0oo".to_vec();
-    ///
-    /// let value = CString::from_vec_with_nul(bytes.clone());
-    ///
-    /// assert_eq!(bytes, value.unwrap_err().into_bytes());
-    /// ```
-    #[must_use = "`self` will be dropped if the result is not used"]
-    pub fn into_bytes(self) -> Vec<u8> {
-        self.bytes
-    }
-}
-
-/// An error indicating invalid UTF-8 when converting a [`CString`] into a [`String`].
-///
-/// `CString` is just a wrapper over a buffer of bytes with a nul terminator;
-/// [`CString::into_string`] performs UTF-8 validation on those bytes and may
-/// return this error.
-///
-/// This `struct` is created by [`CString::into_string()`]. See
-/// its documentation for more.
-#[derive(Clone, PartialEq, Eq, Debug)]
-pub struct IntoStringError {
-    inner: CString,
-    error: Utf8Error,
-}
-
-impl IntoStringError {
-    #[allow(deprecated)]
-    pub fn __description(&self) -> &str {
-        "C string contained non-utf8 bytes"
-    }
-
-    pub fn __source(&self) -> &Utf8Error {
-        &self.error
-    }
-}
-
-impl fmt::Display for IntoStringError {
-    #[allow(deprecated, deprecated_in_future)]
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        self.__description().fmt(f)
-    }
-}
-
-impl CString {
-    /// Creates a new C-compatible string from a container of bytes.
-    ///
-    /// This function will consume the provided data and use the
-    /// underlying bytes to construct a new string, ensuring that
-    /// there is a trailing 0 byte. This trailing 0 byte will be
-    /// appended by this function; the provided data should *not*
-    /// contain any 0 bytes in it.
-    ///
-    /// # Examples
-    ///
-    /// ```ignore (extern-declaration)
-    /// use std::ffi::CString;
-    /// use std::os::raw::c_char;
-    ///
-    /// extern "C" { fn puts(s: *const c_char); }
-    ///
-    /// let to_print = CString::new("Hello!").expect("CString::new failed");
-    /// unsafe {
-    ///     puts(to_print.as_ptr());
-    /// }
-    /// ```
-    ///
-    /// # Errors
-    ///
-    /// This function will return an error if the supplied bytes contain an
-    /// internal 0 byte. The [`NulError`] returned will contain the bytes as well as
-    /// the position of the nul byte.
-    pub fn new<T: Into<Vec<u8>>>(t: T) -> Result<CString, NulError> {
-        trait SpecNewImpl {
-            fn spec_new_impl(self) -> Result<CString, NulError>;
-        }
-
-        impl<T: Into<Vec<u8>>> SpecNewImpl for T {
-            default fn spec_new_impl(self) -> Result<CString, NulError> {
-                let bytes: Vec<u8> = self.into();
-                match memchr::memchr(0, &bytes) {
-                    Some(i) => Err(NulError(i, bytes)),
-                    None => Ok(unsafe { CString::_from_vec_unchecked(bytes) }),
-                }
-            }
-        }
-
-        // Specialization for avoiding reallocation
-        #[inline(always)] // Without that it is not inlined into specializations
-        fn spec_new_impl_bytes(bytes: &[u8]) -> Result<CString, NulError> {
-            // We cannot have such large slice that we would overflow here
-            // but using `checked_add` allows LLVM to assume that capacity never overflows
-            // and generate twice shorter code.
-            // `saturating_add` doesn't help for some reason.
-            let capacity = bytes.len().checked_add(1).unwrap();
-
-            // Allocate before validation to avoid duplication of allocation code.
-            // We still need to allocate and copy memory even if we get an error.
-            let mut buffer = Vec::with_capacity(capacity);
-            buffer.extend(bytes);
-
-            // Check memory of self instead of new buffer.
-            // This allows better optimizations if lto enabled.
-            match memchr::memchr(0, bytes) {
-                Some(i) => Err(NulError(i, buffer)),
-                None => Ok(unsafe { CString::_from_vec_unchecked(buffer) }),
-            }
-        }
-
-        impl SpecNewImpl for &'_ [u8] {
-            fn spec_new_impl(self) -> Result<CString, NulError> {
-                spec_new_impl_bytes(self)
-            }
-        }
-
-        impl SpecNewImpl for &'_ str {
-            fn spec_new_impl(self) -> Result<CString, NulError> {
-                spec_new_impl_bytes(self.as_bytes())
-            }
-        }
-
-        impl SpecNewImpl for &'_ mut [u8] {
-            fn spec_new_impl(self) -> Result<CString, NulError> {
-                spec_new_impl_bytes(self)
-            }
-        }
-
-        t.spec_new_impl()
-    }
-
-    /// Creates a C-compatible string by consuming a byte vector,
-    /// without checking for interior 0 bytes.
-    ///
-    /// Trailing 0 byte will be appended by this function.
-    ///
-    /// This method is equivalent to [`CString::new`] except that no runtime
-    /// assertion is made that `v` contains no 0 bytes, and it requires an
-    /// actual byte vector, not anything that can be converted to one with Into.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::ffi::CString;
-    ///
-    /// let raw = b"foo".to_vec();
-    /// unsafe {
-    ///     let c_string = CString::from_vec_unchecked(raw);
-    /// }
-    /// ```
-    #[must_use]
-    pub unsafe fn from_vec_unchecked(v: Vec<u8>) -> Self {
-        debug_assert!(memchr::memchr(0, &v).is_none());
-        Self::_from_vec_unchecked(v)
-    }
-
-    unsafe fn _from_vec_unchecked(mut v: Vec<u8>) -> Self {
-        v.reserve_exact(1);
-        v.push(0);
-        Self {
-            inner: v.into_boxed_slice(),
-        }
-    }
-
-    /// Retakes ownership of a `CString` that was transferred to C via
-    /// [`CString::into_raw`].
-    ///
-    /// Additionally, the length of the string will be recalculated from the pointer.
-    ///
-    /// # Safety
-    ///
-    /// This should only ever be called with a pointer that was earlier
-    /// obtained by calling [`CString::into_raw`]. Other usage (e.g., trying to take
-    /// ownership of a string that was allocated by foreign code) is likely to lead
-    /// to undefined behavior or allocator corruption.
-    ///
-    /// It should be noted that the length isn't just "recomputed," but that
-    /// the recomputed length must match the original length from the
-    /// [`CString::into_raw`] call. This means the [`CString::into_raw`]/`from_raw`
-    /// methods should not be used when passing the string to C functions that can
-    /// modify the string's length.
-    ///
-    /// > **Note:** If you need to borrow a string that was allocated by
-    /// > foreign code, use [`CStr`]. If you need to take ownership of
-    /// > a string that was allocated by foreign code, you will need to
-    /// > make your own provisions for freeing it appropriately, likely
-    /// > with the foreign code's API to do that.
-    ///
-    /// # Examples
-    ///
-    /// Creates a `CString`, pass ownership to an `extern` function (via raw pointer), then retake
-    /// ownership with `from_raw`:
-    ///
-    /// ```ignore (extern-declaration)
-    /// use std::ffi::CString;
-    /// use std::os::raw::c_char;
-    ///
-    /// extern "C" {
-    ///     fn some_extern_function(s: *mut c_char);
-    /// }
-    ///
-    /// let c_string = CString::new("Hello!").expect("CString::new failed");
-    /// let raw = c_string.into_raw();
-    /// unsafe {
-    ///     some_extern_function(raw);
-    ///     let c_string = CString::from_raw(raw);
-    /// }
-    /// ```
-    #[must_use = "call `drop(from_raw(ptr))` if you intend to drop the `CString`"]
-    pub unsafe fn from_raw(ptr: *mut c_char) -> CString {
-        // SAFETY: This is called with a pointer that was obtained from a call
-        // to `CString::into_raw` and the length has not been modified. As such,
-        // we know there is a NUL byte (and only one) at the end and that the
-        // information about the size of the allocation is correct on Rust's
-        // side.
-        let len = libc::strlen(ptr) + 1; // Including the NUL byte
-        let slice = slice::from_raw_parts_mut(ptr, len as usize);
-        CString {
-            inner: Box::from_raw(slice as *mut [c_char] as *mut [u8]),
-        }
-    }
-
-    /// Consumes the `CString` and transfers ownership of the string to a C caller.
-    ///
-    /// The pointer which this function returns must be returned to Rust and reconstituted using
-    /// [`CString::from_raw`] to be properly deallocated. Specifically, one
-    /// should *not* use the standard C `free()` function to deallocate
-    /// this string.
-    ///
-    /// Failure to call [`CString::from_raw`] will lead to a memory leak.
-    ///
-    /// The C side must **not** modify the length of the string (by writing a
-    /// `null` somewhere inside the string or removing the final one) before
-    /// it makes it back into Rust using [`CString::from_raw`]. See the safety section
-    /// in [`CString::from_raw`].
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::ffi::CString;
-    ///
-    /// let c_string = CString::new("foo").expect("CString::new failed");
-    ///
-    /// let ptr = c_string.into_raw();
-    ///
-    /// unsafe {
-    ///     assert_eq!(b'f', *ptr as u8);
-    ///     assert_eq!(b'o', *ptr.offset(1) as u8);
-    ///     assert_eq!(b'o', *ptr.offset(2) as u8);
-    ///     assert_eq!(b'\0', *ptr.offset(3) as u8);
-    ///
-    ///     // retake pointer to free memory
-    ///     let _ = CString::from_raw(ptr);
-    /// }
-    /// ```
-    #[inline]
-    #[must_use = "`self` will be dropped if the result is not used"]
-    pub fn into_raw(self) -> *mut c_char {
-        Box::into_raw(self.into_inner()) as *mut c_char
-    }
-
-    /// Converts the `CString` into a [`String`] if it contains valid UTF-8 data.
-    ///
-    /// On failure, ownership of the original `CString` is returned.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::ffi::CString;
-    ///
-    /// let valid_utf8 = vec![b'f', b'o', b'o'];
-    /// let cstring = CString::new(valid_utf8).expect("CString::new failed");
-    /// assert_eq!(cstring.into_string().expect("into_string() call failed"), "foo");
-    ///
-    /// let invalid_utf8 = vec![b'f', 0xff, b'o', b'o'];
-    /// let cstring = CString::new(invalid_utf8).expect("CString::new failed");
-    /// let err = cstring.into_string().err().expect("into_string().err() failed");
-    /// assert_eq!(err.utf8_error().valid_up_to(), 1);
-    /// ```
-    pub fn into_string(self) -> Result<String, IntoStringError> {
-        String::from_utf8(self.into_bytes()).map_err(|e| IntoStringError {
-            error: e.utf8_error(),
-            inner: unsafe { Self::_from_vec_unchecked(e.into_bytes()) },
-        })
-    }
-
-    /// Consumes the `CString` and returns the underlying byte buffer.
-    ///
-    /// The returned buffer does **not** contain the trailing nul
-    /// terminator, and it is guaranteed to not have any interior nul
-    /// bytes.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::ffi::CString;
-    ///
-    /// let c_string = CString::new("foo").expect("CString::new failed");
-    /// let bytes = c_string.into_bytes();
-    /// assert_eq!(bytes, vec![b'f', b'o', b'o']);
-    /// ```
-    #[must_use = "`self` will be dropped if the result is not used"]
-    pub fn into_bytes(self) -> Vec<u8> {
-        let mut vec = self.into_inner().into_vec();
-        let _nul = vec.pop();
-        debug_assert_eq!(_nul, Some(0u8));
-        vec
-    }
-
-    /// Equivalent to [`CString::into_bytes()`] except that the
-    /// returned vector includes the trailing nul terminator.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::ffi::CString;
-    ///
-    /// let c_string = CString::new("foo").expect("CString::new failed");
-    /// let bytes = c_string.into_bytes_with_nul();
-    /// assert_eq!(bytes, vec![b'f', b'o', b'o', b'\0']);
-    /// ```
-    #[must_use = "`self` will be dropped if the result is not used"]
-    pub fn into_bytes_with_nul(self) -> Vec<u8> {
-        self.into_inner().into_vec()
-    }
-
-    /// Returns the contents of this `CString` as a slice of bytes.
-    ///
-    /// The returned slice does **not** contain the trailing nul
-    /// terminator, and it is guaranteed to not have any interior nul
-    /// bytes. If you need the nul terminator, use
-    /// [`CString::as_bytes_with_nul`] instead.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::ffi::CString;
-    ///
-    /// let c_string = CString::new("foo").expect("CString::new failed");
-    /// let bytes = c_string.as_bytes();
-    /// assert_eq!(bytes, &[b'f', b'o', b'o']);
-    /// ```
-    #[inline]
-    #[must_use]
-    pub fn as_bytes(&self) -> &[u8] {
-        // SAFETY: CString has a length at least 1
-        unsafe { self.inner.get_unchecked(..self.inner.len() - 1) }
-    }
-
-    /// Equivalent to [`CString::as_bytes()`] except that the
-    /// returned slice includes the trailing nul terminator.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::ffi::CString;
-    ///
-    /// let c_string = CString::new("foo").expect("CString::new failed");
-    /// let bytes = c_string.as_bytes_with_nul();
-    /// assert_eq!(bytes, &[b'f', b'o', b'o', b'\0']);
-    /// ```
-    #[inline]
-    #[must_use]
-    pub fn as_bytes_with_nul(&self) -> &[u8] {
-        &self.inner
-    }
-
-    /// Extracts a [`CStr`] slice containing the entire string.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::ffi::{CString, CStr};
-    ///
-    /// let c_string = CString::new(b"foo".to_vec()).expect("CString::new failed");
-    /// let cstr = c_string.as_c_str();
-    /// assert_eq!(cstr,
-    ///            CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed"));
-    /// ```
-    #[inline]
-    #[must_use]
-    pub fn as_c_str(&self) -> &CStr {
-        &*self
-    }
-
-    /// Converts this `CString` into a boxed [`CStr`].
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::ffi::{CString, CStr};
-    ///
-    /// let c_string = CString::new(b"foo".to_vec()).expect("CString::new failed");
-    /// let boxed = c_string.into_boxed_c_str();
-    /// assert_eq!(&*boxed,
-    ///            CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed"));
-    /// ```
-    #[must_use = "`self` will be dropped if the result is not used"]
-    pub fn into_boxed_c_str(self) -> Box<CStr> {
-        unsafe { Box::from_raw(Box::into_raw(self.into_inner()) as *mut CStr) }
-    }
-
-    /// Bypass "move out of struct which implements [`Drop`] trait" restriction.
-    #[inline]
-    fn into_inner(self) -> Box<[u8]> {
-        // Rationale: `mem::forget(self)` invalidates the previous call to `ptr::read(&self.inner)`
-        // so we use `ManuallyDrop` to ensure `self` is not dropped.
-        // Then we can return the box directly without invalidating it.
-        // See https://github.com/rust-lang/rust/issues/62553.
-        let this = mem::ManuallyDrop::new(self);
-        unsafe { ptr::read(&this.inner) }
-    }
-
-    /// Converts a <code>[Vec]<[u8]></code> to a [`CString`] without checking the
-    /// invariants on the given [`Vec`].
-    ///
-    /// # Safety
-    ///
-    /// The given [`Vec`] **must** have one nul byte as its last element.
-    /// This means it cannot be empty nor have any other nul byte anywhere else.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use std::ffi::CString;
-    /// assert_eq!(
-    ///     unsafe { CString::from_vec_with_nul_unchecked(b"abc\0".to_vec()) },
-    ///     unsafe { CString::from_vec_unchecked(b"abc".to_vec()) }
-    /// );
-    /// ```
-    #[must_use]
-    pub unsafe fn from_vec_with_nul_unchecked(v: Vec<u8>) -> Self {
-        debug_assert!(memchr::memchr(0, &v).unwrap() + 1 == v.len());
-        Self::_from_vec_with_nul_unchecked(v)
-    }
-
-    unsafe fn _from_vec_with_nul_unchecked(v: Vec<u8>) -> Self {
-        Self {
-            inner: v.into_boxed_slice(),
-        }
-    }
-
-    /// Attempts to converts a <code>[Vec]<[u8]></code> to a [`CString`].
-    ///
-    /// Runtime checks are present to ensure there is only one nul byte in the
-    /// [`Vec`], its last element.
-    ///
-    /// # Errors
-    ///
-    /// If a nul byte is present and not the last element or no nul bytes
-    /// is present, an error will be returned.
-    ///
-    /// # Examples
-    ///
-    /// A successful conversion will produce the same result as [`CString::new`]
-    /// when called without the ending nul byte.
-    ///
-    /// ```
-    /// use std::ffi::CString;
-    /// assert_eq!(
-    ///     CString::from_vec_with_nul(b"abc\0".to_vec())
-    ///         .expect("CString::from_vec_with_nul failed"),
-    ///     CString::new(b"abc".to_vec()).expect("CString::new failed")
-    /// );
-    /// ```
-    ///
-    /// An incorrectly formatted [`Vec`] will produce an error.
-    ///
-    /// ```
-    /// use std::ffi::{CString, FromVecWithNulError};
-    /// // Interior nul byte
-    /// let _: FromVecWithNulError = CString::from_vec_with_nul(b"a\0bc".to_vec()).unwrap_err();
-    /// // No nul byte
-    /// let _: FromVecWithNulError = CString::from_vec_with_nul(b"abc".to_vec()).unwrap_err();
-    /// ```
-    pub fn from_vec_with_nul(v: Vec<u8>) -> Result<Self, FromVecWithNulError> {
-        let nul_pos = memchr::memchr(0, &v);
-        match nul_pos {
-            Some(nul_pos) if nul_pos + 1 == v.len() => {
-                // SAFETY: We know there is only one nul byte, at the end
-                // of the vec.
-                Ok(unsafe { Self::_from_vec_with_nul_unchecked(v) })
-            }
-            Some(nul_pos) => Err(FromVecWithNulError {
-                error_kind: FromBytesWithNulErrorKind::InteriorNul(nul_pos),
-                bytes: v,
-            }),
-            None => Err(FromVecWithNulError {
-                error_kind: FromBytesWithNulErrorKind::NotNulTerminated,
-                bytes: v,
-            }),
-        }
-    }
-}
-
-// Turns this `CString` into an empty string to prevent
-// memory-unsafe code from working by accident. Inline
-// to prevent LLVM from optimizing it away in debug builds.
-impl Drop for CString {
-    #[inline]
-    fn drop(&mut self) {
-        unsafe {
-            *self.inner.get_unchecked_mut(0) = 0;
-        }
-    }
-}
-
-impl ops::Deref for CString {
-    type Target = CStr;
-
-    #[inline]
-    fn deref(&self) -> &CStr {
-        unsafe { CStr::_from_bytes_with_nul_unchecked(self.as_bytes_with_nul()) }
-    }
-}
-
-impl fmt::Debug for CString {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        fmt::Debug::fmt(&**self, f)
-    }
-}
-
-impl From<CString> for Vec<u8> {
-    /// Converts a [`CString`] into a <code>[Vec]<[u8]></code>.
-    ///
-    /// The conversion consumes the [`CString`], and removes the terminating NUL byte.
-    #[inline]
-    fn from(s: CString) -> Vec<u8> {
-        s.into_bytes()
-    }
-}
-
-impl fmt::Debug for CStr {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "\"")?;
-        for byte in self
-            .to_bytes()
-            .iter()
-            .flat_map(|&b| ascii::escape_default(b))
-        {
-            f.write_char(byte as char)?;
-        }
-        write!(f, "\"")
-    }
-}
-
-impl Default for &CStr {
-    fn default() -> Self {
-        const SLICE: &[c_char] = &[0];
-        unsafe { CStr::from_ptr(SLICE.as_ptr()) }
-    }
-}
-
-impl Default for CString {
-    /// Creates an empty `CString`.
-    fn default() -> CString {
-        let a: &CStr = Default::default();
-        a.to_owned()
-    }
-}
-
-impl Borrow<CStr> for CString {
-    #[inline]
-    fn borrow(&self) -> &CStr {
-        self
-    }
-}
-
-impl<'a> From<Cow<'a, CStr>> for CString {
-    /// Converts a `Cow<'a, CStr>` into a `CString`, by copying the contents if they are
-    /// borrowed.
-    #[inline]
-    fn from(s: Cow<'a, CStr>) -> Self {
-        s.into_owned()
-    }
-}
-
-impl From<&CStr> for Box<CStr> {
-    /// Converts a `&CStr` into a `Box<CStr>`,
-    /// by copying the contents into a newly allocated [`Box`].
-    fn from(s: &CStr) -> Box<CStr> {
-        let boxed: Box<[u8]> = Box::from(s.to_bytes_with_nul());
-        unsafe { Box::from_raw(Box::into_raw(boxed) as *mut CStr) }
-    }
-}
-
-impl From<Cow<'_, CStr>> for Box<CStr> {
-    /// Converts a `Cow<'a, CStr>` into a `Box<CStr>`,
-    /// by copying the contents if they are borrowed.
-    #[inline]
-    fn from(cow: Cow<'_, CStr>) -> Box<CStr> {
-        match cow {
-            Cow::Borrowed(s) => Box::from(s),
-            Cow::Owned(s) => Box::from(s),
-        }
-    }
-}
-
-impl From<Box<CStr>> for CString {
-    /// Converts a <code>[Box]<[CStr]></code> into a [`CString`] without copying or allocating.
-    #[inline]
-    fn from(s: Box<CStr>) -> CString {
-        s.into_c_string()
-    }
-}
-
-impl From<Vec<NonZeroU8>> for CString {
-    /// Converts a <code>[Vec]<[NonZeroU8]></code> into a [`CString`] without
-    /// copying nor checking for inner null bytes.
-    #[inline]
-    fn from(v: Vec<NonZeroU8>) -> CString {
-        unsafe {
-            // Transmute `Vec<NonZeroU8>` to `Vec<u8>`.
-            let v: Vec<u8> = {
-                // SAFETY:
-                //   - transmuting between `NonZeroU8` and `u8` is sound;
-                //   - `alloc::Layout<NonZeroU8> == alloc::Layout<u8>`.
-                let (ptr, len, cap): (*mut NonZeroU8, _, _) = Vec::into_raw_parts(v);
-                Vec::from_raw_parts(ptr.cast::<u8>(), len, cap)
-            };
-            // SAFETY: `v` cannot contain null bytes, given the type-level
-            // invariant of `NonZeroU8`.
-            Self::_from_vec_unchecked(v)
-        }
-    }
-}
-
-impl Clone for Box<CStr> {
-    #[inline]
-    fn clone(&self) -> Self {
-        (**self).into()
-    }
-}
-
-impl From<CString> for Box<CStr> {
-    /// Converts a [`CString`] into a <code>[Box]<[CStr]></code> without copying or allocating.
-    #[inline]
-    fn from(s: CString) -> Box<CStr> {
-        s.into_boxed_c_str()
-    }
-}
-
-impl<'a> From<CString> for Cow<'a, CStr> {
-    /// Converts a [`CString`] into an owned [`Cow`] without copying or allocating.
-    #[inline]
-    fn from(s: CString) -> Cow<'a, CStr> {
-        Cow::Owned(s)
-    }
-}
-
-impl<'a> From<&'a CStr> for Cow<'a, CStr> {
-    /// Converts a [`CStr`] into a borrowed [`Cow`] without copying or allocating.
-    #[inline]
-    fn from(s: &'a CStr) -> Cow<'a, CStr> {
-        Cow::Borrowed(s)
-    }
-}
-
-impl<'a> From<&'a CString> for Cow<'a, CStr> {
-    /// Converts a `&`[`CString`] into a borrowed [`Cow`] without copying or allocating.
-    #[inline]
-    fn from(s: &'a CString) -> Cow<'a, CStr> {
-        Cow::Borrowed(s.as_c_str())
-    }
-}
-
-impl From<CString> for Arc<CStr> {
-    /// Converts a [`CString`] into an <code>[Arc]<[CStr]></code> by moving the [`CString`]
-    /// data into a new [`Arc`] buffer.
-    #[inline]
-    fn from(s: CString) -> Arc<CStr> {
-        let arc: Arc<[u8]> = Arc::from(s.into_inner());
-        unsafe { Arc::from_raw(Arc::into_raw(arc) as *const CStr) }
-    }
-}
-
-impl From<&CStr> for Arc<CStr> {
-    /// Converts a `&CStr` into a `Arc<CStr>`,
-    /// by copying the contents into a newly allocated [`Arc`].
-    #[inline]
-    fn from(s: &CStr) -> Arc<CStr> {
-        let arc: Arc<[u8]> = Arc::from(s.to_bytes_with_nul());
-        unsafe { Arc::from_raw(Arc::into_raw(arc) as *const CStr) }
-    }
-}
-
-impl From<CString> for Rc<CStr> {
-    /// Converts a [`CString`] into an <code>[Rc]<[CStr]></code> by moving the [`CString`]
-    /// data into a new [`Arc`] buffer.
-    #[inline]
-    fn from(s: CString) -> Rc<CStr> {
-        let rc: Rc<[u8]> = Rc::from(s.into_inner());
-        unsafe { Rc::from_raw(Rc::into_raw(rc) as *const CStr) }
-    }
-}
-
-impl From<&CStr> for Rc<CStr> {
-    /// Converts a `&CStr` into a `Rc<CStr>`,
-    /// by copying the contents into a newly allocated [`Rc`].
-    #[inline]
-    fn from(s: &CStr) -> Rc<CStr> {
-        let rc: Rc<[u8]> = Rc::from(s.to_bytes_with_nul());
-        unsafe { Rc::from_raw(Rc::into_raw(rc) as *const CStr) }
-    }
-}
-
-impl Default for Box<CStr> {
-    fn default() -> Box<CStr> {
-        let boxed: Box<[u8]> = Box::from([0]);
-        unsafe { Box::from_raw(Box::into_raw(boxed) as *mut CStr) }
-    }
-}
-
-impl NulError {
-    /// Returns the position of the nul byte in the slice that caused
-    /// [`CString::new`] to fail.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::ffi::CString;
-    ///
-    /// let nul_error = CString::new("foo\0bar").unwrap_err();
-    /// assert_eq!(nul_error.nul_position(), 3);
-    ///
-    /// let nul_error = CString::new("foo bar\0").unwrap_err();
-    /// assert_eq!(nul_error.nul_position(), 7);
-    /// ```
-    #[must_use]
-    pub fn nul_position(&self) -> usize {
-        self.0
-    }
-
-    /// Consumes this error, returning the underlying vector of bytes which
-    /// generated the error in the first place.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::ffi::CString;
-    ///
-    /// let nul_error = CString::new("foo\0bar").unwrap_err();
-    /// assert_eq!(nul_error.into_vec(), b"foo\0bar");
-    /// ```
-    #[must_use = "`self` will be dropped if the result is not used"]
-    pub fn into_vec(self) -> Vec<u8> {
-        self.1
-    }
-}
-
-impl IntoStringError {
-    /// Consumes this error, returning original [`CString`] which generated the
-    /// error.
-    #[must_use = "`self` will be dropped if the result is not used"]
-    pub fn into_cstring(self) -> CString {
-        self.inner
-    }
-
-    /// Access the underlying UTF-8 error that was the cause of this error.
-    #[must_use]
-    pub fn utf8_error(&self) -> Utf8Error {
-        self.error
-    }
-}
-
-impl CStr {
-    /// Wraps a raw C string with a safe C string wrapper.
-    ///
-    /// This function will wrap the provided `ptr` with a `CStr` wrapper, which
-    /// allows inspection and interoperation of non-owned C strings. The total
-    /// size of the raw C string must be smaller than `isize::MAX` **bytes**
-    /// in memory due to calling the `slice::from_raw_parts` function.
-    /// This method is unsafe for a number of reasons:
-    ///
-    /// * There is no guarantee to the validity of `ptr`.
-    /// * The returned lifetime is not guaranteed to be the actual lifetime of
-    ///   `ptr`.
-    /// * There is no guarantee that the memory pointed to by `ptr` contains a
-    ///   valid nul terminator byte at the end of the string.
-    /// * It is not guaranteed that the memory pointed by `ptr` won't change
-    ///   before the `CStr` has been destroyed.
-    ///
-    /// > **Note**: This operation is intended to be a 0-cost cast but it is
-    /// > currently implemented with an up-front calculation of the length of
-    /// > the string. This is not guaranteed to always be the case.
-    ///
-    /// # Examples
-    ///
-    /// ```ignore (extern-declaration)
-    /// # fn main() {
-    /// use std::ffi::CStr;
-    /// use std::os::raw::c_char;
-    ///
-    /// extern "C" {
-    ///     fn my_string() -> *const c_char;
-    /// }
-    ///
-    /// unsafe {
-    ///     let slice = CStr::from_ptr(my_string());
-    ///     println!("string returned: {}", slice.to_str().unwrap());
-    /// }
-    /// # }
-    /// ```
-    #[inline]
-    #[must_use]
-    pub unsafe fn from_ptr<'a>(ptr: *const c_char) -> &'a CStr {
-        // SAFETY: The caller has provided a pointer that points to a valid C
-        // string with a NUL terminator of size less than `isize::MAX`, whose
-        // content remain valid and doesn't change for the lifetime of the
-        // returned `CStr`.
-        //
-        // Thus computing the length is fine (a NUL byte exists), the call to
-        // from_raw_parts is safe because we know the length is at most `isize::MAX`, meaning
-        // the call to `from_bytes_with_nul_unchecked` is correct.
-        //
-        // The cast from c_char to u8 is ok because a c_char is always one byte.
-        let len = libc::strlen(ptr);
-        let ptr = ptr as *const u8;
-        Self::_from_bytes_with_nul_unchecked(slice::from_raw_parts(ptr, len as usize + 1))
-    }
-
-    /// Creates a C string wrapper from a byte slice.
-    ///
-    /// This function will cast the provided `bytes` to a `CStr`
-    /// wrapper after ensuring that the byte slice is nul-terminated
-    /// and does not contain any interior nul bytes.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::ffi::CStr;
-    ///
-    /// let cstr = CStr::from_bytes_with_nul(b"hello\0");
-    /// assert!(cstr.is_ok());
-    /// ```
-    ///
-    /// Creating a `CStr` without a trailing nul terminator is an error:
-    ///
-    /// ```
-    /// use std::ffi::CStr;
-    ///
-    /// let cstr = CStr::from_bytes_with_nul(b"hello");
-    /// assert!(cstr.is_err());
-    /// ```
-    ///
-    /// Creating a `CStr` with an interior nul byte is an error:
-    ///
-    /// ```
-    /// use std::ffi::CStr;
-    ///
-    /// let cstr = CStr::from_bytes_with_nul(b"he\0llo\0");
-    /// assert!(cstr.is_err());
-    /// ```
-    pub fn from_bytes_with_nul(bytes: &[u8]) -> Result<&Self, FromBytesWithNulError> {
-        let nul_pos = memchr::memchr(0, bytes);
-        match nul_pos {
-            Some(nul_pos) if nul_pos + 1 == bytes.len() => {
-                // SAFETY: We know there is only one nul byte, at the end
-                // of the byte slice.
-                Ok(unsafe { Self::_from_bytes_with_nul_unchecked(bytes) })
-            }
-            Some(nul_pos) => Err(FromBytesWithNulError::interior_nul(nul_pos)),
-            None => Err(FromBytesWithNulError::not_nul_terminated()),
-        }
-    }
-
-    /// Unsafely creates a C string wrapper from a byte slice.
-    ///
-    /// This function will cast the provided `bytes` to a `CStr` wrapper without
-    /// performing any sanity checks. The provided slice **must** be nul-terminated
-    /// and not contain any interior nul bytes.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::ffi::{CStr, CString};
-    ///
-    /// unsafe {
-    ///     let cstring = CString::new("hello").expect("CString::new failed");
-    ///     let cstr = CStr::from_bytes_with_nul_unchecked(cstring.to_bytes_with_nul());
-    ///     assert_eq!(cstr, &*cstring);
-    /// }
-    /// ```
-    #[inline]
-    #[must_use]
-    pub const unsafe fn from_bytes_with_nul_unchecked(bytes: &[u8]) -> &CStr {
-        // We're in a const fn, so this is the best we can do
-        debug_assert!(!bytes.is_empty() && bytes[bytes.len() - 1] == 0);
-        Self::_from_bytes_with_nul_unchecked(bytes)
-    }
-
-    #[inline]
-    const unsafe fn _from_bytes_with_nul_unchecked(bytes: &[u8]) -> &Self {
-        // SAFETY: Casting to CStr is safe because its internal representation
-        // is a [u8] too (safe only inside std).
-        // Dereferencing the obtained pointer is safe because it comes from a
-        // reference. Making a reference is then safe because its lifetime
-        // is bound by the lifetime of the given `bytes`.
-        &*(bytes as *const [u8] as *const Self)
-    }
-
-    /// Returns the inner pointer to this C string.
-    ///
-    /// The returned pointer will be valid for as long as `self` is, and points
-    /// to a contiguous region of memory terminated with a 0 byte to represent
-    /// the end of the string.
-    ///
-    /// **WARNING**
-    ///
-    /// The returned pointer is read-only; writing to it (including passing it
-    /// to C code that writes to it) causes undefined behavior.
-    ///
-    /// It is your responsibility to make sure that the underlying memory is not
-    /// freed too early. For example, the following code will cause undefined
-    /// behavior when `ptr` is used inside the `unsafe` block:
-    ///
-    /// ```no_run
-    /// # #![allow(unused_must_use)] #![allow(temporary_cstring_as_ptr)]
-    /// use std::ffi::CString;
-    ///
-    /// let ptr = CString::new("Hello").expect("CString::new failed").as_ptr();
-    /// unsafe {
-    ///     // `ptr` is dangling
-    ///     *ptr;
-    /// }
-    /// ```
-    ///
-    /// This happens because the pointer returned by `as_ptr` does not carry any
-    /// lifetime information and the [`CString`] is deallocated immediately after
-    /// the `CString::new("Hello").expect("CString::new failed").as_ptr()`
-    /// expression is evaluated.
-    /// To fix the problem, bind the `CString` to a local variable:
-    ///
-    /// ```no_run
-    /// # #![allow(unused_must_use)]
-    /// use std::ffi::CString;
-    ///
-    /// let hello = CString::new("Hello").expect("CString::new failed");
-    /// let ptr = hello.as_ptr();
-    /// unsafe {
-    ///     // `ptr` is valid because `hello` is in scope
-    ///     *ptr;
-    /// }
-    /// ```
-    ///
-    /// This way, the lifetime of the [`CString`] in `hello` encompasses
-    /// the lifetime of `ptr` and the `unsafe` block.
-    #[inline]
-    #[must_use]
-    pub const fn as_ptr(&self) -> *const c_char {
-        self.inner.as_ptr()
-    }
-
-    /// Converts this C string to a byte slice.
-    ///
-    /// The returned slice will **not** contain the trailing nul terminator that this C
-    /// string has.
-    ///
-    /// > **Note**: This method is currently implemented as a constant-time
-    /// > cast, but it is planned to alter its definition in the future to
-    /// > perform the length calculation whenever this method is called.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::ffi::CStr;
-    ///
-    /// let cstr = CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed");
-    /// assert_eq!(cstr.to_bytes(), b"foo");
-    /// ```
-    #[inline]
-    #[must_use = "this returns the result of the operation, \
-                  without modifying the original"]
-    pub fn to_bytes(&self) -> &[u8] {
-        let bytes = self.to_bytes_with_nul();
-        // SAFETY: to_bytes_with_nul returns slice with length at least 1
-        unsafe { bytes.get_unchecked(..bytes.len() - 1) }
-    }
-
-    /// Converts this C string to a byte slice containing the trailing 0 byte.
-    ///
-    /// This function is the equivalent of [`CStr::to_bytes`] except that it
-    /// will retain the trailing nul terminator instead of chopping it off.
-    ///
-    /// > **Note**: This method is currently implemented as a 0-cost cast, but
-    /// > it is planned to alter its definition in the future to perform the
-    /// > length calculation whenever this method is called.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::ffi::CStr;
-    ///
-    /// let cstr = CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed");
-    /// assert_eq!(cstr.to_bytes_with_nul(), b"foo\0");
-    /// ```
-    #[inline]
-    #[must_use = "this returns the result of the operation, \
-                  without modifying the original"]
-    pub fn to_bytes_with_nul(&self) -> &[u8] {
-        unsafe { &*(&self.inner as *const [c_char] as *const [u8]) }
-    }
-
-    /// Yields a <code>&[str]</code> slice if the `CStr` contains valid UTF-8.
-    ///
-    /// If the contents of the `CStr` are valid UTF-8 data, this
-    /// function will return the corresponding <code>&[str]</code> slice. Otherwise,
-    /// it will return an error with details of where UTF-8 validation failed.
-    ///
-    /// [str]: prim@str "str"
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::ffi::CStr;
-    ///
-    /// let cstr = CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed");
-    /// assert_eq!(cstr.to_str(), Ok("foo"));
-    /// ```
-    pub fn to_str(&self) -> Result<&str, str::Utf8Error> {
-        // N.B., when `CStr` is changed to perform the length check in `.to_bytes()`
-        // instead of in `from_ptr()`, it may be worth considering if this should
-        // be rewritten to do the UTF-8 check inline with the length calculation
-        // instead of doing it afterwards.
-        str::from_utf8(self.to_bytes())
-    }
-
-    /// Converts a `CStr` into a <code>[Cow]<[str]></code>.
-    ///
-    /// If the contents of the `CStr` are valid UTF-8 data, this
-    /// function will return a <code>[Cow]::[Borrowed]\(&[str])</code>
-    /// with the corresponding <code>&[str]</code> slice. Otherwise, it will
-    /// replace any invalid UTF-8 sequences with
-    /// [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD] and return a
-    /// <code>[Cow]::[Owned]\(&[str])</code> with the result.
-    ///
-    /// [str]: prim@str "str"
-    /// [Borrowed]: Cow::Borrowed
-    /// [Owned]: Cow::Owned
-    /// [U+FFFD]: crate::char::REPLACEMENT_CHARACTER "std::char::REPLACEMENT_CHARACTER"
-    ///
-    /// # Examples
-    ///
-    /// Calling `to_string_lossy` on a `CStr` containing valid UTF-8:
-    ///
-    /// ```
-    /// use std::borrow::Cow;
-    /// use std::ffi::CStr;
-    ///
-    /// let cstr = CStr::from_bytes_with_nul(b"Hello World\0")
-    ///                  .expect("CStr::from_bytes_with_nul failed");
-    /// assert_eq!(cstr.to_string_lossy(), Cow::Borrowed("Hello World"));
-    /// ```
-    ///
-    /// Calling `to_string_lossy` on a `CStr` containing invalid UTF-8:
-    ///
-    /// ```
-    /// use std::borrow::Cow;
-    /// use std::ffi::CStr;
-    ///
-    /// let cstr = CStr::from_bytes_with_nul(b"Hello \xF0\x90\x80World\0")
-    ///                  .expect("CStr::from_bytes_with_nul failed");
-    /// assert_eq!(
-    ///     cstr.to_string_lossy(),
-    ///     Cow::Owned(String::from("Hello �World")) as Cow<'_, str>
-    /// );
-    /// ```
-    #[must_use = "this returns the result of the operation, \
-                  without modifying the original"]
-    pub fn to_string_lossy(&self) -> Cow<'_, str> {
-        String::from_utf8_lossy(self.to_bytes())
-    }
-
-    /// Converts a <code>[Box]<[CStr]></code> into a [`CString`] without copying or allocating.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::ffi::CString;
-    ///
-    /// let c_string = CString::new(b"foo".to_vec()).expect("CString::new failed");
-    /// let boxed = c_string.into_boxed_c_str();
-    /// assert_eq!(boxed.into_c_string(), CString::new("foo").expect("CString::new failed"));
-    /// ```
-    #[must_use = "`self` will be dropped if the result is not used"]
-    pub fn into_c_string(self: Box<CStr>) -> CString {
-        let raw = Box::into_raw(self) as *mut [u8];
-        CString {
-            inner: unsafe { Box::from_raw(raw) },
-        }
-    }
-}
-
-impl PartialEq for CStr {
-    fn eq(&self, other: &CStr) -> bool {
-        self.to_bytes().eq(other.to_bytes())
-    }
-}
-
-impl Eq for CStr {}
-
-impl PartialOrd for CStr {
-    fn partial_cmp(&self, other: &CStr) -> Option<Ordering> {
-        self.to_bytes().partial_cmp(other.to_bytes())
-    }
-}
-
-impl Ord for CStr {
-    fn cmp(&self, other: &CStr) -> Ordering {
-        self.to_bytes().cmp(other.to_bytes())
-    }
-}
-
-impl ToOwned for CStr {
-    type Owned = CString;
-
-    fn to_owned(&self) -> CString {
-        CString {
-            inner: self.to_bytes_with_nul().into(),
-        }
-    }
-
-    fn clone_into(&self, target: &mut CString) {
-        let mut b = Vec::from(mem::take(&mut target.inner));
-        self.to_bytes_with_nul().clone_into(&mut b);
-        target.inner = b.into_boxed_slice();
-    }
-}
-
-impl From<&CStr> for CString {
-    /// Copies the contents of the `&CStr` into a newly allocated `CString`.
-    fn from(s: &CStr) -> CString {
-        s.to_owned()
-    }
-}
-
-impl ops::Index<ops::RangeFull> for CString {
-    type Output = CStr;
-
-    #[inline]
-    fn index(&self, _index: ops::RangeFull) -> &CStr {
-        self
-    }
-}
-
-impl ops::Index<ops::RangeFrom<usize>> for CStr {
-    type Output = CStr;
-
-    fn index(&self, index: ops::RangeFrom<usize>) -> &CStr {
-        let bytes = self.to_bytes_with_nul();
-        // we need to manually check the starting index to account for the null
-        // byte, since otherwise we could get an empty string that doesn't end
-        // in a null.
-        if index.start < bytes.len() {
-            unsafe { CStr::_from_bytes_with_nul_unchecked(&bytes[index.start..]) }
-        } else {
-            panic!(
-                "index out of bounds: the len is {} but the index is {}",
-                bytes.len(),
-                index.start
-            );
-        }
-    }
-}
-
-impl AsRef<CStr> for CStr {
-    #[inline]
-    fn as_ref(&self) -> &CStr {
-        self
-    }
-}
-
-impl AsRef<CStr> for CString {
-    #[inline]
-    fn as_ref(&self) -> &CStr {
-        self
-    }
-}
+pub use alloc::ffi::{CString, FromVecWithNulError, IntoStringError, NulError};
+pub use core::ffi::{CStr, FromBytesWithNulError};
diff --git a/sgx_trts/src/lib.rs b/sgx_trts/src/lib.rs
index 7659bdc3..ac9606e4 100644
--- a/sgx_trts/src/lib.rs
+++ b/sgx_trts/src/lib.rs
@@ -67,7 +67,6 @@
 #![feature(allocator_api)]
 #![feature(specialization)]
 #![feature(vec_into_raw_parts)]
-#![feature(toowned_clone_into)]
 #![feature(rustc_attrs)]
 #![allow(incomplete_features)]
 #![allow(non_camel_case_types)]
diff --git a/sgx_tse/Cargo.toml b/sgx_tse/Cargo.toml
index 3191167e..d5c72dce 100644
--- a/sgx_tse/Cargo.toml
+++ b/sgx_tse/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "sgx_tse"
-version = "1.1.5"
+version = "1.1.6"
 authors = ["The Teaclave Authors"]
 repository = "https://github.com/apache/teaclave-sgx-sdk"
 license-file = "LICENSE"
diff --git a/sgx_tseal/Cargo.toml b/sgx_tseal/Cargo.toml
index 21e63482..f91fcc19 100644
--- a/sgx_tseal/Cargo.toml
+++ b/sgx_tseal/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "sgx_tseal"
-version = "1.1.5"
+version = "1.1.6"
 authors = ["The Teaclave Authors"]
 repository = "https://github.com/apache/teaclave-sgx-sdk"
 license-file = "LICENSE"
diff --git a/sgx_tstd/Cargo.toml b/sgx_tstd/Cargo.toml
index 97ec1b37..957a8d85 100644
--- a/sgx_tstd/Cargo.toml
+++ b/sgx_tstd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "sgx_tstd"
-version = "1.1.5"
+version = "1.1.6"
 authors = ["The Teaclave Authors"]
 repository = "https://github.com/apache/teaclave-sgx-sdk"
 license-file = "LICENSE"
diff --git a/sgx_tstd/src/alloc.rs b/sgx_tstd/src/alloc.rs
index 1e15ff32..240b2bab 100644
--- a/sgx_tstd/src/alloc.rs
+++ b/sgx_tstd/src/alloc.rs
@@ -59,8 +59,6 @@
 //! [`GlobalAlloc`] trait. This type can be provided by an external library:
 //!
 //! ```rust,ignore (demonstrates crates.io usage)
-//! extern crate jemallocator;
-//!
 //! use jemallocator::Jemalloc;
 //!
 //! #[global_allocator]
@@ -93,6 +91,20 @@ static HOOK: AtomicPtr<()> = AtomicPtr::new(ptr::null_mut());
 /// about the allocation that failed.
 ///
 /// The allocation error hook is a global resource.
+///
+/// # Examples
+///
+/// ```
+/// #![feature(alloc_error_hook)]
+///
+/// use std::alloc::{Layout, set_alloc_error_hook};
+///
+/// fn custom_alloc_error_hook(layout: Layout) {
+///    panic!("memory allocation of {} bytes failed", layout.size());
+/// }
+///
+/// set_alloc_error_hook(custom_alloc_error_hook);
+/// ```
 pub fn set_alloc_error_hook(hook: fn(Layout)) {
     HOOK.store(hook as *mut (), Ordering::SeqCst);
 }
@@ -108,7 +120,18 @@ pub fn take_alloc_error_hook() -> fn(Layout) {
 }
 
 fn default_alloc_error_hook(layout: Layout) {
-    rtprintpanic!("memory allocation of {} bytes failed\n", layout.size());
+    extern "Rust" {
+        // This symbol is emitted by rustc next to __rust_alloc_error_handler.
+        // Its value depends on the -Zoom={panic,abort} compiler option.
+        static __rust_alloc_error_handler_should_panic: u8;
+    }
+
+    #[allow(unused_unsafe)]
+    if unsafe { __rust_alloc_error_handler_should_panic != 0 } {
+        panic!("memory allocation of {} bytes failed\n", layout.size());
+    } else {
+        rtprintpanic!("memory allocation of {} bytes failed\n", layout.size());
+    }
 }
 
 #[doc(hidden)]
diff --git a/sgx_tstd/src/backtrace.rs b/sgx_tstd/src/backtrace.rs
index a491f5d8..6824ced5 100644
--- a/sgx_tstd/src/backtrace.rs
+++ b/sgx_tstd/src/backtrace.rs
@@ -26,19 +26,13 @@
 //! implementing `std::error::Error`) to get a causal chain of where an error
 //! was generated.
 //!
-//! > **Note**: this module is unstable and is designed in [RFC 2504], and you
-//! > can learn more about its status in the [tracking issue].
-//!
-//! [RFC 2504]: https://github.com/rust-lang/rfcs/blob/master/text/2504-fix-error.md
-//! [tracking issue]: https://github.com/rust-lang/rust/issues/53487
-//!
 //! ## Accuracy
 //!
 //! Backtraces are attempted to be as accurate as possible, but no guarantees
 //! are provided about the exact accuracy of a backtrace. Instruction pointers,
 //! symbol names, filenames, line numbers, etc, may all be incorrect when
-//! reported. Accuracy is attempted on a best-effort basis, however, and bugs
-//! are always welcome to indicate areas of improvement!
+//! reported. Accuracy is attempted on a best-effort basis, however, any bug
+//! reports are always welcome to indicate areas of improvement!
 //!
 //! For most platforms a backtrace with a filename/line number requires that
 //! programs be compiled with debug information. Without debug information
@@ -300,7 +294,7 @@ impl Backtrace {
     // `ip`
     fn create(ip: usize) -> Backtrace {
         // SAFETY: We don't attempt to lock this reentrantly.
-        let _lock = unsafe { lock() };
+        let _lock = lock();
         let mut frames = Vec::new();
         let mut actual_start = None;
         unsafe {
@@ -441,8 +435,7 @@ impl Capture {
         // Use the global backtrace lock to synchronize this as it's a
         // requirement of the `backtrace` crate, and then actually resolve
         // everything.
-        // SAFETY: We don't attempt to lock this reentrantly.
-        let _lock = unsafe { lock() };
+        let _lock = lock();
         for frame in self.frames.iter_mut() {
             let symbols = &mut frame.symbols;
             let RawFrame::Actual(frame) = &frame.frame;
diff --git a/sgx_tstd/src/collections/hash/map.rs b/sgx_tstd/src/collections/hash/map.rs
index 2c5012a4..0626409f 100644
--- a/sgx_tstd/src/collections/hash/map.rs
+++ b/sgx_tstd/src/collections/hash/map.rs
@@ -23,10 +23,11 @@ use crate::borrow::Borrow;
 use crate::cell::Cell;
 use crate::collections::TryReserveError;
 use crate::collections::TryReserveErrorKind;
+use crate::error::Error;
 use crate::fmt::{self, Debug};
 #[allow(deprecated)]
 use crate::hash::{BuildHasher, Hash, Hasher, SipHasher13};
-use crate::iter::{FromIterator, FusedIterator};
+use crate::iter::FusedIterator;
 use crate::ops::Index;
 use crate::sys;
 
@@ -68,7 +69,8 @@ use crate::sys;
 /// the [`Eq`] trait, changes while it is in the map. This is normally only
 /// possible through [`Cell`], [`RefCell`], global state, I/O, or unsafe code.
 /// The behavior resulting from such a logic error is not specified, but will
-/// not result in undefined behavior. This could include panics, incorrect results,
+/// be encapsulated to the `HashMap` that observed the logic error and not
+/// result in undefined behavior. This could include panics, incorrect results,
 /// aborts, memory leaks, and non-termination.
 ///
 /// The hash table implementation is a Rust port of Google's [SwissTable].
@@ -123,8 +125,8 @@ use crate::sys;
 /// let to_find = ["Pride and Prejudice", "Alice's Adventure in Wonderland"];
 /// for &book in &to_find {
 ///     match book_reviews.get(book) {
-///         Some(review) => println!("{}: {}", book, review),
-///         None => println!("{} is unreviewed.", book)
+///         Some(review) => println!("{book}: {review}"),
+///         None => println!("{book} is unreviewed.")
 ///     }
 /// }
 ///
@@ -133,7 +135,7 @@ use crate::sys;
 ///
 /// // Iterate over everything.
 /// for (book, review) in &book_reviews {
-///     println!("{}: \"{}\"", book, review);
+///     println!("{book}: \"{review}\"");
 /// }
 /// ```
 ///
@@ -150,7 +152,7 @@ use crate::sys;
 /// ]);
 /// ```
 ///
-/// `HashMap` implements an [`Entry API`](#method.entry), which allows
+/// `HashMap` implements an [`Entry` API](#method.entry), which allows
 /// for complex methods of getting, setting, updating and removing keys and
 /// their values:
 ///
@@ -177,6 +179,9 @@ use crate::sys;
 /// // update a key, guarding against the key possibly not being set
 /// let stat = player_stats.entry("attack").or_insert(100);
 /// *stat += random_stat_buff();
+///
+/// // modify an entry before an insert with in-place mutation
+/// player_stats.entry("mana").and_modify(|mana| *mana += 200).or_insert(100);
 /// ```
 ///
 /// The easiest way to use `HashMap` with a custom key type is to derive [`Eq`] and [`Hash`].
@@ -213,7 +218,7 @@ use crate::sys;
 ///
 /// // Use derived implementation to print the status of the vikings.
 /// for (viking, health) in &vikings {
-///     println!("{:?} has {} hp", viking, health);
+///     println!("{viking:?} has {health} hp");
 /// }
 /// ```
 
@@ -241,10 +246,11 @@ impl<K, V> HashMap<K, V, RandomState> {
         Default::default()
     }
 
-    /// Creates an empty `HashMap` with the specified capacity.
+    /// Creates an empty `HashMap` with at least the specified capacity.
     ///
     /// The hash map will be able to hold at least `capacity` elements without
-    /// reallocating. If `capacity` is 0, the hash map will not allocate.
+    /// reallocating. This method is allowed to allocate for more elements than
+    /// `capacity`. If `capacity` is 0, the hash set will not allocate.
     ///
     /// # Examples
     ///
@@ -284,22 +290,23 @@ impl<K, V, S> HashMap<K, V, S> {
     /// map.insert(1, 2);
     /// ```
     #[inline]
-    pub fn with_hasher(hash_builder: S) -> HashMap<K, V, S> {
+    pub const fn with_hasher(hash_builder: S) -> HashMap<K, V, S> {
         HashMap { base: base::HashMap::with_hasher(hash_builder) }
     }
 
-    /// Creates an empty `HashMap` with the specified capacity, using `hash_builder`
-    /// to hash the keys.
+    /// Creates an empty `HashMap` with at least the specified capacity, using
+    /// `hasher` to hash the keys.
     ///
     /// The hash map will be able to hold at least `capacity` elements without
-    /// reallocating. If `capacity` is 0, the hash map will not allocate.
+    /// reallocating. This method is allowed to allocate for more elements than
+    /// `capacity`. If `capacity` is 0, the hash map will not allocate.
     ///
-    /// Warning: `hash_builder` is normally randomly generated, and
+    /// Warning: `hasher` is normally randomly generated, and
     /// is designed to allow HashMaps to be resistant to attacks that
     /// cause many collisions and very poor performance. Setting it
     /// manually using this function can expose a DoS attack vector.
     ///
-    /// The `hash_builder` passed should implement the [`BuildHasher`] trait for
+    /// The `hasher` passed should implement the [`BuildHasher`] trait for
     /// the HashMap to be useful, see its documentation for details.
     ///
     /// # Examples
@@ -313,8 +320,8 @@ impl<K, V, S> HashMap<K, V, S> {
     /// map.insert(1, 2);
     /// ```
     #[inline]
-    pub fn with_capacity_and_hasher(capacity: usize, hash_builder: S) -> HashMap<K, V, S> {
-        HashMap { base: base::HashMap::with_capacity_and_hasher(capacity, hash_builder) }
+    pub fn with_capacity_and_hasher(capacity: usize, hasher: S) -> HashMap<K, V, S> {
+        HashMap { base: base::HashMap::with_capacity_and_hasher(capacity, hasher) }
     }
 
     /// Returns the number of elements the map can hold without reallocating.
@@ -349,9 +356,14 @@ impl<K, V, S> HashMap<K, V, S> {
     /// ]);
     ///
     /// for key in map.keys() {
-    ///     println!("{}", key);
+    ///     println!("{key}");
     /// }
     /// ```
+    ///
+    /// # Performance
+    ///
+    /// In the current implementation, iterating over keys takes O(capacity) time
+    /// instead of O(len) because it internally visits empty buckets too.
     pub fn keys(&self) -> Keys<'_, K, V> {
         Keys { inner: self.iter() }
     }
@@ -377,8 +389,13 @@ impl<K, V, S> HashMap<K, V, S> {
     /// vec.sort_unstable();
     /// assert_eq!(vec, ["a", "b", "c"]);
     /// ```
+    ///
+    /// # Performance
+    ///
+    /// In the current implementation, iterating over keys takes O(capacity) time
+    /// instead of O(len) because it internally visits empty buckets too.
     #[inline]
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
+    #[rustc_lint_query_instability]
     pub fn into_keys(self) -> IntoKeys<K, V> {
         IntoKeys { inner: self.into_iter() }
     }
@@ -398,9 +415,14 @@ impl<K, V, S> HashMap<K, V, S> {
     /// ]);
     ///
     /// for val in map.values() {
-    ///     println!("{}", val);
+    ///     println!("{val}");
     /// }
     /// ```
+    ///
+    /// # Performance
+    ///
+    /// In the current implementation, iterating over values takes O(capacity) time
+    /// instead of O(len) because it internally visits empty buckets too.
     pub fn values(&self) -> Values<'_, K, V> {
         Values { inner: self.iter() }
     }
@@ -424,9 +446,14 @@ impl<K, V, S> HashMap<K, V, S> {
     /// }
     ///
     /// for val in map.values() {
-    ///     println!("{}", val);
+    ///     println!("{val}");
     /// }
     /// ```
+    ///
+    /// # Performance
+    ///
+    /// In the current implementation, iterating over values takes O(capacity) time
+    /// instead of O(len) because it internally visits empty buckets too.
     pub fn values_mut(&mut self) -> ValuesMut<'_, K, V> {
         ValuesMut { inner: self.iter_mut() }
     }
@@ -452,8 +479,13 @@ impl<K, V, S> HashMap<K, V, S> {
     /// vec.sort_unstable();
     /// assert_eq!(vec, [1, 2, 3]);
     /// ```
+    ///
+    /// # Performance
+    ///
+    /// In the current implementation, iterating over values takes O(capacity) time
+    /// instead of O(len) because it internally visits empty buckets too.
     #[inline]
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
+    #[rustc_lint_query_instability]
     pub fn into_values(self) -> IntoValues<K, V> {
         IntoValues { inner: self.into_iter() }
     }
@@ -473,10 +505,15 @@ impl<K, V, S> HashMap<K, V, S> {
     /// ]);
     ///
     /// for (key, val) in map.iter() {
-    ///     println!("key: {} val: {}", key, val);
+    ///     println!("key: {key} val: {val}");
     /// }
     /// ```
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
+    ///
+    /// # Performance
+    ///
+    /// In the current implementation, iterating over map takes O(capacity) time
+    /// instead of O(len) because it internally visits empty buckets too.
+    #[rustc_lint_query_instability]
     pub fn iter(&self) -> Iter<'_, K, V> {
         Iter { base: self.base.iter() }
     }
@@ -502,10 +539,15 @@ impl<K, V, S> HashMap<K, V, S> {
     /// }
     ///
     /// for (key, val) in &map {
-    ///     println!("key: {} val: {}", key, val);
+    ///     println!("key: {key} val: {val}");
     /// }
     /// ```
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
+    ///
+    /// # Performance
+    ///
+    /// In the current implementation, iterating over map takes O(capacity) time
+    /// instead of O(len) because it internally visits empty buckets too.
+    #[rustc_lint_query_instability]
     pub fn iter_mut(&mut self) -> IterMut<'_, K, V> {
         IterMut { base: self.base.iter_mut() }
     }
@@ -548,7 +590,7 @@ impl<K, V, S> HashMap<K, V, S> {
     ///
     /// If the returned iterator is dropped before being fully consumed, it
     /// drops the remaining key-value pairs. The returned iterator keeps a
-    /// mutable borrow on the vector to optimize its implementation.
+    /// mutable borrow on the map to optimize its implementation.
     ///
     /// # Examples
     ///
@@ -567,7 +609,7 @@ impl<K, V, S> HashMap<K, V, S> {
     /// assert!(a.is_empty());
     /// ```
     #[inline]
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
+    #[rustc_lint_query_instability]
     pub fn drain(&mut self) -> Drain<'_, K, V> {
         Drain { base: self.base.drain() }
     }
@@ -608,7 +650,7 @@ impl<K, V, S> HashMap<K, V, S> {
     /// assert_eq!(odds, vec![1, 3, 5, 7]);
     /// ```
     #[inline]
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
+    #[rustc_lint_query_instability]
     pub fn drain_filter<F>(&mut self, pred: F) -> DrainFilter<'_, K, V, F>
     where
         F: FnMut(&K, &mut V) -> bool,
@@ -618,7 +660,7 @@ impl<K, V, S> HashMap<K, V, S> {
 
     /// Retains only the elements specified by the predicate.
     ///
-    /// In other words, remove all pairs `(k, v)` such that `f(&k, &mut v)` returns `false`.
+    /// In other words, remove all pairs `(k, v)` for which `f(&k, &mut v)` returns `false`.
     /// The elements are visited in unsorted (and unspecified) order.
     ///
     /// # Examples
@@ -630,8 +672,13 @@ impl<K, V, S> HashMap<K, V, S> {
     /// map.retain(|&k, _| k % 2 == 0);
     /// assert_eq!(map.len(), 4);
     /// ```
+    ///
+    /// # Performance
+    ///
+    /// In the current implementation, this operation takes O(capacity) time
+    /// instead of O(len) because it internally visits empty buckets too.
     #[inline]
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
+    #[rustc_lint_query_instability]
     pub fn retain<F>(&mut self, f: F)
     where
         F: FnMut(&K, &mut V) -> bool,
@@ -681,8 +728,10 @@ where
     S: BuildHasher,
 {
     /// Reserves capacity for at least `additional` more elements to be inserted
-    /// in the `HashMap`. The collection may reserve more space to avoid
-    /// frequent reallocations.
+    /// in the `HashMap`. The collection may reserve more space to speculatively
+    /// avoid frequent reallocations. After calling `reserve`,
+    /// capacity will be greater than or equal to `self.len() + additional`.
+    /// Does nothing if capacity is already sufficient.
     ///
     /// # Panics
     ///
@@ -701,8 +750,11 @@ where
     }
 
     /// Tries to reserve capacity for at least `additional` more elements to be inserted
-    /// in the given `HashMap<K, V>`. The collection may reserve more space to avoid
-    /// frequent reallocations.
+    /// in the `HashMap`. The collection may reserve more space to speculatively
+    /// avoid frequent reallocations. After calling `reserve`,
+    /// capacity will be greater than or equal to `self.len() + additional` if
+    /// it returns `Ok(())`.
+    /// Does nothing if capacity is already sufficient.
     ///
     /// # Errors
     ///
@@ -715,7 +767,7 @@ where
     /// use std::collections::HashMap;
     ///
     /// let mut map: HashMap<&str, isize> = HashMap::new();
-    /// map.try_reserve(10).expect("why is the test harness OOMing on 10 bytes?");
+    /// map.try_reserve(10).expect("why is the test harness OOMing on a handful of bytes?");
     /// ```
     #[inline]
     pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
@@ -778,8 +830,7 @@ where
     /// let mut letters = HashMap::new();
     ///
     /// for ch in "a short treatise on fungi".chars() {
-    ///     let counter = letters.entry(ch).or_insert(0);
-    ///     *counter += 1;
+    ///     letters.entry(ch).and_modify(|counter| *counter += 1).or_insert(1);
     /// }
     ///
     /// assert_eq!(letters[&'s'], 2);
@@ -842,6 +893,117 @@ where
         self.base.get_key_value(k)
     }
 
+    /// Attempts to get mutable references to `N` values in the map at once.
+    ///
+    /// Returns an array of length `N` with the results of each query. For soundness, at most one
+    /// mutable reference will be returned to any value. `None` will be returned if any of the
+    /// keys are duplicates or missing.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(map_many_mut)]
+    /// use std::collections::HashMap;
+    ///
+    /// let mut libraries = HashMap::new();
+    /// libraries.insert("Bodleian Library".to_string(), 1602);
+    /// libraries.insert("Athenæum".to_string(), 1807);
+    /// libraries.insert("Herzogin-Anna-Amalia-Bibliothek".to_string(), 1691);
+    /// libraries.insert("Library of Congress".to_string(), 1800);
+    ///
+    /// let got = libraries.get_many_mut([
+    ///     "Athenæum",
+    ///     "Library of Congress",
+    /// ]);
+    /// assert_eq!(
+    ///     got,
+    ///     Some([
+    ///         &mut 1807,
+    ///         &mut 1800,
+    ///     ]),
+    /// );
+    ///
+    /// // Missing keys result in None
+    /// let got = libraries.get_many_mut([
+    ///     "Athenæum",
+    ///     "New York Public Library",
+    /// ]);
+    /// assert_eq!(got, None);
+    ///
+    /// // Duplicate keys result in None
+    /// let got = libraries.get_many_mut([
+    ///     "Athenæum",
+    ///     "Athenæum",
+    /// ]);
+    /// assert_eq!(got, None);
+    /// ```
+    #[inline]
+    pub fn get_many_mut<Q: ?Sized, const N: usize>(&mut self, ks: [&Q; N]) -> Option<[&'_ mut V; N]>
+    where
+        K: Borrow<Q>,
+        Q: Hash + Eq,
+    {
+        self.base.get_many_mut(ks)
+    }
+
+    /// Attempts to get mutable references to `N` values in the map at once, without validating that
+    /// the values are unique.
+    ///
+    /// Returns an array of length `N` with the results of each query. `None` will be returned if
+    /// any of the keys are missing.
+    ///
+    /// For a safe alternative see [`get_many_mut`](Self::get_many_mut).
+    ///
+    /// # Safety
+    ///
+    /// Calling this method with overlapping keys is *[undefined behavior]* even if the resulting
+    /// references are not used.
+    ///
+    /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(map_many_mut)]
+    /// use std::collections::HashMap;
+    ///
+    /// let mut libraries = HashMap::new();
+    /// libraries.insert("Bodleian Library".to_string(), 1602);
+    /// libraries.insert("Athenæum".to_string(), 1807);
+    /// libraries.insert("Herzogin-Anna-Amalia-Bibliothek".to_string(), 1691);
+    /// libraries.insert("Library of Congress".to_string(), 1800);
+    ///
+    /// let got = libraries.get_many_mut([
+    ///     "Athenæum",
+    ///     "Library of Congress",
+    /// ]);
+    /// assert_eq!(
+    ///     got,
+    ///     Some([
+    ///         &mut 1807,
+    ///         &mut 1800,
+    ///     ]),
+    /// );
+    ///
+    /// // Missing keys result in None
+    /// let got = libraries.get_many_mut([
+    ///     "Athenæum",
+    ///     "New York Public Library",
+    /// ]);
+    /// assert_eq!(got, None);
+    /// ```
+    #[inline]
+    pub unsafe fn get_many_unchecked_mut<Q: ?Sized, const N: usize>(
+        &mut self,
+        ks: [&Q; N],
+    ) -> Option<[&'_ mut V; N]>
+    where
+        K: Borrow<Q>,
+        Q: Hash + Eq,
+    {
+        self.base.get_many_unchecked_mut(ks)
+    }
+
     /// Returns `true` if the map contains a value for the specified key.
     ///
     /// The key may be any borrowed form of the map's key type, but
@@ -1907,6 +2069,13 @@ impl<'a, K: Debug, V: Debug> fmt::Display for OccupiedError<'a, K, V> {
     }
 }
 
+impl<'a, K: fmt::Debug, V: fmt::Debug> Error for OccupiedError<'a, K, V> {
+    #[allow(deprecated)]
+    fn description(&self) -> &str {
+        "key already exists"
+    }
+}
+
 impl<'a, K, V, S> IntoIterator for &'a HashMap<K, V, S> {
     type Item = (&'a K, &'a V);
     type IntoIter = Iter<'a, K, V>;
@@ -1950,7 +2119,7 @@ impl<K, V, S> IntoIterator for HashMap<K, V, S> {
     /// let vec: Vec<(&str, i32)> = map.into_iter().collect();
     /// ```
     #[inline]
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
+    #[rustc_lint_query_instability]
     fn into_iter(self) -> IntoIter<K, V> {
         IntoIter { base: self.base.into_iter() }
     }
@@ -2689,6 +2858,7 @@ impl<'a, K: 'a, V: 'a> VacantEntry<'a, K, V> {
     /// # Examples
     ///
     /// ```
+    /// #![feature(entry_insert)]
     /// use std::collections::HashMap;
     /// use std::collections::hash_map::Entry;
     ///
@@ -2846,6 +3016,7 @@ impl DefaultHasher {
     /// This hasher is not guaranteed to be the same as all other
     /// `DefaultHasher` instances, but is the same as all other `DefaultHasher`
     /// instances created through `new` or `default`.
+    #[inline]
     #[allow(deprecated)]
     #[must_use]
     pub fn new() -> DefaultHasher {
@@ -2858,17 +3029,26 @@ impl Default for DefaultHasher {
     /// See its documentation for more.
     ///
     /// [`new`]: DefaultHasher::new
+    #[inline]
     fn default() -> DefaultHasher {
         DefaultHasher::new()
     }
 }
 
 impl Hasher for DefaultHasher {
+    // The underlying `SipHasher13` doesn't override the other
+    // `write_*` methods, so it's ok not to forward them here.
+
     #[inline]
     fn write(&mut self, msg: &[u8]) {
         self.0.write(msg)
     }
 
+    #[inline]
+    fn write_str(&mut self, s: &str) {
+        self.0.write_str(s);
+    }
+
     #[inline]
     fn finish(&self) -> u64 {
         self.0.finish()
diff --git a/sgx_tstd/src/collections/hash/set.rs b/sgx_tstd/src/collections/hash/set.rs
index b6b62b62..4e0baedf 100644
--- a/sgx_tstd/src/collections/hash/set.rs
+++ b/sgx_tstd/src/collections/hash/set.rs
@@ -21,7 +21,7 @@ use crate::borrow::Borrow;
 use crate::collections::TryReserveError;
 use crate::fmt;
 use crate::hash::{BuildHasher, Hash};
-use crate::iter::{Chain, FromIterator, FusedIterator};
+use crate::iter::{Chain, FusedIterator};
 use crate::ops::{BitAnd, BitOr, BitXor, Sub};
 
 use super::map::{map_try_reserve_error, RandomState};
@@ -47,13 +47,14 @@ use super::map::{map_try_reserve_error, RandomState};
 /// In other words, if two keys are equal, their hashes must be equal.
 ///
 ///
-/// It is a logic error for an item to be modified in such a way that the
-/// item's hash, as determined by the [`Hash`] trait, or its equality, as
-/// determined by the [`Eq`] trait, changes while it is in the set. This is
-/// normally only possible through [`Cell`], [`RefCell`], global state, I/O, or
-/// unsafe code. The behavior resulting from such a logic error is not
-/// specified (it could include panics, incorrect results, aborts, memory
-/// leaks, or non-termination) but will not be undefined behavior.
+/// It is a logic error for a key to be modified in such a way that the key's
+/// hash, as determined by the [`Hash`] trait, or its equality, as determined by
+/// the [`Eq`] trait, changes while it is in the map. This is normally only
+/// possible through [`Cell`], [`RefCell`], global state, I/O, or unsafe code.
+/// The behavior resulting from such a logic error is not specified, but will
+/// be encapsulated to the `HashSet` that observed the logic error and not
+/// result in undefined behavior. This could include panics, incorrect results,
+/// aborts, memory leaks, and non-termination.
 ///
 /// # Examples
 ///
@@ -80,7 +81,7 @@ use super::map::{map_try_reserve_error, RandomState};
 ///
 /// // Iterate over everything.
 /// for book in &books {
-///     println!("{}", book);
+///     println!("{book}");
 /// }
 /// ```
 ///
@@ -105,7 +106,7 @@ use super::map::{map_try_reserve_error, RandomState};
 ///
 /// // Use derived implementation to print the vikings.
 /// for x in &vikings {
-///     println!("{:?}", x);
+///     println!("{x:?}");
 /// }
 /// ```
 ///
@@ -144,10 +145,11 @@ impl<T> HashSet<T, RandomState> {
         Default::default()
     }
 
-    /// Creates an empty `HashSet` with the specified capacity.
+    /// Creates an empty `HashSet` with at least the specified capacity.
     ///
     /// The hash set will be able to hold at least `capacity` elements without
-    /// reallocating. If `capacity` is 0, the hash set will not allocate.
+    /// reallocating. This method is allowed to allocate for more elements than
+    /// `capacity`. If `capacity` is 0, the hash set will not allocate.
     ///
     /// # Examples
     ///
@@ -191,11 +193,16 @@ impl<T, S> HashSet<T, S> {
     ///
     /// // Will print in an arbitrary order.
     /// for x in set.iter() {
-    ///     println!("{}", x);
+    ///     println!("{x}");
     /// }
     /// ```
+    ///
+    /// # Performance
+    ///
+    /// In the current implementation, iterating over set takes O(capacity) time
+    /// instead of O(len) because it internally visits empty buckets too.
     #[inline]
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
+    #[rustc_lint_query_instability]
     pub fn iter(&self) -> Iter<'_, T> {
         Iter { base: self.base.iter() }
     }
@@ -239,7 +246,7 @@ impl<T, S> HashSet<T, S> {
     ///
     /// If the returned iterator is dropped before being fully consumed, it
     /// drops the remaining elements. The returned iterator keeps a mutable
-    /// borrow on the vector to optimize its implementation.
+    /// borrow on the set to optimize its implementation.
     ///
     /// # Examples
     ///
@@ -251,13 +258,13 @@ impl<T, S> HashSet<T, S> {
     ///
     /// // print 1, 2, 3 in an arbitrary order
     /// for i in set.drain() {
-    ///     println!("{}", i);
+    ///     println!("{i}");
     /// }
     ///
     /// assert!(set.is_empty());
     /// ```
     #[inline]
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
+    #[rustc_lint_query_instability]
     pub fn drain(&mut self) -> Drain<'_, T> {
         Drain { base: self.base.drain() }
     }
@@ -295,7 +302,7 @@ impl<T, S> HashSet<T, S> {
     /// assert_eq!(odds, vec![1, 3, 5, 7]);
     /// ```
     #[inline]
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
+    #[rustc_lint_query_instability]
     pub fn drain_filter<F>(&mut self, pred: F) -> DrainFilter<'_, T, F>
     where
         F: FnMut(&T) -> bool,
@@ -305,7 +312,7 @@ impl<T, S> HashSet<T, S> {
 
     /// Retains only the elements specified by the predicate.
     ///
-    /// In other words, remove all elements `e` such that `f(&e)` returns `false`.
+    /// In other words, remove all elements `e` for which `f(&e)` returns `false`.
     /// The elements are visited in unsorted (and unspecified) order.
     ///
     /// # Examples
@@ -317,7 +324,12 @@ impl<T, S> HashSet<T, S> {
     /// set.retain(|&k| k % 2 == 0);
     /// assert_eq!(set.len(), 3);
     /// ```
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
+    ///
+    /// # Performance
+    ///
+    /// In the current implementation, this operation takes O(capacity) time
+    /// instead of O(len) because it internally visits empty buckets too.
+    #[rustc_lint_query_instability]
     pub fn retain<F>(&mut self, f: F)
     where
         F: FnMut(&T) -> bool,
@@ -366,15 +378,16 @@ impl<T, S> HashSet<T, S> {
     /// set.insert(2);
     /// ```
     #[inline]
-    pub fn with_hasher(hasher: S) -> HashSet<T, S> {
+    pub const fn with_hasher(hasher: S) -> HashSet<T, S> {
         HashSet { base: base::HashSet::with_hasher(hasher) }
     }
 
-    /// Creates an empty `HashSet` with the specified capacity, using
+    /// Creates an empty `HashSet` with at least the specified capacity, using
     /// `hasher` to hash the keys.
     ///
     /// The hash set will be able to hold at least `capacity` elements without
-    /// reallocating. If `capacity` is 0, the hash set will not allocate.
+    /// reallocating. This method is allowed to allocate for more elements than
+    /// `capacity`. If `capacity` is 0, the hash set will not allocate.
     ///
     /// Warning: `hasher` is normally randomly generated, and
     /// is designed to allow `HashSet`s to be resistant to attacks that
@@ -423,8 +436,10 @@ where
     S: BuildHasher,
 {
     /// Reserves capacity for at least `additional` more elements to be inserted
-    /// in the `HashSet`. The collection may reserve more space to avoid
-    /// frequent reallocations.
+    /// in the `HashSet`. The collection may reserve more space to speculatively
+    /// avoid frequent reallocations. After calling `reserve`,
+    /// capacity will be greater than or equal to `self.len() + additional`.
+    /// Does nothing if capacity is already sufficient.
     ///
     /// # Panics
     ///
@@ -444,8 +459,11 @@ where
     }
 
     /// Tries to reserve capacity for at least `additional` more elements to be inserted
-    /// in the given `HashSet<K, V>`. The collection may reserve more space to avoid
-    /// frequent reallocations.
+    /// in the `HashSet`. The collection may reserve more space to speculatively
+    /// avoid frequent reallocations. After calling `reserve`,
+    /// capacity will be greater than or equal to `self.len() + additional` if
+    /// it returns `Ok(())`.
+    /// Does nothing if capacity is already sufficient.
     ///
     /// # Errors
     ///
@@ -457,7 +475,7 @@ where
     /// ```
     /// use std::collections::HashSet;
     /// let mut set: HashSet<i32> = HashSet::new();
-    /// set.try_reserve(10).expect("why is the test harness OOMing on 10 bytes?");
+    /// set.try_reserve(10).expect("why is the test harness OOMing on a handful of bytes?");
     /// ```
     #[inline]
     pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
@@ -521,7 +539,7 @@ where
     ///
     /// // Can be seen as `a - b`.
     /// for x in a.difference(&b) {
-    ///     println!("{}", x); // Print 1
+    ///     println!("{x}"); // Print 1
     /// }
     ///
     /// let diff: HashSet<_> = a.difference(&b).collect();
@@ -533,7 +551,7 @@ where
     /// assert_eq!(diff, [4].iter().collect());
     /// ```
     #[inline]
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
+    #[rustc_lint_query_instability]
     pub fn difference<'a>(&'a self, other: &'a HashSet<T, S>) -> Difference<'a, T, S> {
         Difference { iter: self.iter(), other }
     }
@@ -550,7 +568,7 @@ where
     ///
     /// // Print 1, 4 in arbitrary order.
     /// for x in a.symmetric_difference(&b) {
-    ///     println!("{}", x);
+    ///     println!("{x}");
     /// }
     ///
     /// let diff1: HashSet<_> = a.symmetric_difference(&b).collect();
@@ -560,7 +578,7 @@ where
     /// assert_eq!(diff1, [1, 4].iter().collect());
     /// ```
     #[inline]
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
+    #[rustc_lint_query_instability]
     pub fn symmetric_difference<'a>(
         &'a self,
         other: &'a HashSet<T, S>,
@@ -571,6 +589,12 @@ where
     /// Visits the values representing the intersection,
     /// i.e., the values that are both in `self` and `other`.
     ///
+    /// When an equal element is present in `self` and `other`
+    /// then the resulting `Intersection` may yield references to
+    /// one or the other. This can be relevant if `T` contains fields which
+    /// are not compared by its `Eq` implementation, and may hold different
+    /// value between the two equal copies of `T` in the two sets.
+    ///
     /// # Examples
     ///
     /// ```
@@ -580,14 +604,14 @@ where
     ///
     /// // Print 2, 3 in arbitrary order.
     /// for x in a.intersection(&b) {
-    ///     println!("{}", x);
+    ///     println!("{x}");
     /// }
     ///
     /// let intersection: HashSet<_> = a.intersection(&b).collect();
     /// assert_eq!(intersection, [2, 3].iter().collect());
     /// ```
     #[inline]
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
+    #[rustc_lint_query_instability]
     pub fn intersection<'a>(&'a self, other: &'a HashSet<T, S>) -> Intersection<'a, T, S> {
         if self.len() <= other.len() {
             Intersection { iter: self.iter(), other }
@@ -608,14 +632,14 @@ where
     ///
     /// // Print 1, 2, 3, 4 in arbitrary order.
     /// for x in a.union(&b) {
-    ///     println!("{}", x);
+    ///     println!("{x}");
     /// }
     ///
     /// let union: HashSet<_> = a.union(&b).collect();
     /// assert_eq!(union, [1, 2, 3, 4].iter().collect());
     /// ```
     #[inline]
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
+    #[rustc_lint_query_instability]
     pub fn union<'a>(&'a self, other: &'a HashSet<T, S>) -> Union<'a, T, S> {
         if self.len() >= other.len() {
             Union { iter: self.iter().chain(other.difference(self)) }
@@ -831,9 +855,10 @@ where
 
     /// Adds a value to the set.
     ///
-    /// If the set did not have this value present, `true` is returned.
+    /// Returns whether the value was newly inserted. That is:
     ///
-    /// If the set did have this value present, `false` is returned.
+    /// - If the set did not previously contain this value, `true` is returned.
+    /// - If the set already contained this value, `false` is returned.
     ///
     /// # Examples
     ///
@@ -1381,7 +1406,7 @@ impl<'a, T, S> IntoIterator for &'a HashSet<T, S> {
     type IntoIter = Iter<'a, T>;
 
     #[inline]
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
+    #[rustc_lint_query_instability]
     fn into_iter(self) -> Iter<'a, T> {
         self.iter()
     }
@@ -1408,11 +1433,11 @@ impl<T, S> IntoIterator for HashSet<T, S> {
     ///
     /// // Will print in an arbitrary order.
     /// for x in &v {
-    ///     println!("{}", x);
+    ///     println!("{x}");
     /// }
     /// ```
     #[inline]
-    #[cfg_attr(not(bootstrap), rustc_lint_query_instability)]
+    #[rustc_lint_query_instability]
     fn into_iter(self) -> IntoIter<T> {
         IntoIter { base: self.base.into_iter() }
     }
diff --git a/sgx_tstd/src/collections/mod.rs b/sgx_tstd/src/collections/mod.rs
index 5b2dcbd1..4b8c5a14 100644
--- a/sgx_tstd/src/collections/mod.rs
+++ b/sgx_tstd/src/collections/mod.rs
@@ -216,7 +216,7 @@
 //! ```
 //! let vec = vec![1, 2, 3, 4];
 //! for x in vec.iter() {
-//!    println!("vec contained {}", x);
+//!    println!("vec contained {x:?}");
 //! }
 //! ```
 //!
@@ -263,7 +263,7 @@
 //! ```
 //! let vec = vec![1, 2, 3, 4];
 //! for x in vec.iter().rev() {
-//!    println!("vec contained {}", x);
+//!    println!("vec contained {x:?}");
 //! }
 //! ```
 //!
@@ -323,7 +323,7 @@
 //!
 //! println!("Number of occurrences of each character");
 //! for (char, count) in &count {
-//!     println!("{}: {}", char, count);
+//!     println!("{char}: {count}");
 //! }
 //! ```
 //!
@@ -356,7 +356,7 @@
 //!     // Check if they're sober enough to have another beer.
 //!     if person.blood_alcohol > 0.3 {
 //!         // Too drunk... for now.
-//!         println!("Sorry {}, I have to cut you off", id);
+//!         println!("Sorry {id}, I have to cut you off");
 //!     } else {
 //!         // Have another!
 //!         person.blood_alcohol += 0.1;
@@ -415,6 +415,7 @@
 //!
 //! [IntoIterator]: crate::iter::IntoIterator "iter::IntoIterator"
 
+#[doc(hidden)]
 pub use crate::ops::Bound;
 pub use alloc_crate::collections::{binary_heap, btree_map, btree_set};
 pub use alloc_crate::collections::{linked_list, vec_deque};
diff --git a/sgx_tstd/src/enclave.rs b/sgx_tstd/src/enclave.rs
index 1f26a95e..4b1efe83 100644
--- a/sgx_tstd/src/enclave.rs
+++ b/sgx_tstd/src/enclave.rs
@@ -103,7 +103,7 @@ pub fn get_enclave_id() -> sgx_enclave_id_t {
 /// set_enclave_id is to set enclave ID.
 ///
 pub fn set_enclave_id(eid: sgx_enclave_id_t) {
-    ENCLAVE_ID.store(eid as u64, Ordering::SeqCst);
+    ENCLAVE_ID.store(eid, Ordering::SeqCst);
 }
 
 ///
diff --git a/sgx_tstd/src/env.rs b/sgx_tstd/src/env.rs
index cae3405c..fda2b4ac 100644
--- a/sgx_tstd/src/env.rs
+++ b/sgx_tstd/src/env.rs
@@ -37,9 +37,11 @@ use crate::sys::os as os_imp;
 ///
 /// # Platform-specific behavior
 ///
-/// This function currently corresponds to the `getcwd` function on Unix
+/// This function [currently] corresponds to the `getcwd` function on Unix
 /// and the `GetCurrentDirectoryW` function on Windows.
 ///
+/// [currently]: crate::io#platform-specific-behavior
+///
 /// # Errors
 ///
 /// Returns an [`Err`] if the current working directory value is invalid.
@@ -67,11 +69,13 @@ pub fn current_dir() -> io::Result<PathBuf> {
 ///
 /// # Platform-specific behavior
 ///
-/// This function currently corresponds to the `chdir` function on Unix
+/// This function [currently] corresponds to the `chdir` function on Unix
 /// and the `SetCurrentDirectoryW` function on Windows.
 ///
 /// Returns an [`Err`] if the operation fails.
 ///
+/// [currently]: crate::io#platform-specific-behavior
+///
 /// # Examples
 ///
 /// ```
@@ -125,7 +129,7 @@ pub struct VarsOs {
 /// // We will iterate through the references to the element returned by
 /// // env::vars();
 /// for (key, value) in env::vars() {
-///     println!("{}: {}", key, value);
+///     println!("{key}: {value}");
 /// }
 /// ```
 ///
@@ -154,7 +158,7 @@ pub fn vars() -> Vars {
 /// // We will iterate through the references to the element returned by
 /// // env::vars_os();
 /// for (key, value) in env::vars_os() {
-///     println!("{:?}: {:?}", key, value);
+///     println!("{key:?}: {value:?}");
 /// }
 /// ```
 #[must_use]
@@ -213,8 +217,8 @@ impl fmt::Debug for VarsOs {
 ///
 /// let key = "HOME";
 /// match env::var(key) {
-///     Ok(val) => println!("{}: {:?}", key, val),
-///     Err(e) => println!("couldn't interpret {}: {}", key, e),
+///     Ok(val) => println!("{key}: {val:?}"),
+///     Err(e) => println!("couldn't interpret {key}: {e}"),
 /// }
 /// ```
 pub fn var<K: AsRef<OsStr>>(key: K) -> Result<String, VarError> {
@@ -252,8 +256,8 @@ fn _var(key: &OsStr) -> Result<String, VarError> {
 ///
 /// let key = "HOME";
 /// match env::var_os(key) {
-///     Some(val) => println!("{}: {:?}", key, val),
-///     None => println!("{} is not defined in the environment.", key)
+///     Some(val) => println!("{key}: {val:?}"),
+///     None => println!("{key} is not defined in the environment.")
 /// }
 /// ```
 #[must_use]
@@ -263,7 +267,7 @@ pub fn var_os<K: AsRef<OsStr>>(key: K) -> Option<OsString> {
 
 fn _var_os(key: &OsStr) -> Option<OsString> {
     os_imp::getenv(key)
-        .unwrap_or_else(|e| panic!("failed to get environment variable `{:?}`: {}", key, e))
+        .unwrap_or_else(|e| panic!("failed to get environment variable `{key:?}`: {e}"))
 }
 
 /// The error type for operations interacting with environment variables.
@@ -337,7 +341,7 @@ pub fn set_var<K: AsRef<OsStr>, V: AsRef<OsStr>>(key: K, value: V) {
 
 fn _set_var(key: &OsStr, value: &OsStr) {
     os_imp::setenv(key, value).unwrap_or_else(|e| {
-        panic!("failed to set environment variable `{:?}` to `{:?}`: {}", key, value, e)
+        panic!("failed to set environment variable `{key:?}` to `{value:?}`: {e}")
     })
 }
 
@@ -378,7 +382,7 @@ pub fn remove_var<K: AsRef<OsStr>>(key: K) {
 
 fn _remove_var(key: &OsStr) {
     os_imp::unsetenv(key)
-        .unwrap_or_else(|e| panic!("failed to remove environment variable `{:?}`: {}", key, e))
+        .unwrap_or_else(|e| panic!("failed to remove environment variable `{key:?}`: {e}"))
 }
 
 /// An iterator that splits an environment variable into paths according to
@@ -413,7 +417,7 @@ pub struct SplitPaths<'a> {
 ///             println!("'{}'", path.display());
 ///         }
 ///     }
-///     None => println!("{} is not defined in the environment.", key)
+///     None => println!("{key} is not defined in the environment.")
 /// }
 /// ```
 pub fn split_paths<T: AsRef<OsStr> + ?Sized>(unparsed: &T) -> SplitPaths<'_> {
@@ -575,7 +579,7 @@ pub fn home_dir() -> Option<PathBuf> {
 /// # Platform-specific behavior
 ///
 /// On Unix, returns the value of the `TMPDIR` environment variable if it is
-/// set, otherwise for non-Android it returns `/tmp`. If Android, since there
+/// set, otherwise for non-Android it returns `/tmp`. On Android, since there
 /// is no global temporary folder (it is usually allocated per-app), it returns
 /// `/data/local/tmp`.
 /// On Windows, the behavior is equivalent to that of [`GetTempPath2`][GetTempPath2] /
@@ -618,36 +622,23 @@ pub fn temp_dir() -> PathBuf {
 ///
 /// # Security
 ///
-/// The output of this function should not be used in anything that might have
-/// security implications. For example:
+/// The output of this function should not be trusted for anything
+/// that might have security implications. Basically, if users can run
+/// the executable, they can change the output arbitrarily.
 ///
-/// ```
-/// fn main() {
-///     println!("{:?}", std::env::current_exe());
-/// }
-/// ```
+/// As an example, you can easily introduce a race condition. It goes
+/// like this:
 ///
-/// On Linux systems, if this is compiled as `foo`:
+/// 1. You get the path to the current executable using `current_exe()`, and
+///    store it in a variable.
+/// 2. Time passes. A malicious actor removes the current executable, and
+///    replaces it with a malicious one.
+/// 3. You then use the stored path to re-execute the current
+///    executable.
 ///
-/// ```bash
-/// $ rustc foo.rs
-/// $ ./foo
-/// Ok("/home/alex/foo")
-/// ```
-///
-/// And you make a hard link of the program:
-///
-/// ```bash
-/// $ ln foo bar
-/// ```
-///
-/// When you run it, you won’t get the path of the original executable, you’ll
-/// get the path of the hard link:
-///
-/// ```bash
-/// $ ./bar
-/// Ok("/home/alex/bar")
-/// ```
+/// You expected to safely execute the current executable, but you're
+/// instead executing something completely different. The code you
+/// just executed run with your privileges.
 ///
 /// This sort of behavior has been known to [lead to privilege escalation] when
 /// used incorrectly.
@@ -662,7 +653,7 @@ pub fn temp_dir() -> PathBuf {
 /// match env::current_exe() {
 ///     Ok(exe_path) => println!("Path of this executable is: {}",
 ///                              exe_path.display()),
-///     Err(e) => println!("failed to get current exe path: {}", e),
+///     Err(e) => println!("failed to get current exe path: {e}"),
 /// };
 /// ```
 pub fn current_exe() -> io::Result<PathBuf> {
diff --git a/sgx_tstd/src/error.rs b/sgx_tstd/src/error.rs
index d795fc9a..ec182b39 100644
--- a/sgx_tstd/src/error.rs
+++ b/sgx_tstd/src/error.rs
@@ -17,150 +17,14 @@
 
 //! Traits for working with Errors.
 
-// A note about crates and the facade:
-//
-// Originally, the `Error` trait was defined in libcore, and the impls
-// were scattered about. However, coherence objected to this
-// arrangement, because to create the blanket impls for `Box` required
-// knowing that `&str: !Error`, and we have no means to deal with that
-// sort of conflict just now. Therefore, for the time being, we have
-// moved the `Error` trait into libstd. As we evolve a sol'n to the
-// coherence challenge (e.g., specialization, neg impls, etc) we can
-// reconsider what crate these items belong in.
-
-use core::array;
-use core::convert::Infallible;
+#[cfg(feature = "unit_test")]
+mod tests;
 
-use crate::alloc::{AllocError, LayoutError};
-use crate::any::TypeId;
 #[cfg(feature = "backtrace")]
 use crate::backtrace::Backtrace;
-use crate::borrow::Cow;
-use crate::cell;
-use crate::char;
-use crate::fmt::{self, Debug, Display};
-#[cfg(feature = "backtrace")]
-use crate::fmt::Write;
-use crate::mem::transmute;
-use crate::num;
-use crate::str;
-use crate::string;
-use crate::sync::Arc;
-use crate::time;
+use crate::fmt::{self, Write};
 
-use sgx_types::sgx_status_t;
-
-/// `Error` is a trait representing the basic expectations for error values,
-/// i.e., values of type `E` in [`Result<T, E>`].
-///
-/// Errors must describe themselves through the [`Display`] and [`Debug`]
-/// traits. Error messages are typically concise lowercase sentences without
-/// trailing punctuation:
-///
-/// ```
-/// let err = "NaN".parse::<u32>().unwrap_err();
-/// assert_eq!(err.to_string(), "invalid digit found in string");
-/// ```
-///
-/// Errors may provide cause chain information. [`Error::source()`] is generally
-/// used when errors cross "abstraction boundaries". If one module must report
-/// an error that is caused by an error from a lower-level module, it can allow
-/// accessing that error via [`Error::source()`]. This makes it possible for the
-/// high-level module to provide its own errors while also revealing some of the
-/// implementation for debugging via `source` chains.
-pub trait Error: Debug + Display {
-    /// The lower-level source of this error, if any.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::error::Error;
-    /// use std::fmt;
-    ///
-    /// #[derive(Debug)]
-    /// struct SuperError {
-    ///     source: SuperErrorSideKick,
-    /// }
-    ///
-    /// impl fmt::Display for SuperError {
-    ///     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-    ///         write!(f, "SuperError is here!")
-    ///     }
-    /// }
-    ///
-    /// impl Error for SuperError {
-    ///     fn source(&self) -> Option<&(dyn Error + 'static)> {
-    ///         Some(&self.source)
-    ///     }
-    /// }
-    ///
-    /// #[derive(Debug)]
-    /// struct SuperErrorSideKick;
-    ///
-    /// impl fmt::Display for SuperErrorSideKick {
-    ///     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-    ///         write!(f, "SuperErrorSideKick is here!")
-    ///     }
-    /// }
-    ///
-    /// impl Error for SuperErrorSideKick {}
-    ///
-    /// fn get_super_error() -> Result<(), SuperError> {
-    ///     Err(SuperError { source: SuperErrorSideKick })
-    /// }
-    ///
-    /// fn main() {
-    ///     match get_super_error() {
-    ///         Err(e) => {
-    ///             println!("Error: {}", e);
-    ///             println!("Caused by: {}", e.source().unwrap());
-    ///         }
-    ///         _ => println!("No error"),
-    ///     }
-    /// }
-    /// ```
-    fn source(&self) -> Option<&(dyn Error + 'static)> {
-        None
-    }
-
-    /// Gets the `TypeId` of `self`.
-    #[doc(hidden)]
-    fn type_id(&self, _: private::Internal) -> TypeId
-    where
-        Self: 'static,
-    {
-        TypeId::of::<Self>()
-    }
-
-    /// Returns a stack backtrace, if available, of where this error occurred.
-    ///
-    /// This function allows inspecting the location, in code, of where an error
-    /// happened. The returned `Backtrace` contains information about the stack
-    /// trace of the OS thread of execution of where the error originated from.
-    ///
-    /// Note that not all errors contain a `Backtrace`. Also note that a
-    /// `Backtrace` may actually be empty. For more information consult the
-    /// `Backtrace` type itself.
-    #[cfg(feature = "backtrace")]
-    fn backtrace(&self) -> Option<&Backtrace> {
-        None
-    }
-
-    /// ```
-    /// if let Err(e) = "xc".parse::<u32>() {
-    ///     // Print `e` itself, no need for description().
-    ///     eprintln!("Error: {}", e);
-    /// }
-    /// ```
-    fn description(&self) -> &str {
-        "description() is deprecated; use Display"
-    }
-
-    #[allow(missing_docs)]
-    fn cause(&self) -> Option<&dyn Error> {
-        self.source()
-    }
-}
+pub use core::error::Error;
 
 mod private {
     // This is a hack to prevent `type_id` from being overridden by `Error`
@@ -169,612 +33,12 @@ mod private {
     pub struct Internal;
 }
 
-impl<'a, E: Error + 'a> From<E> for Box<dyn Error + 'a> {
-    /// Converts a type of [`Error`] into a box of dyn [`Error`].
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::error::Error;
-    /// use std::fmt;
-    /// use std::mem;
-    ///
-    /// #[derive(Debug)]
-    /// struct AnError;
-    ///
-    /// impl fmt::Display for AnError {
-    ///     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-    ///         write!(f, "An error")
-    ///     }
-    /// }
-    ///
-    /// impl Error for AnError {}
-    ///
-    /// let an_error = AnError;
-    /// assert!(0 == mem::size_of_val(&an_error));
-    /// let a_boxed_error = Box::<dyn Error>::from(an_error);
-    /// assert!(mem::size_of::<Box<dyn Error>>() == mem::size_of_val(&a_boxed_error))
-    /// ```
-    fn from(err: E) -> Box<dyn Error + 'a> {
-        Box::new(err)
-    }
-}
-
-impl<'a, E: Error + Send + Sync + 'a> From<E> for Box<dyn Error + Send + Sync + 'a> {
-    /// Converts a type of [`Error`] + [`Send`] + [`Sync`] into a box of
-    /// dyn [`Error`] + [`Send`] + [`Sync`].
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::error::Error;
-    /// use std::fmt;
-    /// use std::mem;
-    ///
-    /// #[derive(Debug)]
-    /// struct AnError;
-    ///
-    /// impl fmt::Display for AnError {
-    ///     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-    ///         write!(f, "An error")
-    ///     }
-    /// }
-    ///
-    /// impl Error for AnError {}
-    ///
-    /// unsafe impl Send for AnError {}
-    ///
-    /// unsafe impl Sync for AnError {}
-    ///
-    /// let an_error = AnError;
-    /// assert!(0 == mem::size_of_val(&an_error));
-    /// let a_boxed_error = Box::<dyn Error + Send + Sync>::from(an_error);
-    /// assert!(
-    ///     mem::size_of::<Box<dyn Error + Send + Sync>>() == mem::size_of_val(&a_boxed_error))
-    /// ```
-    fn from(err: E) -> Box<dyn Error + Send + Sync + 'a> {
-        Box::new(err)
-    }
-}
-
-impl From<String> for Box<dyn Error + Send + Sync> {
-    /// Converts a [`String`] into a box of dyn [`Error`] + [`Send`] + [`Sync`].
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::error::Error;
-    /// use std::mem;
-    ///
-    /// let a_string_error = "a string error".to_string();
-    /// let a_boxed_error = Box::<dyn Error + Send + Sync>::from(a_string_error);
-    /// assert!(
-    ///     mem::size_of::<Box<dyn Error + Send + Sync>>() == mem::size_of_val(&a_boxed_error))
-    /// ```
-    #[inline]
-    fn from(err: String) -> Box<dyn Error + Send + Sync> {
-        struct StringError(String);
-
-        impl Error for StringError {
-            #[allow(deprecated)]
-            fn description(&self) -> &str {
-                &self.0
-            }
-        }
-
-        impl Display for StringError {
-            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-                Display::fmt(&self.0, f)
-            }
-        }
-
-        // Purposefully skip printing "StringError(..)"
-        impl Debug for StringError {
-            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-                Debug::fmt(&self.0, f)
-            }
-        }
-
-        Box::new(StringError(err))
-    }
-}
-
-impl From<String> for Box<dyn Error> {
-    /// Converts a [`String`] into a box of dyn [`Error`].
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::error::Error;
-    /// use std::mem;
-    ///
-    /// let a_string_error = "a string error".to_string();
-    /// let a_boxed_error = Box::<dyn Error>::from(a_string_error);
-    /// assert!(mem::size_of::<Box<dyn Error>>() == mem::size_of_val(&a_boxed_error))
-    /// ```
-    fn from(str_err: String) -> Box<dyn Error> {
-        let err1: Box<dyn Error + Send + Sync> = From::from(str_err);
-        let err2: Box<dyn Error> = err1;
-        err2
-    }
-}
-
-impl<'a> From<&str> for Box<dyn Error + Send + Sync + 'a> {
-    /// Converts a [`str`] into a box of dyn [`Error`] + [`Send`] + [`Sync`].
-    ///
-    /// [`str`]: prim@str
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::error::Error;
-    /// use std::mem;
-    ///
-    /// let a_str_error = "a str error";
-    /// let a_boxed_error = Box::<dyn Error + Send + Sync>::from(a_str_error);
-    /// assert!(
-    ///     mem::size_of::<Box<dyn Error + Send + Sync>>() == mem::size_of_val(&a_boxed_error))
-    /// ```
-    #[inline]
-    fn from(err: &str) -> Box<dyn Error + Send + Sync + 'a> {
-        From::from(String::from(err))
-    }
-}
-
-impl From<&str> for Box<dyn Error> {
-    /// Converts a [`str`] into a box of dyn [`Error`].
-    ///
-    /// [`str`]: prim@str
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::error::Error;
-    /// use std::mem;
-    ///
-    /// let a_str_error = "a str error";
-    /// let a_boxed_error = Box::<dyn Error>::from(a_str_error);
-    /// assert!(mem::size_of::<Box<dyn Error>>() == mem::size_of_val(&a_boxed_error))
-    /// ```
-    fn from(err: &str) -> Box<dyn Error> {
-        From::from(String::from(err))
-    }
-}
-
-impl<'a, 'b> From<Cow<'b, str>> for Box<dyn Error + Send + Sync + 'a> {
-    /// Converts a [`Cow`] into a box of dyn [`Error`] + [`Send`] + [`Sync`].
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::error::Error;
-    /// use std::mem;
-    /// use std::borrow::Cow;
-    ///
-    /// let a_cow_str_error = Cow::from("a str error");
-    /// let a_boxed_error = Box::<dyn Error + Send + Sync>::from(a_cow_str_error);
-    /// assert!(
-    ///     mem::size_of::<Box<dyn Error + Send + Sync>>() == mem::size_of_val(&a_boxed_error))
-    /// ```
-    fn from(err: Cow<'b, str>) -> Box<dyn Error + Send + Sync + 'a> {
-        From::from(String::from(err))
-    }
-}
-
-impl<'a> From<Cow<'a, str>> for Box<dyn Error> {
-    /// Converts a [`Cow`] into a box of dyn [`Error`].
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::error::Error;
-    /// use std::mem;
-    /// use std::borrow::Cow;
-    ///
-    /// let a_cow_str_error = Cow::from("a str error");
-    /// let a_boxed_error = Box::<dyn Error>::from(a_cow_str_error);
-    /// assert!(mem::size_of::<Box<dyn Error>>() == mem::size_of_val(&a_boxed_error))
-    /// ```
-    fn from(err: Cow<'a, str>) -> Box<dyn Error> {
-        From::from(String::from(err))
-    }
-}
-
-impl Error for ! {}
-
-impl Error for AllocError {}
-
-impl Error for LayoutError {}
-
-impl Error for str::ParseBoolError {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        "failed to parse bool"
-    }
-}
-
-impl Error for str::Utf8Error {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        "invalid utf-8: corrupt contents"
-    }
-}
-
-impl Error for num::ParseIntError {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        self.__description()
-    }
-}
-
-impl Error for num::TryFromIntError {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        self.__description()
-    }
-}
-
-impl Error for array::TryFromSliceError {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        self.__description()
-    }
-}
-
-impl Error for num::ParseFloatError {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        self.__description()
-    }
-}
-
-impl Error for string::FromUtf8Error {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        "invalid utf-8"
-    }
-}
-
-impl Error for string::FromUtf16Error {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        "invalid utf-16"
-    }
-}
-
-impl Error for Infallible {
-    fn description(&self) -> &str {
-        match *self {}
-    }
-}
-
-impl Error for char::DecodeUtf16Error {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        "unpaired surrogate found"
-    }
-}
-
-impl Error for char::TryFromCharError {}
-
-impl<'a, K: Debug + Ord, V: Debug> Error
-    for crate::collections::btree_map::OccupiedError<'a, K, V>
-{
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        "key already exists"
-    }
-}
-
-impl<'a, K: Debug, V: Debug> Error for crate::collections::hash_map::OccupiedError<'a, K, V> {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        "key already exists"
-    }
-}
-
-impl Error for sgx_status_t {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        self.__description()
-    }
-}
-
-impl<T: Error> Error for Box<T> {
-    #[allow(deprecated, deprecated_in_future)]
-    fn description(&self) -> &str {
-        Error::description(&**self)
-    }
-
-    #[allow(deprecated)]
-    fn cause(&self) -> Option<&dyn Error> {
-        Error::cause(&**self)
-    }
-
-    fn source(&self) -> Option<&(dyn Error + 'static)> {
-        Error::source(&**self)
-    }
-}
-
-impl<'a, T: Error + ?Sized> Error for &'a T {
-    #[allow(deprecated, deprecated_in_future)]
-    fn description(&self) -> &str {
-        Error::description(&**self)
-    }
-
-    #[allow(deprecated)]
-    fn cause(&self) -> Option<&dyn Error> {
-        Error::cause(&**self)
-    }
-
-    fn source(&self) -> Option<&(dyn Error + 'static)> {
-        Error::source(&**self)
-    }
-
-    #[cfg(feature = "backtrace")]
-    fn backtrace(&self) -> Option<&Backtrace> {
-        Error::backtrace(&**self)
-    }
-}
-
-impl<T: Error + ?Sized> Error for Arc<T> {
-    #[allow(deprecated, deprecated_in_future)]
-    fn description(&self) -> &str {
-        Error::description(&**self)
-    }
-
-    #[allow(deprecated)]
-    fn cause(&self) -> Option<&dyn Error> {
-        Error::cause(&**self)
-    }
-
-    fn source(&self) -> Option<&(dyn Error + 'static)> {
-        Error::source(&**self)
-    }
-
-    #[cfg(feature = "backtrace")]
-    fn backtrace(&self) -> Option<&Backtrace> {
-        Error::backtrace(&**self)
-    }
-}
-
-impl Error for fmt::Error {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        "an error occurred when formatting an argument"
-    }
-}
-
-impl Error for cell::BorrowError {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        "already mutably borrowed"
-    }
-}
-
-impl Error for cell::BorrowMutError {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        "already borrowed"
-    }
-}
-
-impl Error for char::CharTryFromError {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        "converted integer out of range for `char`"
-    }
-}
-
-impl Error for char::ParseCharError {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        self.__description()
-    }
-}
-
-impl Error for alloc_crate::collections::TryReserveError {}
-
-impl Error for time::FromFloatSecsError {}
-
-// Copied from `any.rs`.
-impl dyn Error + 'static {
-    /// Returns `true` if the inner type is the same as `T`.
-    #[inline]
-    pub fn is<T: Error + 'static>(&self) -> bool {
-        // Get `TypeId` of the type this function is instantiated with.
-        let t = TypeId::of::<T>();
-
-        // Get `TypeId` of the type in the trait object (`self`).
-        let concrete = self.type_id(private::Internal);
-
-        // Compare both `TypeId`s on equality.
-        t == concrete
-    }
-
-    /// Returns some reference to the inner value if it is of type `T`, or
-    /// `None` if it isn't.
-    #[inline]
-    pub fn downcast_ref<T: Error + 'static>(&self) -> Option<&T> {
-        if self.is::<T>() {
-            unsafe { Some(&*(self as *const dyn Error as *const T)) }
-        } else {
-            None
-        }
-    }
-
-    /// Returns some mutable reference to the inner value if it is of type `T`, or
-    /// `None` if it isn't.
-    #[inline]
-    pub fn downcast_mut<T: Error + 'static>(&mut self) -> Option<&mut T> {
-        if self.is::<T>() {
-            unsafe { Some(&mut *(self as *mut dyn Error as *mut T)) }
-        } else {
-            None
-        }
-    }
-}
-
-impl dyn Error + 'static + Send {
-    /// Forwards to the method defined on the type `dyn Error`.
-    #[inline]
-    pub fn is<T: Error + 'static>(&self) -> bool {
-        <dyn Error + 'static>::is::<T>(self)
-    }
-
-    /// Forwards to the method defined on the type `dyn Error`.
-    #[inline]
-    pub fn downcast_ref<T: Error + 'static>(&self) -> Option<&T> {
-        <dyn Error + 'static>::downcast_ref::<T>(self)
-    }
-
-    /// Forwards to the method defined on the type `dyn Error`.
-    #[inline]
-    pub fn downcast_mut<T: Error + 'static>(&mut self) -> Option<&mut T> {
-        <dyn Error + 'static>::downcast_mut::<T>(self)
-    }
-}
-
-impl dyn Error + 'static + Send + Sync {
-    /// Forwards to the method defined on the type `dyn Error`.
-    #[inline]
-    pub fn is<T: Error + 'static>(&self) -> bool {
-        <dyn Error + 'static>::is::<T>(self)
-    }
-
-    /// Forwards to the method defined on the type `dyn Error`.
-    #[inline]
-    pub fn downcast_ref<T: Error + 'static>(&self) -> Option<&T> {
-        <dyn Error + 'static>::downcast_ref::<T>(self)
-    }
-
-    /// Forwards to the method defined on the type `dyn Error`.
-    #[inline]
-    pub fn downcast_mut<T: Error + 'static>(&mut self) -> Option<&mut T> {
-        <dyn Error + 'static>::downcast_mut::<T>(self)
-    }
-}
-
-impl dyn Error {
-    #[inline]
-    /// Attempts to downcast the box to a concrete type.
-    pub fn downcast<T: Error + 'static>(self: Box<Self>) -> Result<Box<T>, Box<dyn Error>> {
-        if self.is::<T>() {
-            unsafe {
-                let raw: *mut dyn Error = Box::into_raw(self);
-                Ok(Box::from_raw(raw as *mut T))
-            }
-        } else {
-            Err(self)
-        }
-    }
-
-    /// Returns an iterator starting with the current error and continuing with
-    /// recursively calling [`Error::source`].
-    ///
-    /// If you want to omit the current error and only use its sources,
-    /// use `skip(1)`.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(error_iter)]
-    /// use std::error::Error;
-    /// use std::fmt;
-    ///
-    /// #[derive(Debug)]
-    /// struct A;
-    ///
-    /// #[derive(Debug)]
-    /// struct B(Option<Box<dyn Error + 'static>>);
-    ///
-    /// impl fmt::Display for A {
-    ///     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-    ///         write!(f, "A")
-    ///     }
-    /// }
-    ///
-    /// impl fmt::Display for B {
-    ///     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-    ///         write!(f, "B")
-    ///     }
-    /// }
-    ///
-    /// impl Error for A {}
-    ///
-    /// impl Error for B {
-    ///     fn source(&self) -> Option<&(dyn Error + 'static)> {
-    ///         self.0.as_ref().map(|e| e.as_ref())
-    ///     }
-    /// }
-    ///
-    /// let b = B(Some(Box::new(A)));
-    ///
-    /// // let err : Box<Error> = b.into(); // or
-    /// let err = &b as &(dyn Error);
-    ///
-    /// let mut iter = err.chain();
-    ///
-    /// assert_eq!("B".to_string(), iter.next().unwrap().to_string());
-    /// assert_eq!("A".to_string(), iter.next().unwrap().to_string());
-    /// assert!(iter.next().is_none());
-    /// assert!(iter.next().is_none());
-    /// ```
-    #[inline]
-    pub fn chain(&self) -> Chain<'_> {
-        Chain { current: Some(self) }
-    }
-}
-
-/// An iterator over an [`Error`] and its sources.
+/// An error reporter that prints an error and its sources.
 ///
-/// If you want to omit the initial error and only process
-/// its sources, use `skip(1)`.
-#[derive(Clone, Debug)]
-pub struct Chain<'a> {
-    current: Option<&'a (dyn Error + 'static)>,
-}
-
-impl<'a> Iterator for Chain<'a> {
-    type Item = &'a (dyn Error + 'static);
-
-    fn next(&mut self) -> Option<Self::Item> {
-        let current = self.current;
-        self.current = self.current.and_then(Error::source);
-        current
-    }
-}
-
-impl dyn Error + Send {
-    #[inline]
-    /// Attempts to downcast the box to a concrete type.
-    pub fn downcast<T: Error + 'static>(self: Box<Self>) -> Result<Box<T>, Box<dyn Error + Send>> {
-        let err: Box<dyn Error> = self;
-        <dyn Error>::downcast(err).map_err(|s| unsafe {
-            // Reapply the `Send` marker.
-            transmute::<Box<dyn Error>, Box<dyn Error + Send>>(s)
-        })
-    }
-}
-
-impl dyn Error + Send + Sync {
-    #[inline]
-    /// Attempts to downcast the box to a concrete type.
-    pub fn downcast<T: Error + 'static>(self: Box<Self>) -> Result<Box<T>, Box<Self>> {
-        let err: Box<dyn Error> = self;
-        <dyn Error>::downcast(err).map_err(|s| unsafe {
-            // Reapply the `Send + Sync` marker.
-            transmute::<Box<dyn Error>, Box<dyn Error + Send + Sync>>(s)
-        })
-    }
-}
-
-/// An error reporter that print's an error and its sources.
-///
-/// Report also exposes configuration options for formatting the error chain, either entirely on a
-/// single line, or in multi-line format with each cause in the error chain on a new line.
+/// Report also exposes configuration options for formatting the error sources, either entirely on a
+/// single line, or in multi-line format with each source on a new line.
 ///
-/// `Report` only requires that the wrapped error implements `Error`. It doesn't require that the
+/// `Report` only requires that the wrapped error implement `Error`. It doesn't require that the
 /// wrapped error be `Send`, `Sync`, or `'static`.
 ///
 /// # Examples
@@ -878,7 +142,7 @@ impl dyn Error + Send + Sync {
 ///
 /// ## Return from `main`
 ///
-/// `Report` also implements `From` for all types that implement [`Error`], this when combined with
+/// `Report` also implements `From` for all types that implement [`Error`]; this when combined with
 /// the `Debug` output means `Report` is an ideal starting place for formatting errors returned
 /// from `main`.
 ///
@@ -913,7 +177,7 @@ impl dyn Error + Send + Sync {
 /// #     Err(SuperError { source: SuperErrorSideKick })
 /// # }
 ///
-/// fn main() -> Result<(), Report> {
+/// fn main() -> Result<(), Report<SuperError>> {
 ///     get_super_error()?;
 ///     Ok(())
 /// }
@@ -926,7 +190,7 @@ impl dyn Error + Send + Sync {
 /// ```
 ///
 /// **Note**: `Report`s constructed via `?` and `From` will be configured to use the single line
-/// output format, if you want to make sure your `Report`s are pretty printed and include backtrace
+/// output format. If you want to make sure your `Report`s are pretty printed and include backtrace
 /// you will need to manually convert and enable those flags.
 ///
 /// ```should_panic
@@ -960,7 +224,7 @@ impl dyn Error + Send + Sync {
 /// #     Err(SuperError { source: SuperErrorSideKick })
 /// # }
 ///
-/// fn main() -> Result<(), Report> {
+/// fn main() -> Result<(), Report<SuperError>> {
 ///     get_super_error()
 ///         .map_err(Report::from)
 ///         .map_err(|r| r.pretty(true).show_backtrace(true))?;
@@ -976,7 +240,6 @@ impl dyn Error + Send + Sync {
 /// Caused by:
 ///       SuperErrorSideKick is here!
 /// ```
-#[cfg(feature = "backtrace")]
 pub struct Report<E = Box<dyn Error>> {
     /// The error being reported.
     error: E,
@@ -986,7 +249,6 @@ pub struct Report<E = Box<dyn Error>> {
     pretty: bool,
 }
 
-#[cfg(feature = "backtrace")]
 impl<E> Report<E>
 where
     Report<E>: From<E>,
@@ -997,7 +259,6 @@ where
     }
 }
 
-#[cfg(feature = "backtrace")]
 impl<E> Report<E> {
     /// Enable pretty-printing the report across multiple lines.
     ///
@@ -1033,7 +294,7 @@ impl<E> Report<E> {
     ///
     /// let error = SuperError { source: SuperErrorSideKick };
     /// let report = Report::new(error).pretty(true);
-    /// eprintln!("Error: {:?}", report);
+    /// eprintln!("Error: {report:?}");
     /// ```
     ///
     /// This example produces the following output:
@@ -1094,7 +355,7 @@ impl<E> Report<E> {
     /// let source = SuperErrorSideKick { source };
     /// let error = SuperError { source };
     /// let report = Report::new(error).pretty(true);
-    /// eprintln!("Error: {:?}", report);
+    /// eprintln!("Error: {report:?}");
     /// ```
     ///
     /// This example produces the following output:
@@ -1117,13 +378,15 @@ impl<E> Report<E> {
     ///
     /// **Note**: Report will search for the first `Backtrace` it can find starting from the
     /// outermost error. In this example it will display the backtrace from the second error in the
-    /// chain, `SuperErrorSideKick`.
+    /// sources, `SuperErrorSideKick`.
     ///
     /// ```rust
     /// #![feature(error_reporter)]
-    /// #![feature(backtrace)]
+    /// #![feature(provide_any)]
+    /// #![feature(error_generic_member_access)]
     /// # use std::error::Error;
     /// # use std::fmt;
+    /// use std::any::Demand;
     /// use std::error::Report;
     /// use std::backtrace::Backtrace;
     ///
@@ -1153,8 +416,8 @@ impl<E> Report<E> {
     /// }
     ///
     /// impl Error for SuperErrorSideKick {
-    ///     fn backtrace(&self) -> Option<&Backtrace> {
-    ///         Some(&self.backtrace)
+    ///     fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
+    ///         demand.provide_ref::<Backtrace>(&self.backtrace);
     ///     }
     /// }
     ///
@@ -1168,7 +431,7 @@ impl<E> Report<E> {
     /// let source = SuperErrorSideKick::new();
     /// let error = SuperError { source };
     /// let report = Report::new(error).pretty(true).show_backtrace(true);
-    /// eprintln!("Error: {:?}", report);
+    /// eprintln!("Error: {report:?}");
     /// ```
     ///
     /// This example produces something similar to the following output:
@@ -1199,82 +462,21 @@ impl<E> Report<E> {
     }
 }
 
-#[cfg(feature = "backtrace")]
 impl<E> Report<E>
 where
     E: Error,
 {
+    #[cfg(feature = "backtrace")]
+    #[allow(clippy::map_flatten)]
     fn backtrace(&self) -> Option<&Backtrace> {
         // have to grab the backtrace on the first error directly since that error may not be
         // 'static
-        let backtrace = self.error.backtrace();
-        backtrace.or_else(|| {
-            self.error
-                .source()
-                .and_then(|source| source.chain().find_map(|source| source.backtrace()))
-        })
-    }
-
-    /// Format the report as a single line.
-    fn fmt_singleline(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "{}", self.error)?;
-
-        let sources = self.error.source().into_iter().flat_map(<dyn Error>::chain);
-
-        for cause in sources {
-            write!(f, ": {}", cause)?;
-        }
-
-        Ok(())
-    }
-
-    /// Format the report as multiple lines, with each error cause on its own line.
-    fn fmt_multiline(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let error = &self.error;
-
-        write!(f, "{}", error)?;
-
-        if let Some(cause) = error.source() {
-            write!(f, "\n\nCaused by:")?;
-
-            let multiple = cause.source().is_some();
-
-            for (ind, error) in cause.chain().enumerate() {
-                writeln!(f)?;
-                let mut indented = Indented { inner: f };
-                if multiple {
-                    write!(indented, "{: >4}: {}", ind, error)?;
-                } else {
-                    write!(indented, "      {}", error)?;
-                }
-            }
-        }
-
-        if self.show_backtrace {
-            let backtrace = self.backtrace();
-
-            if let Some(backtrace) = backtrace {
-                let backtrace = backtrace.to_string();
-
-                f.write_str("\n\nStack backtrace:\n")?;
-                f.write_str(backtrace.trim_end())?;
-            }
-        }
-
-        Ok(())
-    }
-}
-
-#[cfg(feature = "backtrace")]
-impl Report<Box<dyn Error>> {
-    fn backtrace(&self) -> Option<&Backtrace> {
-        // have to grab the backtrace on the first error directly since that error may not be
-        // 'static
-        let backtrace = self.error.backtrace();
+        let backtrace = (&self.error as &dyn Error).request_ref();
         backtrace.or_else(|| {
             self.error
                 .source()
-                .and_then(|source| source.chain().find_map(|source| source.backtrace()))
+                .map(|source| source.sources().find_map(|source| source.request_ref()))
+                .flatten()
         })
     }
 
@@ -1282,10 +484,10 @@ impl Report<Box<dyn Error>> {
     fn fmt_singleline(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         write!(f, "{}", self.error)?;
 
-        let sources = self.error.source().into_iter().flat_map(<dyn Error>::chain);
+        let sources = self.error.source().into_iter().flat_map(<dyn Error>::sources);
 
         for cause in sources {
-            write!(f, ": {}", cause)?;
+            write!(f, ": {cause}")?;
         }
 
         Ok(())
@@ -1295,24 +497,25 @@ impl Report<Box<dyn Error>> {
     fn fmt_multiline(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         let error = &self.error;
 
-        write!(f, "{}", error)?;
+        write!(f, "{error}")?;
 
         if let Some(cause) = error.source() {
             write!(f, "\n\nCaused by:")?;
 
             let multiple = cause.source().is_some();
 
-            for (ind, error) in cause.chain().enumerate() {
+            for (ind, error) in cause.sources().enumerate() {
                 writeln!(f)?;
                 let mut indented = Indented { inner: f };
                 if multiple {
-                    write!(indented, "{: >4}: {}", ind, error)?;
+                    write!(indented, "{ind: >4}: {error}")?;
                 } else {
-                    write!(indented, "      {}", error)?;
+                    write!(indented, "      {error}")?;
                 }
             }
         }
 
+        #[cfg(feature = "backtrace")]
         if self.show_backtrace {
             let backtrace = self.backtrace();
 
@@ -1328,7 +531,6 @@ impl Report<Box<dyn Error>> {
     }
 }
 
-#[cfg(feature = "backtrace")]
 impl<E> From<E> for Report<E>
 where
     E: Error,
@@ -1338,18 +540,6 @@ where
     }
 }
 
-#[cfg(feature = "backtrace")]
-impl<'a, E> From<E> for Report<Box<dyn Error + 'a>>
-where
-    E: Error + 'a,
-{
-    fn from(error: E) -> Self {
-        let error = box error;
-        Report { error, show_backtrace: false, pretty: false }
-    }
-}
-
-#[cfg(feature = "backtrace")]
 impl<E> fmt::Display for Report<E>
 where
     E: Error,
@@ -1359,16 +549,8 @@ where
     }
 }
 
-#[cfg(feature = "backtrace")]
-impl fmt::Display for Report<Box<dyn Error>> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        if self.pretty { self.fmt_multiline(f) } else { self.fmt_singleline(f) }
-    }
-}
-
 // This type intentionally outputs the same format for `Display` and `Debug`for
 // situations where you unwrap a `Report` or return it from main.
-#[cfg(feature = "backtrace")]
 impl<E> fmt::Debug for Report<E>
 where
     Report<E>: fmt::Display,
@@ -1379,12 +561,10 @@ where
 }
 
 /// Wrapper type for indenting the inner source.
-#[cfg(feature = "backtrace")]
 struct Indented<'a, D> {
     inner: &'a mut D,
 }
 
-#[cfg(feature = "backtrace")]
 impl<T> Write for Indented<'_, T>
 where
     T: Write,
diff --git a/sgx_tstd/src/f32.rs b/sgx_tstd/src/f32.rs
index e8b0850f..71fd19a2 100644
--- a/sgx_tstd/src/f32.rs
+++ b/sgx_tstd/src/f32.rs
@@ -15,7 +15,7 @@
 // specific language governing permissions and limitations
 // under the License..
 
-//! Constants specific to the `f32` single-precision floating point type.
+//! Constants for the `f32` single-precision floating point type.
 //!
 //! *[See also the `f32` primitive type](primitive@f32).*
 //!
@@ -37,9 +37,8 @@ pub use core::f32::{
     MIN_EXP, MIN_POSITIVE, NAN, NEG_INFINITY, RADIX,
 };
 
-#[lang = "f32_runtime"]
 impl f32 {
-    /// Returns the largest integer less than or equal to a number.
+    /// Returns the largest integer less than or equal to `self`.
     ///
     /// # Examples
     ///
@@ -52,13 +51,14 @@ impl f32 {
     /// assert_eq!(g.floor(), 3.0);
     /// assert_eq!(h.floor(), -4.0);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn floor(self) -> f32 {
         unsafe { intrinsics::floorf32(self) }
     }
 
-    /// Returns the smallest integer greater than or equal to a number.
+    /// Returns the smallest integer greater than or equal to `self`.
     ///
     /// # Examples
     ///
@@ -69,13 +69,14 @@ impl f32 {
     /// assert_eq!(f.ceil(), 4.0);
     /// assert_eq!(g.ceil(), 4.0);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn ceil(self) -> f32 {
         unsafe { intrinsics::ceilf32(self) }
     }
 
-    /// Returns the nearest integer to a number. Round half-way cases away from
+    /// Returns the nearest integer to `self`. Round half-way cases away from
     /// `0.0`.
     ///
     /// # Examples
@@ -87,13 +88,15 @@ impl f32 {
     /// assert_eq!(f.round(), 3.0);
     /// assert_eq!(g.round(), -3.0);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn round(self) -> f32 {
         unsafe { intrinsics::roundf32(self) }
     }
 
-    /// Returns the integer part of a number.
+    /// Returns the integer part of `self`.
+    /// This means that non-integer numbers are always truncated towards zero.
     ///
     /// # Examples
     ///
@@ -106,13 +109,14 @@ impl f32 {
     /// assert_eq!(g.trunc(), 3.0);
     /// assert_eq!(h.trunc(), -3.0);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn trunc(self) -> f32 {
         unsafe { intrinsics::truncf32(self) }
     }
 
-    /// Returns the fractional part of a number.
+    /// Returns the fractional part of `self`.
     ///
     /// # Examples
     ///
@@ -125,14 +129,14 @@ impl f32 {
     /// assert!(abs_difference_x <= f32::EPSILON);
     /// assert!(abs_difference_y <= f32::EPSILON);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn fract(self) -> f32 {
         self - self.trunc()
     }
 
-    /// Computes the absolute value of `self`. Returns `NAN` if the
-    /// number is `NAN`.
+    /// Computes the absolute value of `self`.
     ///
     /// # Examples
     ///
@@ -148,6 +152,7 @@ impl f32 {
     ///
     /// assert!(f32::NAN.abs().is_nan());
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn abs(self) -> f32 {
@@ -158,7 +163,7 @@ impl f32 {
     ///
     /// - `1.0` if the number is positive, `+0.0` or `INFINITY`
     /// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
-    /// - `NAN` if the number is `NAN`
+    /// - NaN if the number is NaN
     ///
     /// # Examples
     ///
@@ -170,6 +175,7 @@ impl f32 {
     ///
     /// assert!(f32::NAN.signum().is_nan());
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn signum(self) -> f32 {
@@ -180,8 +186,10 @@ impl f32 {
     /// `sign`.
     ///
     /// Equal to `self` if the sign of `self` and `sign` are the same, otherwise
-    /// equal to `-self`. If `self` is a `NAN`, then a `NAN` with the sign of
-    /// `sign` is returned.
+    /// equal to `-self`. If `self` is a NaN, then a NaN with the sign bit of
+    /// `sign` is returned. Note, however, that conserving the sign bit on NaN
+    /// across arithmetical operations is not generally guaranteed.
+    /// See [explanation of NaN as a special value](primitive@f32) for more info.
     ///
     /// # Examples
     ///
@@ -195,6 +203,7 @@ impl f32 {
     ///
     /// assert!(f32::NAN.copysign(1.0).is_nan());
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn copysign(self, sign: f32) -> f32 {
@@ -221,6 +230,7 @@ impl f32 {
     ///
     /// assert!(abs_difference <= f32::EPSILON);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn mul_add(self, a: f32, b: f32) -> f32 {
@@ -244,6 +254,7 @@ impl f32 {
     /// assert_eq!(a.div_euclid(-b), -1.0); // 7.0 >= -4.0 * -1.0
     /// assert_eq!((-a).div_euclid(-b), 2.0); // -7.0 >= -4.0 * 2.0
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn div_euclid(self, rhs: f32) -> f32 {
@@ -277,6 +288,7 @@ impl f32 {
     /// // limitation due to round-off error
     /// assert!((-f32::EPSILON).rem_euclid(3.0) != 0.0);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn rem_euclid(self, rhs: f32) -> f32 {
@@ -286,7 +298,9 @@ impl f32 {
 
     /// Raises a number to an integer power.
     ///
-    /// Using this function is generally faster than using `powf`
+    /// Using this function is generally faster than using `powf`.
+    /// It might have a different sequence of rounding operations than `powf`,
+    /// so the results are not guaranteed to agree.
     ///
     /// # Examples
     ///
@@ -296,6 +310,7 @@ impl f32 {
     ///
     /// assert!(abs_difference <= f32::EPSILON);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn powi(self, n: i32) -> f32 {
@@ -312,6 +327,7 @@ impl f32 {
     ///
     /// assert!(abs_difference <= f32::EPSILON);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn powf(self, n: f32) -> f32 {
@@ -335,6 +351,7 @@ impl f32 {
     /// assert!(negative.sqrt().is_nan());
     /// assert!(negative_zero.sqrt() == negative_zero);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn sqrt(self) -> f32 {
@@ -355,6 +372,7 @@ impl f32 {
     ///
     /// assert!(abs_difference <= f32::EPSILON);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn exp(self) -> f32 {
@@ -373,6 +391,7 @@ impl f32 {
     ///
     /// assert!(abs_difference <= f32::EPSILON);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn exp2(self) -> f32 {
@@ -393,6 +412,7 @@ impl f32 {
     ///
     /// assert!(abs_difference <= f32::EPSILON);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn ln(self) -> f32 {
@@ -415,6 +435,7 @@ impl f32 {
     ///
     /// assert!(abs_difference <= f32::EPSILON);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn log(self, base: f32) -> f32 {
@@ -433,6 +454,7 @@ impl f32 {
     ///
     /// assert!(abs_difference <= f32::EPSILON);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn log2(self) -> f32 {
@@ -454,6 +476,7 @@ impl f32 {
     ///
     /// assert!(abs_difference <= f32::EPSILON);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn log10(self) -> f32 {
@@ -477,6 +500,7 @@ impl f32 {
     /// assert!(abs_difference_x <= f32::EPSILON);
     /// assert!(abs_difference_y <= f32::EPSILON);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn abs_sub(self, other: f32) -> f32 {
@@ -495,6 +519,7 @@ impl f32 {
     ///
     /// assert!(abs_difference <= f32::EPSILON);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn cbrt(self) -> f32 {
@@ -515,6 +540,7 @@ impl f32 {
     ///
     /// assert!(abs_difference <= f32::EPSILON);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn hypot(self, other: f32) -> f32 {
@@ -532,6 +558,7 @@ impl f32 {
     ///
     /// assert!(abs_difference <= f32::EPSILON);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn sin(self) -> f32 {
@@ -549,6 +576,7 @@ impl f32 {
     ///
     /// assert!(abs_difference <= f32::EPSILON);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn cos(self) -> f32 {
@@ -565,6 +593,7 @@ impl f32 {
     ///
     /// assert!(abs_difference <= f32::EPSILON);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn tan(self) -> f32 {
@@ -585,6 +614,7 @@ impl f32 {
     ///
     /// assert!(abs_difference <= f32::EPSILON);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn asin(self) -> f32 {
@@ -605,6 +635,7 @@ impl f32 {
     ///
     /// assert!(abs_difference <= f32::EPSILON);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn acos(self) -> f32 {
@@ -624,6 +655,7 @@ impl f32 {
     ///
     /// assert!(abs_difference <= f32::EPSILON);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn atan(self) -> f32 {
@@ -656,6 +688,7 @@ impl f32 {
     /// assert!(abs_difference_1 <= f32::EPSILON);
     /// assert!(abs_difference_2 <= f32::EPSILON);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn atan2(self, other: f32) -> f32 {
@@ -677,6 +710,7 @@ impl f32 {
     /// assert!(abs_difference_0 <= f32::EPSILON);
     /// assert!(abs_difference_1 <= f32::EPSILON);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[inline]
     pub fn sin_cos(self) -> (f32, f32) {
         (self.sin(), self.cos())
@@ -696,6 +730,7 @@ impl f32 {
     ///
     /// assert!(abs_difference < 1e-10);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn exp_m1(self) -> f32 {
@@ -716,6 +751,7 @@ impl f32 {
     ///
     /// assert!(abs_difference < 1e-10);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn ln_1p(self) -> f32 {
@@ -737,6 +773,7 @@ impl f32 {
     ///
     /// assert!(abs_difference <= f32::EPSILON);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn sinh(self) -> f32 {
@@ -758,6 +795,7 @@ impl f32 {
     /// // Same result
     /// assert!(abs_difference <= f32::EPSILON);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn cosh(self) -> f32 {
@@ -779,6 +817,7 @@ impl f32 {
     ///
     /// assert!(abs_difference <= f32::EPSILON);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn tanh(self) -> f32 {
@@ -797,6 +836,7 @@ impl f32 {
     ///
     /// assert!(abs_difference <= f32::EPSILON);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn asinh(self) -> f32 {
@@ -815,6 +855,7 @@ impl f32 {
     ///
     /// assert!(abs_difference <= f32::EPSILON);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn acosh(self) -> f32 {
@@ -833,6 +874,7 @@ impl f32 {
     ///
     /// assert!(abs_difference <= 1e-5);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn atanh(self) -> f32 {
diff --git a/sgx_tstd/src/f64.rs b/sgx_tstd/src/f64.rs
index 25a5c498..b9c31894 100644
--- a/sgx_tstd/src/f64.rs
+++ b/sgx_tstd/src/f64.rs
@@ -15,7 +15,7 @@
 // specific language governing permissions and limitations
 // under the License..
 
-//! Constants specific to the `f64` double-precision floating point type.
+//! Constants for the `f64` double-precision floating point type.
 //!
 //! *[See also the `f64` primitive type](primitive@f64).*
 //!
@@ -28,6 +28,7 @@
 
 #![allow(missing_docs)]
 
+
 use crate::intrinsics;
 use crate::sys::cmath;
 
@@ -37,9 +38,8 @@ pub use core::f64::{
     MIN_EXP, MIN_POSITIVE, NAN, NEG_INFINITY, RADIX,
 };
 
-#[lang = "f64_runtime"]
 impl f64 {
-    /// Returns the largest integer less than or equal to a number.
+    /// Returns the largest integer less than or equal to `self`.
     ///
     /// # Examples
     ///
@@ -52,13 +52,14 @@ impl f64 {
     /// assert_eq!(g.floor(), 3.0);
     /// assert_eq!(h.floor(), -4.0);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn floor(self) -> f64 {
         unsafe { intrinsics::floorf64(self) }
     }
 
-    /// Returns the smallest integer greater than or equal to a number.
+    /// Returns the smallest integer greater than or equal to `self`.
     ///
     /// # Examples
     ///
@@ -69,13 +70,14 @@ impl f64 {
     /// assert_eq!(f.ceil(), 4.0);
     /// assert_eq!(g.ceil(), 4.0);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn ceil(self) -> f64 {
         unsafe { intrinsics::ceilf64(self) }
     }
 
-    /// Returns the nearest integer to a number. Round half-way cases away from
+    /// Returns the nearest integer to `self`. Round half-way cases away from
     /// `0.0`.
     ///
     /// # Examples
@@ -87,13 +89,15 @@ impl f64 {
     /// assert_eq!(f.round(), 3.0);
     /// assert_eq!(g.round(), -3.0);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn round(self) -> f64 {
         unsafe { intrinsics::roundf64(self) }
     }
 
-    /// Returns the integer part of a number.
+    /// Returns the integer part of `self`.
+    /// This means that non-integer numbers are always truncated towards zero.
     ///
     /// # Examples
     ///
@@ -106,13 +110,14 @@ impl f64 {
     /// assert_eq!(g.trunc(), 3.0);
     /// assert_eq!(h.trunc(), -3.0);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn trunc(self) -> f64 {
         unsafe { intrinsics::truncf64(self) }
     }
 
-    /// Returns the fractional part of a number.
+    /// Returns the fractional part of `self`.
     ///
     /// # Examples
     ///
@@ -125,14 +130,14 @@ impl f64 {
     /// assert!(abs_difference_x < 1e-10);
     /// assert!(abs_difference_y < 1e-10);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn fract(self) -> f64 {
         self - self.trunc()
     }
 
-    /// Computes the absolute value of `self`. Returns `NAN` if the
-    /// number is `NAN`.
+    /// Computes the absolute value of `self`.
     ///
     /// # Examples
     ///
@@ -148,6 +153,7 @@ impl f64 {
     ///
     /// assert!(f64::NAN.abs().is_nan());
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn abs(self) -> f64 {
@@ -158,7 +164,7 @@ impl f64 {
     ///
     /// - `1.0` if the number is positive, `+0.0` or `INFINITY`
     /// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
-    /// - `NAN` if the number is `NAN`
+    /// - NaN if the number is NaN
     ///
     /// # Examples
     ///
@@ -170,6 +176,7 @@ impl f64 {
     ///
     /// assert!(f64::NAN.signum().is_nan());
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn signum(self) -> f64 {
@@ -180,8 +187,10 @@ impl f64 {
     /// `sign`.
     ///
     /// Equal to `self` if the sign of `self` and `sign` are the same, otherwise
-    /// equal to `-self`. If `self` is a `NAN`, then a `NAN` with the sign of
-    /// `sign` is returned.
+    /// equal to `-self`. If `self` is a NaN, then a NaN with the sign bit of
+    /// `sign` is returned. Note, however, that conserving the sign bit on NaN
+    /// across arithmetical operations is not generally guaranteed.
+    /// See [explanation of NaN as a special value](primitive@f32) for more info.
     ///
     /// # Examples
     ///
@@ -195,6 +204,7 @@ impl f64 {
     ///
     /// assert!(f64::NAN.copysign(1.0).is_nan());
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn copysign(self, sign: f64) -> f64 {
@@ -221,6 +231,7 @@ impl f64 {
     ///
     /// assert!(abs_difference < 1e-10);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn mul_add(self, a: f64, b: f64) -> f64 {
@@ -244,6 +255,7 @@ impl f64 {
     /// assert_eq!(a.div_euclid(-b), -1.0); // 7.0 >= -4.0 * -1.0
     /// assert_eq!((-a).div_euclid(-b), 2.0); // -7.0 >= -4.0 * 2.0
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn div_euclid(self, rhs: f64) -> f64 {
@@ -277,6 +289,7 @@ impl f64 {
     /// // limitation due to round-off error
     /// assert!((-f64::EPSILON).rem_euclid(3.0) != 0.0);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn rem_euclid(self, rhs: f64) -> f64 {
@@ -286,7 +299,9 @@ impl f64 {
 
     /// Raises a number to an integer power.
     ///
-    /// Using this function is generally faster than using `powf`
+    /// Using this function is generally faster than using `powf`.
+    /// It might have a different sequence of rounding operations than `powf`,
+    /// so the results are not guaranteed to agree.
     ///
     /// # Examples
     ///
@@ -296,6 +311,7 @@ impl f64 {
     ///
     /// assert!(abs_difference < 1e-10);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn powi(self, n: i32) -> f64 {
@@ -312,6 +328,7 @@ impl f64 {
     ///
     /// assert!(abs_difference < 1e-10);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn powf(self, n: f64) -> f64 {
@@ -335,6 +352,7 @@ impl f64 {
     /// assert!(negative.sqrt().is_nan());
     /// assert!(negative_zero.sqrt() == negative_zero);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn sqrt(self) -> f64 {
@@ -355,6 +373,7 @@ impl f64 {
     ///
     /// assert!(abs_difference < 1e-10);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn exp(self) -> f64 {
@@ -373,6 +392,7 @@ impl f64 {
     ///
     /// assert!(abs_difference < 1e-10);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn exp2(self) -> f64 {
@@ -393,6 +413,7 @@ impl f64 {
     ///
     /// assert!(abs_difference < 1e-10);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn ln(self) -> f64 {
@@ -415,6 +436,7 @@ impl f64 {
     ///
     /// assert!(abs_difference < 1e-10);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn log(self, base: f64) -> f64 {
@@ -433,6 +455,7 @@ impl f64 {
     ///
     /// assert!(abs_difference < 1e-10);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn log2(self) -> f64 {
@@ -456,6 +479,7 @@ impl f64 {
     ///
     /// assert!(abs_difference < 1e-10);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn log10(self) -> f64 {
@@ -479,6 +503,7 @@ impl f64 {
     /// assert!(abs_difference_x < 1e-10);
     /// assert!(abs_difference_y < 1e-10);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn abs_sub(self, other: f64) -> f64 {
@@ -497,6 +522,7 @@ impl f64 {
     ///
     /// assert!(abs_difference < 1e-10);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn cbrt(self) -> f64 {
@@ -517,6 +543,7 @@ impl f64 {
     ///
     /// assert!(abs_difference < 1e-10);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn hypot(self, other: f64) -> f64 {
@@ -534,6 +561,7 @@ impl f64 {
     ///
     /// assert!(abs_difference < 1e-10);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn sin(self) -> f64 {
@@ -551,6 +579,7 @@ impl f64 {
     ///
     /// assert!(abs_difference < 1e-10);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn cos(self) -> f64 {
@@ -567,6 +596,7 @@ impl f64 {
     ///
     /// assert!(abs_difference < 1e-14);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn tan(self) -> f64 {
@@ -587,6 +617,7 @@ impl f64 {
     ///
     /// assert!(abs_difference < 1e-10);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn asin(self) -> f64 {
@@ -607,6 +638,7 @@ impl f64 {
     ///
     /// assert!(abs_difference < 1e-10);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn acos(self) -> f64 {
@@ -626,6 +658,7 @@ impl f64 {
     ///
     /// assert!(abs_difference < 1e-10);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn atan(self) -> f64 {
@@ -658,6 +691,7 @@ impl f64 {
     /// assert!(abs_difference_1 < 1e-10);
     /// assert!(abs_difference_2 < 1e-10);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn atan2(self, other: f64) -> f64 {
@@ -679,6 +713,7 @@ impl f64 {
     /// assert!(abs_difference_0 < 1e-10);
     /// assert!(abs_difference_1 < 1e-10);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[inline]
     pub fn sin_cos(self) -> (f64, f64) {
         (self.sin(), self.cos())
@@ -698,6 +733,7 @@ impl f64 {
     ///
     /// assert!(abs_difference < 1e-20);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn exp_m1(self) -> f64 {
@@ -718,6 +754,7 @@ impl f64 {
     ///
     /// assert!(abs_difference < 1e-20);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn ln_1p(self) -> f64 {
@@ -739,6 +776,7 @@ impl f64 {
     ///
     /// assert!(abs_difference < 1e-10);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn sinh(self) -> f64 {
@@ -760,6 +798,7 @@ impl f64 {
     /// // Same result
     /// assert!(abs_difference < 1.0e-10);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn cosh(self) -> f64 {
@@ -781,6 +820,7 @@ impl f64 {
     ///
     /// assert!(abs_difference < 1.0e-10);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn tanh(self) -> f64 {
@@ -799,6 +839,7 @@ impl f64 {
     ///
     /// assert!(abs_difference < 1.0e-10);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn asinh(self) -> f64 {
@@ -817,6 +858,7 @@ impl f64 {
     ///
     /// assert!(abs_difference < 1.0e-10);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn acosh(self) -> f64 {
@@ -835,6 +877,7 @@ impl f64 {
     ///
     /// assert!(abs_difference < 1.0e-10);
     /// ```
+    #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
     pub fn atanh(self) -> f64 {
@@ -845,6 +888,7 @@ impl f64 {
     // because of their non-standard behavior (e.g., log(-n) returns -Inf instead
     // of expected NaN).
     #[allow(clippy::if_same_then_else)]
+    #[rustc_allow_incoherent_impl]
     fn log_wrapper<F: Fn(f64) -> f64>(self, log_fn: F) -> f64 {
         if !cfg!(any(target_os = "solaris", target_os = "illumos")) {
             log_fn(self)
diff --git a/sgx_tstd/src/ffi/c_str.rs b/sgx_tstd/src/ffi/c_str.rs
deleted file mode 100644
index 6ecdabd1..00000000
--- a/sgx_tstd/src/ffi/c_str.rs
+++ /dev/null
@@ -1,55 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License.  You may obtain a copy of the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied.  See the License for the
-// specific language governing permissions and limitations
-// under the License..
-
-pub use sgx_trts::c_str::*;
-
-use crate::error::Error;
-use crate::io;
-
-impl Error for NulError {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        "nul byte found in data"
-    }
-}
-
-impl From<NulError> for io::Error {
-    /// Converts a [`NulError`] into a [`io::Error`].
-    fn from(_: NulError) -> io::Error {
-        io::const_io_error!(io::ErrorKind::InvalidInput, "data provided contains a nul byte")
-    }
-}
-
-impl Error for FromBytesWithNulError {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        self.__description()
-    }
-}
-
-impl Error for FromVecWithNulError {}
-
-impl Error for IntoStringError {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        self.__description()
-    }
-
-    fn source(&self) -> Option<&(dyn Error + 'static)> {
-        Some(self.__source())
-    }
-}
diff --git a/sgx_tstd/src/ffi/mod.rs b/sgx_tstd/src/ffi/mod.rs
index 1c6152af..7e72f121 100644
--- a/sgx_tstd/src/ffi/mod.rs
+++ b/sgx_tstd/src/ffi/mod.rs
@@ -121,7 +121,7 @@
 //! On Unix, [`OsStr`] implements the
 //! <code>std::os::unix::ffi::[OsStrExt][unix.OsStrExt]</code> trait, which
 //! augments it with two methods, [`from_bytes`] and [`as_bytes`].
-//! These do inexpensive conversions from and to UTF-8 byte slices.
+//! These do inexpensive conversions from and to byte slices.
 //!
 //! Additionally, on Unix [`OsString`] implements the
 //! <code>std::os::unix::ffi::[OsStringExt][unix.OsStringExt]</code> trait,
@@ -161,13 +161,18 @@
 //! [windows.OsStringExt]: crate::os::windows::ffi::OsStringExt "os::windows::ffi::OsStringExt"
 //! [`from_wide`]: crate::os::windows::ffi::OsStringExt::from_wide "os::windows::ffi::OsStringExt::from_wide"
 
-pub use self::c_str::FromBytesWithNulError;
-pub use self::c_str::FromVecWithNulError;
-pub use self::c_str::{CStr, CString, IntoStringError, NulError};
+pub use alloc_crate::ffi::{CString, FromVecWithNulError, IntoStringError, NulError};
+pub use core::ffi::{CStr, FromBytesWithNulError};
+
 pub use self::os_str::{OsStr, OsString};
 
+pub use core::ffi::{
+    c_char, c_double, c_float, c_int, c_long, c_longlong, c_schar, c_short, c_uchar, c_uint,
+    c_ulong, c_ulonglong, c_ushort,
+};
+
 pub use core::ffi::c_void;
+
 pub use core::ffi::{VaList, VaListImpl};
 
-mod c_str;
 mod os_str;
diff --git a/sgx_tstd/src/ffi/os_str.rs b/sgx_tstd/src/ffi/os_str.rs
index 8dc3d034..0a44c5ba 100644
--- a/sgx_tstd/src/ffi/os_str.rs
+++ b/sgx_tstd/src/ffi/os_str.rs
@@ -22,7 +22,7 @@ use crate::cmp;
 use crate::collections::TryReserveError;
 use crate::fmt;
 use crate::hash::{Hash, Hasher};
-use crate::iter::{Extend, FromIterator};
+use crate::iter::Extend;
 use crate::ops;
 use crate::rc::Rc;
 use crate::str::FromStr;
@@ -61,6 +61,22 @@ use crate::sys_common::{AsInner, FromInner, IntoInner};
 /// values, encoded in a less-strict variant of UTF-8. This is useful to
 /// understand when handling capacity and length values.
 ///
+/// # Capacity of `OsString`
+///
+/// Capacity uses units of UTF-8 bytes for OS strings which were created from valid unicode, and
+/// uses units of bytes in an unspecified encoding for other contents. On a given target, all
+/// `OsString` and `OsStr` values use the same units for capacity, so the following will work:
+/// ```
+/// use std::ffi::{OsStr, OsString};
+///
+/// fn concat_os_strings(a: &OsStr, b: &OsStr) -> OsString {
+///     let mut ret = OsString::with_capacity(a.len() + b.len()); // This will allocate
+///     ret.push(a); // This will not allocate further
+///     ret.push(b); // This will not allocate further
+///     ret
+/// }
+/// ```
+///
 /// # Creating an `OsString`
 ///
 /// **From a Rust string**: `OsString` implements
@@ -188,13 +204,14 @@ impl OsString {
         self.inner.push_slice(&s.as_ref().inner)
     }
 
-    /// Creates a new `OsString` with the given capacity.
+    /// Creates a new `OsString` with at least the given capacity.
     ///
-    /// The string will be able to hold exactly `capacity` length units of other
-    /// OS strings without reallocating. If `capacity` is 0, the string will not
+    /// The string will be able to hold at least `capacity` length units of other
+    /// OS strings without reallocating. This method is allowed to allocate for
+    /// more units than `capacity`. If `capacity` is 0, the string will not
     /// allocate.
     ///
-    /// See main `OsString` documentation information about encoding.
+    /// See the main `OsString` documentation information about encoding and capacity units.
     ///
     /// # Examples
     ///
@@ -235,7 +252,7 @@ impl OsString {
 
     /// Returns the capacity this `OsString` can hold without reallocating.
     ///
-    /// See `OsString` introduction for information about encoding.
+    /// See the main `OsString` documentation information about encoding and capacity units.
     ///
     /// # Examples
     ///
@@ -252,9 +269,12 @@ impl OsString {
     }
 
     /// Reserves capacity for at least `additional` more capacity to be inserted
-    /// in the given `OsString`.
+    /// in the given `OsString`. Does nothing if the capacity is
+    /// already sufficient.
+    ///
+    /// The collection may reserve more space to speculatively avoid frequent reallocations.
     ///
-    /// The collection may reserve more space to avoid frequent reallocations.
+    /// See the main `OsString` documentation information about encoding and capacity units.
     ///
     /// # Examples
     ///
@@ -271,10 +291,13 @@ impl OsString {
     }
 
     /// Tries to reserve capacity for at least `additional` more length units
-    /// in the given `OsString`. The string may reserve more space to avoid
+    /// in the given `OsString`. The string may reserve more space to speculatively avoid
     /// frequent reallocations. After calling `try_reserve`, capacity will be
-    /// greater than or equal to `self.len() + additional`. Does nothing if
-    /// capacity is already sufficient.
+    /// greater than or equal to `self.len() + additional` if it returns `Ok(())`.
+    /// Does nothing if capacity is already sufficient. This method preserves
+    /// the contents even if an error occurs.
+    ///
+    /// See the main `OsString` documentation information about encoding and capacity units.
     ///
     /// # Errors
     ///
@@ -284,7 +307,6 @@ impl OsString {
     /// # Examples
     ///
     /// ```
-    /// #![feature(try_reserve_2)]
     /// use std::ffi::{OsStr, OsString};
     /// use std::collections::TryReserveError;
     ///
@@ -306,7 +328,7 @@ impl OsString {
         self.inner.try_reserve(additional)
     }
 
-    /// Reserves the minimum capacity for exactly `additional` more capacity to
+    /// Reserves the minimum capacity for at least `additional` more capacity to
     /// be inserted in the given `OsString`. Does nothing if the capacity is
     /// already sufficient.
     ///
@@ -316,6 +338,8 @@ impl OsString {
     ///
     /// [`reserve`]: OsString::reserve
     ///
+    /// See the main `OsString` documentation information about encoding and capacity units.
+    ///
     /// # Examples
     ///
     /// ```
@@ -330,7 +354,7 @@ impl OsString {
         self.inner.reserve_exact(additional)
     }
 
-    /// Tries to reserve the minimum capacity for exactly `additional`
+    /// Tries to reserve the minimum capacity for at least `additional`
     /// more length units in the given `OsString`. After calling
     /// `try_reserve_exact`, capacity will be greater than or equal to
     /// `self.len() + additional` if it returns `Ok(())`.
@@ -342,6 +366,8 @@ impl OsString {
     ///
     /// [`try_reserve`]: OsString::try_reserve
     ///
+    /// See the main `OsString` documentation information about encoding and capacity units.
+    ///
     /// # Errors
     ///
     /// If the capacity overflows, or the allocator reports a failure, then an error
@@ -350,7 +376,6 @@ impl OsString {
     /// # Examples
     ///
     /// ```
-    /// #![feature(try_reserve_2)]
     /// use std::ffi::{OsStr, OsString};
     /// use std::collections::TryReserveError;
     ///
@@ -374,6 +399,8 @@ impl OsString {
 
     /// Shrinks the capacity of the `OsString` to match its length.
     ///
+    /// See the main `OsString` documentation information about encoding and capacity units.
+    ///
     /// # Examples
     ///
     /// ```
@@ -399,6 +426,8 @@ impl OsString {
     ///
     /// If the current capacity is less than the lower limit, this is a no-op.
     ///
+    /// See the main `OsString` documentation information about encoding and capacity units.
+    ///
     /// # Examples
     ///
     /// ```
@@ -594,6 +623,13 @@ impl Hash for OsString {
     }
 }
 
+impl fmt::Write for OsString {
+    fn write_str(&mut self, s: &str) -> fmt::Result {
+        self.push(s);
+        Ok(())
+    }
+}
+
 impl OsStr {
     /// Coerces into an `OsStr` slice.
     ///
@@ -747,6 +783,8 @@ impl OsStr {
     /// This number is simply useful for passing to other methods, like
     /// [`OsString::with_capacity`] to avoid reallocations.
     ///
+    /// See the main `OsString` documentation information about encoding and capacity units.
+    ///
     /// # Examples
     ///
     /// ```
@@ -1160,6 +1198,22 @@ impl OsStr {
     }
 }
 
+impl<S: Borrow<OsStr>> alloc_crate::slice::Join<&OsStr> for [S] {
+    type Output = OsString;
+
+    fn join(slice: &Self, sep: &OsStr) -> OsString {
+        let Some((first, suffix)) = slice.split_first() else {
+            return OsString::new();
+        };
+        let first_owned = first.borrow().to_owned();
+        suffix.iter().fold(first_owned, |mut a, b| {
+            a.push(sep);
+            a.push(b.borrow());
+            a
+        })
+    }
+}
+
 impl Borrow<OsStr> for OsString {
     #[inline]
     fn borrow(&self) -> &OsStr {
diff --git a/sgx_tstd/src/fs.rs b/sgx_tstd/src/fs.rs
index cbac797c..c7633e25 100644
--- a/sgx_tstd/src/fs.rs
+++ b/sgx_tstd/src/fs.rs
@@ -20,7 +20,7 @@
 #![deny(unsafe_op_in_unsafe_fn)]
 use crate::ffi::OsString;
 use crate::fmt;
-use crate::io::{self, IoSlice, IoSliceMut, Read, ReadBuf, Seek, SeekFrom, Write};
+use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, Read, Seek, SeekFrom, Write};
 use crate::path::{Path, PathBuf};
 use crate::sys::fs as fs_imp;
 use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
@@ -28,7 +28,7 @@ use crate::time::SystemTime;
 #[cfg(not(feature = "untrusted_fs"))]
 use crate::untrusted::path::PathEx;
 
-/// A reference to an open file on the filesystem.
+/// An object providing access to an open file on the filesystem.
 ///
 /// An instance of a `File` can be read and/or written depending on what options
 /// it was opened with. Files also implement [`Seek`] to alter the logical cursor
@@ -94,6 +94,12 @@ use crate::untrusted::path::PathEx;
 /// by different processes. Avoid assuming that holding a `&File` means that the
 /// file will not change.
 ///
+/// # Platform-specific behavior
+///
+/// On Windows, the implementation of [`Read`] and [`Write`] traits for `File`
+/// perform synchronous I/O operations. Therefore the underlying file must not
+/// have been opened for asynchronous I/O (e.g. by using `FILE_FLAG_OVERLAPPED`).
+///
 /// [`BufReader<R>`]: io::BufReader
 /// [`sync_all`]: File::sync_all
 #[cfg_attr(not(test), rustc_diagnostic_item = "File")]
@@ -132,6 +138,16 @@ pub struct ReadDir(fs_imp::ReadDir);
 /// An instance of `DirEntry` represents an entry inside of a directory on the
 /// filesystem. Each entry can be inspected via methods to learn about the full
 /// path or possibly other metadata through per-platform extension traits.
+///
+/// # Platform-specific behavior
+///
+/// On Unix, the `DirEntry` struct contains an internal reference to the open
+/// directory. Holding `DirEntry` objects will consume a file handle even
+/// after the `ReadDir` iterator is dropped.
+///
+/// Note that this [may change in the future][changes].
+///
+/// [changes]: io#platform-specific-behavior
 pub struct DirEntry(fs_imp::DirEntry);
 
 /// Options and flags which can be used to configure how a file is opened.
@@ -172,6 +188,10 @@ pub struct DirEntry(fs_imp::DirEntry);
 #[derive(Clone, Debug)]
 pub struct OpenOptions(fs_imp::OpenOptions);
 
+/// Representation of the various timestamps on a file.
+#[derive(Copy, Clone, Debug, Default)]
+pub struct FileTimes(fs_imp::FileTimes);
+
 /// Representation of the various permissions on a file.
 ///
 /// This module only currently provides one bit of information,
@@ -278,6 +298,9 @@ pub fn read_to_string<P: AsRef<Path>>(path: P) -> io::Result<String> {
 /// This function will create a file if it does not exist,
 /// and will entirely replace its contents if it does.
 ///
+/// Depending on the platform, this function may fail if the
+/// full directory path does not exist.
+///
 /// This is a convenience function for using [`File::create`] and [`write_all`]
 /// with fewer imports.
 ///
@@ -330,6 +353,9 @@ impl File {
     /// This function will create a file if it does not exist,
     /// and will truncate it if it does.
     ///
+    /// Depending on the platform, this function may fail if the
+    /// full directory path does not exist.
+    ///
     /// See the [`OpenOptions::open`] function for more details.
     ///
     /// # Examples
@@ -346,6 +372,34 @@ impl File {
         OpenOptions::new().write(true).create(true).truncate(true).open(path.as_ref())
     }
 
+    /// Creates a new file in read-write mode; error if the file exists.
+    ///
+    /// This function will create a file if it does not exist, or return an error if it does. This
+    /// way, if the call succeeds, the file returned is guaranteed to be new.
+    ///
+    /// This option is useful because it is atomic. Otherwise between checking whether a file
+    /// exists and creating a new one, the file may have been created by another process (a TOCTOU
+    /// race condition / attack).
+    ///
+    /// This can also be written using
+    /// `File::options().read(true).write(true).create_new(true).open(...)`.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// #![feature(file_create_new)]
+    ///
+    /// use std::fs::File;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let mut f = File::create_new("foo.txt")?;
+    ///     Ok(())
+    /// }
+    /// ```
+    pub fn create_new<P: AsRef<Path>>(path: P) -> io::Result<File> {
+        OpenOptions::new().read(true).write(true).create_new(true).open(path.as_ref())
+    }
+
     /// Returns a new OpenOptions object.
     ///
     /// This function returns a new OpenOptions object that you can use to
@@ -563,6 +617,53 @@ impl File {
     pub fn set_permissions(&self, perm: Permissions) -> io::Result<()> {
         self.inner.set_permissions(perm.0)
     }
+
+    /// Changes the timestamps of the underlying file.
+    ///
+    /// # Platform-specific behavior
+    ///
+    /// This function currently corresponds to the `futimens` function on Unix (falling back to
+    /// `futimes` on macOS before 10.13) and the `SetFileTime` function on Windows. Note that this
+    /// [may change in the future][changes].
+    ///
+    /// [changes]: io#platform-specific-behavior
+    ///
+    /// # Errors
+    ///
+    /// This function will return an error if the user lacks permission to change timestamps on the
+    /// underlying file. It may also return an error in other os-specific unspecified cases.
+    ///
+    /// This function may return an error if the operating system lacks support to change one or
+    /// more of the timestamps set in the `FileTimes` structure.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// #![feature(file_set_times)]
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     use std::fs::{self, File, FileTimes};
+    ///
+    ///     let src = fs::metadata("src")?;
+    ///     let dest = File::options().write(true).open("dest")?;
+    ///     let times = FileTimes::new()
+    ///         .set_accessed(src.accessed()?)
+    ///         .set_modified(src.modified()?);
+    ///     dest.set_times(times)?;
+    ///     Ok(())
+    /// }
+    /// ```
+    pub fn set_times(&self, times: FileTimes) -> io::Result<()> {
+        self.inner.set_times(times.0)
+    }
+
+    /// Changes the modification time of the underlying file.
+    ///
+    /// This is an alias for `set_times(FileTimes::new().set_modified(time))`.
+    #[inline]
+    pub fn set_modified(&self, time: SystemTime) -> io::Result<()> {
+        self.set_times(FileTimes::new().set_modified(time))
+    }
 }
 
 // In addition to the `impl`s here, `File` also has `impl`s for
@@ -611,8 +712,8 @@ impl Read for File {
         self.inner.read_vectored(bufs)
     }
 
-    fn read_buf(&mut self, buf: &mut ReadBuf<'_>) -> io::Result<()> {
-        self.inner.read_buf(buf)
+    fn read_buf(&mut self, cursor: BorrowedCursor<'_>) -> io::Result<()> {
+        self.inner.read_buf(cursor)
     }
 
     #[inline]
@@ -662,8 +763,8 @@ impl Read for &File {
         self.inner.read(buf)
     }
 
-    fn read_buf(&mut self, buf: &mut ReadBuf<'_>) -> io::Result<()> {
-        self.inner.read_buf(buf)
+    fn read_buf(&mut self, cursor: BorrowedCursor<'_>) -> io::Result<()> {
+        self.inner.read_buf(cursor)
     }
 
     fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
@@ -1094,7 +1195,7 @@ impl Metadata {
     ///     let metadata = fs::metadata("foo.txt")?;
     ///
     ///     if let Ok(time) = metadata.modified() {
-    ///         println!("{:?}", time);
+    ///         println!("{time:?}");
     ///     } else {
     ///         println!("Not supported on this platform");
     ///     }
@@ -1128,7 +1229,7 @@ impl Metadata {
     ///     let metadata = fs::metadata("foo.txt")?;
     ///
     ///     if let Ok(time) = metadata.accessed() {
-    ///         println!("{:?}", time);
+    ///         println!("{time:?}");
     ///     } else {
     ///         println!("Not supported on this platform");
     ///     }
@@ -1159,7 +1260,7 @@ impl Metadata {
     ///     let metadata = fs::metadata("foo.txt")?;
     ///
     ///     if let Ok(time) = metadata.created() {
-    ///         println!("{:?}", time);
+    ///         println!("{time:?}");
     ///     } else {
     ///         println!("Not supported on this platform or filesystem");
     ///     }
@@ -1197,6 +1298,27 @@ impl FromInner<fs_imp::FileAttr> for Metadata {
     }
 }
 
+impl FileTimes {
+    /// Create a new `FileTimes` with no times set.
+    ///
+    /// Using the resulting `FileTimes` in [`File::set_times`] will not modify any timestamps.
+    pub fn new() -> Self {
+        Self::default()
+    }
+
+    /// Set the last access time of a file.
+    pub fn set_accessed(mut self, t: SystemTime) -> Self {
+        self.0.set_accessed(t.into_inner());
+        self
+    }
+
+    /// Set the last modified time of a file.
+    pub fn set_modified(mut self, t: SystemTime) -> Self {
+        self.0.set_modified(t.into_inner());
+        self
+    }
+}
+
 impl Permissions {
     /// Returns `true` if these permissions describe a readonly (unwritable) file.
     ///
@@ -1559,7 +1681,7 @@ pub fn remove_file<P: AsRef<Path>>(path: P) -> io::Result<()> {
 /// # Platform-specific behavior
 ///
 /// This function currently corresponds to the `stat` function on Unix
-/// and the `GetFileAttributesEx` function on Windows.
+/// and the `GetFileInformationByHandle` function on Windows.
 /// Note that, this [may change in the future][changes].
 ///
 /// [changes]: io#platform-specific-behavior
@@ -1592,7 +1714,7 @@ pub fn metadata<P: AsRef<Path>>(path: P) -> io::Result<Metadata> {
 /// # Platform-specific behavior
 ///
 /// This function currently corresponds to the `lstat` function on Unix
-/// and the `GetFileAttributesEx` function on Windows.
+/// and the `GetFileInformationByHandle` function on Windows.
 /// Note that, this [may change in the future][changes].
 ///
 /// [changes]: io#platform-specific-behavior
@@ -1681,11 +1803,17 @@ pub fn rename<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> io::Result<()>
 /// This function currently corresponds to the `open` function in Unix
 /// with `O_RDONLY` for `from` and `O_WRONLY`, `O_CREAT`, and `O_TRUNC` for `to`.
 /// `O_CLOEXEC` is set for returned file descriptors.
+///
+/// On Linux (including Android), this function attempts to use `copy_file_range(2)`,
+/// and falls back to reading and writing if that is not possible.
+///
 /// On Windows, this function currently corresponds to `CopyFileEx`. Alternate
 /// NTFS streams are copied but only the size of the main stream is returned by
-/// this function. On MacOS, this function corresponds to `fclonefileat` and
-/// `fcopyfile`.
-/// Note that, this [may change in the future][changes].
+/// this function.
+///
+/// On MacOS, this function corresponds to `fclonefileat` and `fcopyfile`.
+///
+/// Note that platform-specific behavior [may change in the future][changes].
 ///
 /// [changes]: io#platform-specific-behavior
 ///
@@ -1988,9 +2116,10 @@ pub fn remove_dir<P: AsRef<Path>>(path: P) -> io::Result<()> {
 ///
 /// [changes]: io#platform-specific-behavior
 ///
-/// On macOS before version 10.10 and REDOX this function is not protected against time-of-check to
-/// time-of-use (TOCTOU) race conditions, and should not be used in security-sensitive code on
-/// those platforms. All other platforms are protected.
+/// On macOS before version 10.10 and REDOX, as well as when running in Miri for any target, this
+/// function is not protected against time-of-check to time-of-use (TOCTOU) race conditions, and
+/// should not be used in security-sensitive code on those platforms. All other platforms are
+/// protected.
 ///
 /// # Errors
 ///
@@ -2225,10 +2354,14 @@ impl AsInnerMut<fs_imp::DirBuilder> for DirBuilder {
 /// unrelated to the path not existing. (E.g. it will return `Err(_)` in case of permission
 /// denied on some of the parent directories.)
 ///
+/// Note that while this avoids some pitfalls of the `exists()` method, it still can not
+/// prevent time-of-check to time-of-use (TOCTOU) bugs. You should only use it in scenarios
+/// where those bugs are not an issue.
+///
 /// # Examples
 ///
 /// ```no_run
-/// #![feature(path_try_exists)]
+/// #![feature(fs_try_exists)]
 /// use std::fs;
 ///
 /// assert!(!fs::try_exists("does_not_exist.txt").expect("Can't check existence of file does_not_exist.txt"));
diff --git a/sgx_tstd/src/io/buffered/bufreader.rs b/sgx_tstd/src/io/buffered/bufreader.rs
index cd0795fb..5b8c50bb 100644
--- a/sgx_tstd/src/io/buffered/bufreader.rs
+++ b/sgx_tstd/src/io/buffered/bufreader.rs
@@ -15,12 +15,13 @@
 // specific language governing permissions and limitations
 // under the License..
 
-use crate::cmp;
+mod buffer;
+
 use crate::fmt;
 use crate::io::{
-    self, BufRead, IoSliceMut, Read, ReadBuf, Seek, SeekFrom, SizeHint, DEFAULT_BUF_SIZE,
+    self, BorrowedCursor, BufRead, IoSliceMut, Read, Seek, SeekFrom, SizeHint, DEFAULT_BUF_SIZE,
 };
-use crate::mem::MaybeUninit;
+use buffer::Buffer;
 
 /// The `BufReader<R>` struct adds buffering to any reader.
 ///
@@ -58,16 +59,13 @@ use crate::mem::MaybeUninit;
 ///
 ///     let mut line = String::new();
 ///     let len = reader.read_line(&mut line)?;
-///     println!("First line is {} bytes long", len);
+///     println!("First line is {len} bytes long");
 ///     Ok(())
 /// }
 /// ```
 pub struct BufReader<R> {
     inner: R,
-    buf: Box<[MaybeUninit<u8>]>,
-    pos: usize,
-    cap: usize,
-    init: usize,
+    buf: Buffer,
 }
 
 impl<R: Read> BufReader<R> {
@@ -107,8 +105,7 @@ impl<R: Read> BufReader<R> {
     /// }
     /// ```
     pub fn with_capacity(capacity: usize, inner: R) -> BufReader<R> {
-        let buf = Box::new_uninit_slice(capacity);
-        BufReader { inner, buf, pos: 0, cap: 0, init: 0 }
+        BufReader { inner, buf: Buffer::with_capacity(capacity) }
     }
 }
 
@@ -181,8 +178,7 @@ impl<R> BufReader<R> {
     /// }
     /// ```
     pub fn buffer(&self) -> &[u8] {
-        // SAFETY: self.cap is always <= self.init, so self.buf[self.pos..self.cap] is always init
-        unsafe { MaybeUninit::slice_assume_init_ref(&self.buf[self.pos..self.cap]) }
+        self.buf.buffer()
     }
 
     /// Returns the number of bytes the internal buffer can hold at once.
@@ -204,7 +200,7 @@ impl<R> BufReader<R> {
     /// }
     /// ```
     pub fn capacity(&self) -> usize {
-        self.buf.len()
+        self.buf.capacity()
     }
 
     /// Unwraps this `BufReader<R>`, returning the underlying reader.
@@ -233,8 +229,15 @@ impl<R> BufReader<R> {
     /// Invalidates all data in the internal buffer.
     #[inline]
     fn discard_buffer(&mut self) {
-        self.pos = 0;
-        self.cap = 0;
+        self.buf.discard_buffer()
+    }
+}
+
+// This is only used by a test which asserts that the initialization-tracking is correct.
+#[cfg(feature = "unit_test")]
+impl<R> BufReader<R> {
+    pub fn initialized(&self) -> usize {
+        self.buf.initialized()
     }
 }
 
@@ -243,17 +246,17 @@ impl<R: Seek> BufReader<R> {
     /// the buffer will not be flushed, allowing for more efficient seeks.
     /// This method does not return the location of the underlying reader, so the caller
     /// must track this information themselves if it is required.
-    #[allow(clippy::collapsible_else_if)]
+    #[allow(clippy::redundant_pattern_matching)]
     pub fn seek_relative(&mut self, offset: i64) -> io::Result<()> {
-        let pos = self.pos as u64;
+        let pos = self.buf.pos() as u64;
         if offset < 0 {
-            if let Some(new_pos) = pos.checked_sub((-offset) as u64) {
-                self.pos = new_pos as usize;
+            if let Some(_) = pos.checked_sub((-offset) as u64) {
+                self.buf.unconsume((-offset) as usize);
                 return Ok(());
             }
         } else if let Some(new_pos) = pos.checked_add(offset as u64) {
-            if new_pos <= self.cap as u64 {
-                self.pos = new_pos as usize;
+            if new_pos <= self.buf.filled() as u64 {
+                self.buf.consume(offset as usize);
                 return Ok(());
             }
         }
@@ -267,7 +270,7 @@ impl<R: Read> Read for BufReader<R> {
         // If we don't have any buffered data and we're doing a massive read
         // (larger than our internal buffer), bypass our internal buffer
         // entirely.
-        if self.pos == self.cap && buf.len() >= self.buf.len() {
+        if self.buf.pos() == self.buf.filled() && buf.len() >= self.capacity() {
             self.discard_buffer();
             return self.inner.read(buf);
         }
@@ -279,21 +282,21 @@ impl<R: Read> Read for BufReader<R> {
         Ok(nread)
     }
 
-    fn read_buf(&mut self, buf: &mut ReadBuf<'_>) -> io::Result<()> {
+    fn read_buf(&mut self, mut cursor: BorrowedCursor<'_>) -> io::Result<()> {
         // If we don't have any buffered data and we're doing a massive read
         // (larger than our internal buffer), bypass our internal buffer
         // entirely.
-        if self.pos == self.cap && buf.remaining() >= self.buf.len() {
+        if self.buf.pos() == self.buf.filled() && cursor.capacity() >= self.capacity() {
             self.discard_buffer();
-            return self.inner.read_buf(buf);
+            return self.inner.read_buf(cursor);
         }
 
-        let prev = buf.filled_len();
+        let prev = cursor.written();
 
         let mut rem = self.fill_buf()?;
-        rem.read_buf(buf)?;
+        rem.read_buf(cursor.reborrow())?;
 
-        self.consume(buf.filled_len() - prev); //slice impl of read_buf known to never unfill buf
+        self.consume(cursor.written() - prev); //slice impl of read_buf known to never unfill buf
 
         Ok(())
     }
@@ -303,9 +306,7 @@ impl<R: Read> Read for BufReader<R> {
     // generation for the common path where the buffer has enough bytes to fill the passed-in
     // buffer.
     fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
-        if self.buffer().len() >= buf.len() {
-            buf.copy_from_slice(&self.buffer()[..buf.len()]);
-            self.consume(buf.len());
+        if self.buf.consume_with(buf.len(), |claimed| buf.copy_from_slice(claimed)) {
             return Ok(());
         }
 
@@ -314,7 +315,7 @@ impl<R: Read> Read for BufReader<R> {
 
     fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
         let total_len = bufs.iter().map(|b| b.len()).sum::<usize>();
-        if self.pos == self.cap && total_len >= self.buf.len() {
+        if self.buf.pos() == self.buf.filled() && total_len >= self.capacity() {
             self.discard_buffer();
             return self.inner.read_vectored(bufs);
         }
@@ -333,8 +334,9 @@ impl<R: Read> Read for BufReader<R> {
     // The inner reader might have an optimized `read_to_end`. Drain our buffer and then
     // delegate to the inner implementation.
     fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
-        let nread = self.cap - self.pos;
-        buf.extend_from_slice(self.buffer());
+        let inner_buf = self.buffer();
+        buf.extend_from_slice(inner_buf);
+        let nread = inner_buf.len();
         self.discard_buffer();
         Ok(nread + self.inner.read_to_end(buf)?)
     }
@@ -378,33 +380,11 @@ impl<R: Read> Read for BufReader<R> {
 
 impl<R: Read> BufRead for BufReader<R> {
     fn fill_buf(&mut self) -> io::Result<&[u8]> {
-        // If we've reached the end of our internal buffer then we need to fetch
-        // some more data from the underlying reader.
-        // Branch using `>=` instead of the more correct `==`
-        // to tell the compiler that the pos..cap slice is always valid.
-        if self.pos >= self.cap {
-            debug_assert!(self.pos == self.cap);
-
-            let mut readbuf = ReadBuf::uninit(&mut self.buf);
-
-            // SAFETY: `self.init` is either 0 or set to `readbuf.initialized_len()`
-            // from the last time this function was called
-            unsafe {
-                readbuf.assume_init(self.init);
-            }
-
-            self.inner.read_buf(&mut readbuf)?;
-
-            self.cap = readbuf.filled_len();
-            self.init = readbuf.initialized_len();
-
-            self.pos = 0;
-        }
-        Ok(self.buffer())
+        self.buf.fill_buf(&mut self.inner)
     }
 
     fn consume(&mut self, amt: usize) {
-        self.pos = cmp::min(self.pos + amt, self.cap);
+        self.buf.consume(amt)
     }
 }
 
@@ -415,7 +395,10 @@ where
     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
         fmt.debug_struct("BufReader")
             .field("reader", &self.inner)
-            .field("buffer", &format_args!("{}/{}", self.cap - self.pos, self.buf.len()))
+            .field(
+                "buffer",
+                &format_args!("{}/{}", self.buf.filled() - self.buf.pos(), self.capacity()),
+            )
             .finish()
     }
 }
@@ -446,7 +429,7 @@ impl<R: Seek> Seek for BufReader<R> {
     fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
         let result: u64;
         if let SeekFrom::Current(n) = pos {
-            let remainder = (self.cap - self.pos) as i64;
+            let remainder = (self.buf.filled() - self.buf.pos()) as i64;
             // it should be safe to assume that remainder fits within an i64 as the alternative
             // means we managed to allocate 8 exbibytes and that's absurd.
             // But it's not out of the realm of possibility for some weird underlying reader to
@@ -504,7 +487,7 @@ impl<R: Seek> Seek for BufReader<R> {
     /// }
     /// ```
     fn stream_position(&mut self) -> io::Result<u64> {
-        let remainder = (self.cap - self.pos) as u64;
+        let remainder = (self.buf.filled() - self.buf.pos()) as u64;
         self.inner.stream_position().map(|pos| {
             pos.checked_sub(remainder).expect(
                 "overflow when subtracting remaining buffer size from inner stream position",
diff --git a/sgx_tstd/src/io/buffered/bufreader/buffer.rs b/sgx_tstd/src/io/buffered/bufreader/buffer.rs
new file mode 100644
index 00000000..d3293bab
--- /dev/null
+++ b/sgx_tstd/src/io/buffered/bufreader/buffer.rs
@@ -0,0 +1,139 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License..
+
+///! An encapsulation of `BufReader`'s buffer management logic.
+///
+/// This module factors out the basic functionality of `BufReader` in order to protect two core
+/// invariants:
+/// * `filled` bytes of `buf` are always initialized
+/// * `pos` is always <= `filled`
+/// Since this module encapsulates the buffer management logic, we can ensure that the range
+/// `pos..filled` is always a valid index into the initialized region of the buffer. This means
+/// that user code which wants to do reads from a `BufReader` via `buffer` + `consume` can do so
+/// without encountering any runtime bounds checks.
+use crate::cmp;
+use crate::io::{self, BorrowedBuf, Read};
+use crate::mem::MaybeUninit;
+
+pub struct Buffer {
+    // The buffer.
+    buf: Box<[MaybeUninit<u8>]>,
+    // The current seek offset into `buf`, must always be <= `filled`.
+    pos: usize,
+    // Each call to `fill_buf` sets `filled` to indicate how many bytes at the start of `buf` are
+    // initialized with bytes from a read.
+    filled: usize,
+    // This is the max number of bytes returned across all `fill_buf` calls. We track this so that we
+    // can accurately tell `read_buf` how many bytes of buf are initialized, to bypass as much of its
+    // defensive initialization as possible. Note that while this often the same as `filled`, it
+    // doesn't need to be. Calls to `fill_buf` are not required to actually fill the buffer, and
+    // omitting this is a huge perf regression for `Read` impls that do not.
+    initialized: usize,
+}
+
+impl Buffer {
+    #[inline]
+    pub fn with_capacity(capacity: usize) -> Self {
+        let buf = Box::new_uninit_slice(capacity);
+        Self { buf, pos: 0, filled: 0, initialized: 0 }
+    }
+
+    #[inline]
+    pub fn buffer(&self) -> &[u8] {
+        // SAFETY: self.pos and self.cap are valid, and self.cap => self.pos, and
+        // that region is initialized because those are all invariants of this type.
+        unsafe { MaybeUninit::slice_assume_init_ref(self.buf.get_unchecked(self.pos..self.filled)) }
+    }
+
+    #[inline]
+    pub fn capacity(&self) -> usize {
+        self.buf.len()
+    }
+
+    #[inline]
+    pub fn filled(&self) -> usize {
+        self.filled
+    }
+
+    #[inline]
+    pub fn pos(&self) -> usize {
+        self.pos
+    }
+
+    // This is only used by a test which asserts that the initialization-tracking is correct.
+    #[cfg(feature = "unit_test")]
+    pub fn initialized(&self) -> usize {
+        self.initialized
+    }
+
+    #[inline]
+    pub fn discard_buffer(&mut self) {
+        self.pos = 0;
+        self.filled = 0;
+    }
+
+    #[inline]
+    pub fn consume(&mut self, amt: usize) {
+        self.pos = cmp::min(self.pos + amt, self.filled);
+    }
+
+    /// If there are `amt` bytes available in the buffer, pass a slice containing those bytes to
+    /// `visitor` and return true. If there are not enough bytes available, return false.
+    #[inline]
+    pub fn consume_with<V>(&mut self, amt: usize, mut visitor: V) -> bool
+    where
+        V: FnMut(&[u8]),
+    {
+        if let Some(claimed) = self.buffer().get(..amt) {
+            visitor(claimed);
+            // If the indexing into self.buffer() succeeds, amt must be a valid increment.
+            self.pos += amt;
+            true
+        } else {
+            false
+        }
+    }
+
+    #[inline]
+    pub fn unconsume(&mut self, amt: usize) {
+        self.pos = self.pos.saturating_sub(amt);
+    }
+
+    #[inline]
+    pub fn fill_buf(&mut self, mut reader: impl Read) -> io::Result<&[u8]> {
+        // If we've reached the end of our internal buffer then we need to fetch
+        // some more data from the reader.
+        // Branch using `>=` instead of the more correct `==`
+        // to tell the compiler that the pos..cap slice is always valid.
+        if self.pos >= self.filled {
+            debug_assert!(self.pos == self.filled);
+
+            let mut buf = BorrowedBuf::from(&mut *self.buf);
+            // SAFETY: `self.filled` bytes will always have been initialized.
+            unsafe {
+                buf.set_init(self.initialized);
+            }
+
+            reader.read_buf(buf.unfilled())?;
+
+            self.pos = 0;
+            self.filled = buf.len();
+            self.initialized = buf.init_len();
+        }
+        Ok(self.buffer())
+    }
+}
diff --git a/sgx_tstd/src/io/buffered/bufwriter.rs b/sgx_tstd/src/io/buffered/bufwriter.rs
index 3897735e..1c74f29d 100644
--- a/sgx_tstd/src/io/buffered/bufwriter.rs
+++ b/sgx_tstd/src/io/buffered/bufwriter.rs
@@ -112,11 +112,11 @@ impl<W: Write> BufWriter<W> {
         BufWriter::with_capacity(DEFAULT_BUF_SIZE, inner)
     }
 
-    /// Creates a new `BufWriter<W>` with the specified buffer capacity.
+    /// Creates a new `BufWriter<W>` with at least the specified buffer capacity.
     ///
     /// # Examples
     ///
-    /// Creating a buffer with a buffer of a hundred bytes.
+    /// Creating a buffer with a buffer of at least a hundred bytes.
     ///
     /// ```no_run
     /// use std::io::BufWriter;
diff --git a/sgx_tstd/src/io/buffered/linewriter.rs b/sgx_tstd/src/io/buffered/linewriter.rs
index 8fbdad5e..2dcbd3e8 100644
--- a/sgx_tstd/src/io/buffered/linewriter.rs
+++ b/sgx_tstd/src/io/buffered/linewriter.rs
@@ -104,8 +104,8 @@ impl<W: Write> LineWriter<W> {
         LineWriter::with_capacity(1024, inner)
     }
 
-    /// Creates a new `LineWriter` with a specified capacity for the internal
-    /// buffer.
+    /// Creates a new `LineWriter` with at least the specified capacity for the
+    /// internal buffer.
     ///
     /// # Examples
     ///
diff --git a/sgx_tstd/src/io/copy.rs b/sgx_tstd/src/io/copy.rs
index b5aa5f43..8730bbd4 100644
--- a/sgx_tstd/src/io/copy.rs
+++ b/sgx_tstd/src/io/copy.rs
@@ -15,7 +15,7 @@
 // specific language governing permissions and limitations
 // under the License..
 
-use super::{BufWriter, ErrorKind, Read, ReadBuf, Result, Write, DEFAULT_BUF_SIZE};
+use super::{BorrowedBuf, BufWriter, ErrorKind, Read, Result, Write, DEFAULT_BUF_SIZE};
 use crate::mem::MaybeUninit;
 
 /// Copies the entire contents of a reader into a writer.
@@ -56,12 +56,22 @@ use crate::mem::MaybeUninit;
 ///     Ok(())
 /// }
 /// ```
+///
+/// # Platform-specific behavior
+///
+/// On Linux (including Android), this function uses `copy_file_range(2)`,
+/// `sendfile(2)` or `splice(2)` syscalls to move data directly between file
+/// descriptors if possible.
+///
+/// Note that platform-specific behavior [may change in the future][changes].
+///
+/// [changes]: crate::io#platform-specific-behavior
 pub fn copy<R: ?Sized, W: ?Sized>(reader: &mut R, writer: &mut W) -> Result<u64>
 where
     R: Read,
     W: Write,
 {
-    generic_copy(reader, writer)
+    crate::sys::kernel_copy::copy_spec(reader, writer)
 }
 
 /// The userspace read-write-loop implementation of `io::copy` that is used when
@@ -97,37 +107,39 @@ impl<I: Write> BufferedCopySpec for BufWriter<I> {
 
         loop {
             let buf = writer.buffer_mut();
-            let mut read_buf = ReadBuf::uninit(buf.spare_capacity_mut());
+            let mut read_buf: BorrowedBuf<'_> = buf.spare_capacity_mut().into();
 
-            // SAFETY: init is either 0 or the initialized_len of the previous iteration
             unsafe {
-                read_buf.assume_init(init);
+                // SAFETY: init is either 0 or the init_len from the previous iteration.
+                read_buf.set_init(init);
             }
 
             if read_buf.capacity() >= DEFAULT_BUF_SIZE {
-                match reader.read_buf(&mut read_buf) {
+                let mut cursor = read_buf.unfilled();
+                match reader.read_buf(cursor.reborrow()) {
                     Ok(()) => {
-                        let bytes_read = read_buf.filled_len();
+                        let bytes_read = cursor.written();
 
                         if bytes_read == 0 {
                             return Ok(len);
                         }
 
-                        init = read_buf.initialized_len() - bytes_read;
+                        init = read_buf.init_len() - bytes_read;
+                        len += bytes_read as u64;
 
-                        // SAFETY: ReadBuf guarantees all of its filled bytes are init
+                        // SAFETY: BorrowedBuf guarantees all of its filled bytes are init
                         unsafe { buf.set_len(buf.len() + bytes_read) };
-                        len += bytes_read as u64;
+
                         // Read again if the buffer still has enough capacity, as BufWriter itself would do
                         // This will occur if the reader returns short reads
-                        continue;
                     }
-                    Err(ref e) if e.kind() == ErrorKind::Interrupted => continue,
+                    Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
                     Err(e) => return Err(e),
                 }
+            } else {
+                writer.flush_buf()?;
+                init = 0;
             }
-
-            writer.flush_buf()?;
         }
     }
 }
@@ -136,13 +148,13 @@ fn stack_buffer_copy<R: Read + ?Sized, W: Write + ?Sized>(
     reader: &mut R,
     writer: &mut W,
 ) -> Result<u64> {
-    let mut buf = [MaybeUninit::uninit(); DEFAULT_BUF_SIZE];
-    let mut buf = ReadBuf::uninit(&mut buf);
+    let buf: &mut [_] = &mut [MaybeUninit::uninit(); DEFAULT_BUF_SIZE];
+    let mut buf: BorrowedBuf<'_> = buf.into();
 
     let mut len = 0;
 
     loop {
-        match reader.read_buf(&mut buf) {
+        match reader.read_buf(buf.unfilled()) {
             Ok(()) => {}
             Err(e) if e.kind() == ErrorKind::Interrupted => continue,
             Err(e) => return Err(e),
diff --git a/sgx_tstd/src/io/cursor.rs b/sgx_tstd/src/io/cursor.rs
index be40a321..e7ed2597 100644
--- a/sgx_tstd/src/io/cursor.rs
+++ b/sgx_tstd/src/io/cursor.rs
@@ -17,10 +17,9 @@
 
 use crate::io::prelude::*;
 
+use crate::alloc::Allocator;
 use crate::cmp;
-use crate::io::{self, ErrorKind, IoSlice, IoSliceMut, ReadBuf, SeekFrom};
-
-use core::convert::TryInto;
+use crate::io::{self, BorrowedCursor, ErrorKind, IoSlice, IoSliceMut, SeekFrom};
 
 /// A `Cursor` wraps an in-memory buffer and provides it with a
 /// [`Seek`] implementation.
@@ -323,12 +322,12 @@ where
         Ok(n)
     }
 
-    fn read_buf(&mut self, buf: &mut ReadBuf<'_>) -> io::Result<()> {
-        let prev_filled = buf.filled_len();
+    fn read_buf(&mut self, mut cursor: BorrowedCursor<'_>) -> io::Result<()> {
+        let prev_written = cursor.written();
 
-        Read::read_buf(&mut self.fill_buf()?, buf)?;
+        Read::read_buf(&mut self.fill_buf()?, cursor.reborrow())?;
 
-        self.pos += (buf.filled_len() - prev_filled) as u64;
+        self.pos += (cursor.written() - prev_written) as u64;
 
         Ok(())
     }
@@ -395,45 +394,127 @@ fn slice_write_vectored(
     Ok(nwritten)
 }
 
-// Resizing write implementation
-fn vec_write(pos_mut: &mut u64, vec: &mut Vec<u8>, buf: &[u8]) -> io::Result<usize> {
+/// Reserves the required space, and pads the vec with 0s if necessary.
+fn reserve_and_pad<A: Allocator>(
+    pos_mut: &mut u64,
+    vec: &mut Vec<u8, A>,
+    buf_len: usize,
+) -> io::Result<usize> {
     let pos: usize = (*pos_mut).try_into().map_err(|_| {
         io::const_io_error!(
             ErrorKind::InvalidInput,
             "cursor position exceeds maximum possible vector length",
         )
     })?;
-    // Make sure the internal buffer is as least as big as where we
-    // currently are
-    let len = vec.len();
-    if len < pos {
-        // use `resize` so that the zero filling is as efficient as possible
-        vec.resize(pos, 0);
-    }
-    // Figure out what bytes will be used to overwrite what's currently
-    // there (left), and what will be appended on the end (right)
-    {
-        let space = vec.len() - pos;
-        let (left, right) = buf.split_at(cmp::min(space, buf.len()));
-        vec[pos..pos + left.len()].copy_from_slice(left);
-        vec.extend_from_slice(right);
+
+    // For safety reasons, we don't want these numbers to overflow
+    // otherwise our allocation won't be enough
+    let desired_cap = pos.saturating_add(buf_len);
+    if desired_cap > vec.capacity() {
+        // We want our vec's total capacity
+        // to have room for (pos+buf_len) bytes. Reserve allocates
+        // based on additional elements from the length, so we need to
+        // reserve the difference
+        vec.reserve(desired_cap - vec.len());
+    }
+    // Pad if pos is above the current len.
+    if pos > vec.len() {
+        let diff = pos - vec.len();
+        // Unfortunately, `resize()` would suffice but the optimiser does not
+        // realise the `reserve` it does can be eliminated. So we do it manually
+        // to eliminate that extra branch
+        let spare = vec.spare_capacity_mut();
+        debug_assert!(spare.len() >= diff);
+        // Safety: we have allocated enough capacity for this.
+        // And we are only writing, not reading
+        unsafe {
+            spare.get_unchecked_mut(..diff).fill(core::mem::MaybeUninit::new(0));
+            vec.set_len(pos);
+        }
     }
 
+    Ok(pos)
+}
+
+/// Writes the slice to the vec without allocating
+/// # Safety: vec must have buf.len() spare capacity
+unsafe fn vec_write_unchecked<A>(pos: usize, vec: &mut Vec<u8, A>, buf: &[u8]) -> usize
+where
+    A: Allocator,
+{
+    debug_assert!(vec.capacity() >= pos + buf.len());
+    vec.as_mut_ptr().add(pos).copy_from(buf.as_ptr(), buf.len());
+    pos + buf.len()
+}
+
+/// Resizing write implementation for [`Cursor`]
+///
+/// Cursor is allowed to have a pre-allocated and initialised
+/// vector body, but with a position of 0. This means the [`Write`]
+/// will overwrite the contents of the vec.
+///
+/// This also allows for the vec body to be empty, but with a position of N.
+/// This means that [`Write`] will pad the vec with 0 initially,
+/// before writing anything from that point
+fn vec_write<A>(pos_mut: &mut u64, vec: &mut Vec<u8, A>, buf: &[u8]) -> io::Result<usize>
+where
+    A: Allocator,
+{
+    let buf_len = buf.len();
+    let mut pos = reserve_and_pad(pos_mut, vec, buf_len)?;
+
+    // Write the buf then progress the vec forward if necessary
+    // Safety: we have ensured that the capacity is available
+    // and that all bytes get written up to pos
+    unsafe {
+        pos = vec_write_unchecked(pos, vec, buf);
+        if pos > vec.len() {
+            vec.set_len(pos);
+        }
+    };
+
     // Bump us forward
-    *pos_mut = (pos + buf.len()) as u64;
-    Ok(buf.len())
+    *pos_mut += buf_len as u64;
+    Ok(buf_len)
 }
 
-fn vec_write_vectored(
+/// Resizing write_vectored implementation for [`Cursor`]
+///
+/// Cursor is allowed to have a pre-allocated and initialised
+/// vector body, but with a position of 0. This means the [`Write`]
+/// will overwrite the contents of the vec.
+///
+/// This also allows for the vec body to be empty, but with a position of N.
+/// This means that [`Write`] will pad the vec with 0 initially,
+/// before writing anything from that point
+fn vec_write_vectored<A>(
     pos_mut: &mut u64,
-    vec: &mut Vec<u8>,
+    vec: &mut Vec<u8, A>,
     bufs: &[IoSlice<'_>],
-) -> io::Result<usize> {
-    let mut nwritten = 0;
-    for buf in bufs {
-        nwritten += vec_write(pos_mut, vec, buf)?;
+) -> io::Result<usize>
+where
+    A: Allocator,
+{
+    // For safety reasons, we don't want this sum to overflow ever.
+    // If this saturates, the reserve should panic to avoid any unsound writing.
+    let buf_len = bufs.iter().fold(0usize, |a, b| a.saturating_add(b.len()));
+    let mut pos = reserve_and_pad(pos_mut, vec, buf_len)?;
+
+    // Write the buf then progress the vec forward if necessary
+    // Safety: we have ensured that the capacity is available
+    // and that all bytes get written up to the last pos
+    unsafe {
+        for buf in bufs {
+            pos = vec_write_unchecked(pos, vec, buf);
+        }
+        if pos > vec.len() {
+            vec.set_len(pos);
+        }
     }
-    Ok(nwritten)
+
+    // Bump us forward
+    *pos_mut += buf_len as u64;
+    Ok(buf_len)
 }
 
 impl Write for Cursor<&mut [u8]> {
@@ -458,7 +539,10 @@ impl Write for Cursor<&mut [u8]> {
     }
 }
 
-impl Write for Cursor<&mut Vec<u8>> {
+impl<A> Write for Cursor<&mut Vec<u8, A>>
+where
+    A: Allocator,
+{
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
         vec_write(&mut self.pos, self.inner, buf)
     }
@@ -478,7 +562,10 @@ impl Write for Cursor<&mut Vec<u8>> {
     }
 }
 
-impl Write for Cursor<Vec<u8>> {
+impl<A> Write for Cursor<Vec<u8, A>>
+where
+    A: Allocator,
+{
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
         vec_write(&mut self.pos, &mut self.inner, buf)
     }
@@ -498,7 +585,32 @@ impl Write for Cursor<Vec<u8>> {
     }
 }
 
-impl Write for Cursor<Box<[u8]>> {
+impl<A> Write for Cursor<Box<[u8], A>>
+where
+    A: Allocator,
+{
+    #[inline]
+    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+        slice_write(&mut self.pos, &mut self.inner, buf)
+    }
+
+    #[inline]
+    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
+        slice_write_vectored(&mut self.pos, &mut self.inner, bufs)
+    }
+
+    #[inline]
+    fn is_write_vectored(&self) -> bool {
+        true
+    }
+
+    #[inline]
+    fn flush(&mut self) -> io::Result<()> {
+        Ok(())
+    }
+}
+
+impl<const N: usize> Write for Cursor<[u8; N]> {
     #[inline]
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
         slice_write(&mut self.pos, &mut self.inner, buf)
diff --git a/sgx_tstd/src/io/error.rs b/sgx_tstd/src/io/error.rs
index 6de63fbb..13acec0c 100644
--- a/sgx_tstd/src/io/error.rs
+++ b/sgx_tstd/src/io/error.rs
@@ -82,6 +82,13 @@ impl fmt::Debug for Error {
     }
 }
 
+impl From<alloc_crate::ffi::NulError> for Error {
+    /// Converts a [`alloc::ffi::NulError`] into a [`Error`].
+    fn from(_: alloc_crate::ffi::NulError) -> Error {
+        const_io_error!(ErrorKind::InvalidInput, "data provided contains a nul byte")
+    }
+}
+
 // Only derive debug in tests, to make sure it
 // doesn't accidentally get printed.
 #[cfg_attr(feature = "unit_test", derive(Debug))]
@@ -148,6 +155,19 @@ struct Custom {
 /// It is used with the [`io::Error`] type.
 ///
 /// [`io::Error`]: Error
+///
+/// # Handling errors and matching on `ErrorKind`
+///
+/// In application code, use `match` for the `ErrorKind` values you are
+/// expecting; use `_` to match "all other errors".
+///
+/// In comprehensive and thorough tests that want to verify that a test doesn't
+/// return any known incorrect error kind, you may want to cut-and-paste the
+/// current full list of errors from here into your test code, and then match
+/// `_` as the correct case. This seems counterintuitive, but it will make your
+/// tests more robust. In particular, if you want to verify that your code does
+/// produce an unrecognized error kind, the robust solution is to check for all
+/// the recognized error kinds and fail in those cases.
 #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
 #[allow(deprecated)]
 #[non_exhaustive]
@@ -334,7 +354,7 @@ pub enum ErrorKind {
 impl ErrorKind {
     pub(crate) fn as_str(&self) -> &'static str {
         use ErrorKind::*;
-        // Strictly alphabetical, please.  (Sadly rustfmt cannot do this yet.)
+        // tidy-alphabetical-start
         match *self {
             AddrInUse => "address in use",
             AddrNotAvailable => "address not available",
@@ -379,6 +399,7 @@ impl ErrorKind {
             WriteZero => "write zero",
             SgxError => "Sgx error status",
         }
+        // tidy-alphabetical-end
     }
 }
 
@@ -411,7 +432,7 @@ impl From<ErrorKind> for Error {
     ///
     /// let not_found = ErrorKind::NotFound;
     /// let error = Error::from(not_found);
-    /// assert_eq!("entity not found", format!("{}", error));
+    /// assert_eq!("entity not found", format!("{error}"));
     /// ```
     #[inline]
     fn from(kind: ErrorKind) -> Error {
@@ -434,6 +455,7 @@ impl Error {
     /// originate from the OS itself. The `error` argument is an arbitrary
     /// payload which will be contained in this [`Error`].
     ///
+    /// Note that this function allocates memory on the heap.
     /// If no extra payload is required, use the `From` conversion from
     /// `ErrorKind`.
     ///
@@ -448,7 +470,7 @@ impl Error {
     /// // errors can also be created from other errors
     /// let custom_error2 = Error::new(ErrorKind::Interrupted, custom_error);
     ///
-    /// // creating an error without payload
+    /// // creating an error without payload (and without memory allocation)
     /// let eof_error = Error::from(ErrorKind::UnexpectedEof);
     /// ```
     pub fn new<E>(kind: ErrorKind, error: E) -> Error
@@ -520,12 +542,13 @@ impl Error {
     /// use std::io::Error;
     ///
     /// let os_error = Error::last_os_error();
-    /// println!("last OS error: {:?}", os_error);
+    /// println!("last OS error: {os_error:?}");
     /// ```
+    #[doc(alias = "errno")]
     #[must_use]
     #[inline]
     pub fn last_os_error() -> Error {
-        Error::from_raw_os_error(sys::os::errno() as i32)
+        Error::from_raw_os_error(sys::os::errno())
     }
 
     /// Creates a new instance of an [`Error`] from a particular OS error code.
@@ -575,7 +598,7 @@ impl Error {
     ///
     /// fn print_os_error(err: &Error) {
     ///     if let Some(raw_os_err) = err.raw_os_error() {
-    ///         println!("raw OS error: {:?}", raw_os_err);
+    ///         println!("raw OS error: {raw_os_err:?}");
     ///     } else {
     ///         println!("Not an OS error");
     ///     }
@@ -634,7 +657,7 @@ impl Error {
     ///
     /// fn print_error(err: &Error) {
     ///     if let Some(inner_err) = err.get_ref() {
-    ///         println!("Inner error: {:?}", inner_err);
+    ///         println!("Inner error: {inner_err:?}");
     ///     } else {
     ///         println!("No inner error");
     ///     }
@@ -708,7 +731,7 @@ impl Error {
     ///
     /// fn print_error(err: &Error) {
     ///     if let Some(inner_err) = err.get_ref() {
-    ///         println!("Inner error: {}", inner_err);
+    ///         println!("Inner error: {inner_err}");
     ///     } else {
     ///         println!("No inner error");
     ///     }
@@ -747,7 +770,7 @@ impl Error {
     ///
     /// fn print_error(err: Error) {
     ///     if let Some(inner_err) = err.into_inner() {
-    ///         println!("Inner error: {}", inner_err);
+    ///         println!("Inner error: {inner_err}");
     ///     } else {
     ///         println!("No inner error");
     ///     }
@@ -772,6 +795,67 @@ impl Error {
         }
     }
 
+    /// Attempt to downgrade the inner error to `E` if any.
+    ///
+    /// If this [`Error`] was constructed via [`new`] then this function will
+    /// attempt to perform downgrade on it, otherwise it will return [`Err`].
+    ///
+    /// If downgrade succeeds, it will return [`Ok`], otherwise it will also
+    /// return [`Err`].
+    ///
+    /// [`new`]: Error::new
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(io_error_downcast)]
+    ///
+    /// use std::fmt;
+    /// use std::io;
+    /// use std::error::Error;
+    ///
+    /// #[derive(Debug)]
+    /// enum E {
+    ///     Io(io::Error),
+    ///     SomeOtherVariant,
+    /// }
+    ///
+    /// impl fmt::Display for E {
+    ///    // ...
+    /// #    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+    /// #        todo!()
+    /// #    }
+    /// }
+    /// impl Error for E {}
+    ///
+    /// impl From<io::Error> for E {
+    ///     fn from(err: io::Error) -> E {
+    ///         err.downcast::<E>()
+    ///             .map(|b| *b)
+    ///             .unwrap_or_else(E::Io)
+    ///     }
+    /// }
+    /// ```
+    pub fn downcast<E>(self) -> result::Result<Box<E>, Self>
+    where
+        E: error::Error + Send + Sync + 'static,
+    {
+        match self.repr.into_data() {
+            ErrorData::Custom(b) if b.error.is::<E>() => {
+                let res = (*b).error.downcast::<E>();
+
+                // downcast is a really trivial and is marked as inline, so
+                // it's likely be inlined here.
+                //
+                // And the compiler should be able to eliminate the branch
+                // that produces `Err` here since b.error.is::<E>()
+                // returns true.
+                Ok(res.unwrap())
+            }
+            repr_data => Err(Self { repr: Repr::new(repr_data) }),
+        }
+    }
+
     /// Returns the corresponding [`ErrorKind`] for this error.
     ///
     /// # Examples
@@ -833,14 +917,14 @@ impl fmt::Display for Error {
         match self.repr.data() {
             ErrorData::Os(code) => {
                 let detail = sys::os::error_string(code);
-                write!(fmt, "{} (os error {})", detail, code)
+                write!(fmt, "{detail} (os error {code})")
             }
-            ErrorData::Custom(c) => c.error.fmt(fmt),
+            ErrorData::Custom(ref c) => c.error.fmt(fmt),
             ErrorData::Simple(kind) => write!(fmt, "{}", kind.as_str()),
             ErrorData::SimpleMessage(msg) => msg.message.fmt(fmt),
             ErrorData::SgxStatus(status) => {
                 let detail = status.__description();
-                write!(fmt, "{} (sgx error: {})", detail, status)
+                write!(fmt, "{detail} (sgx error: {status})")
             }
         }
     }
diff --git a/sgx_tstd/src/io/error/repr_unpacked.rs b/sgx_tstd/src/io/error/repr_unpacked.rs
index f1713077..00f318a8 100644
--- a/sgx_tstd/src/io/error/repr_unpacked.rs
+++ b/sgx_tstd/src/io/error/repr_unpacked.rs
@@ -12,6 +12,10 @@ type Inner = ErrorData<Box<Custom>>;
 pub(super) struct Repr(Inner);
 
 impl Repr {
+    #[inline]
+    pub(super) fn new(dat: ErrorData<Box<Custom>>) -> Self {
+        Self(dat)
+    }
     pub(super) fn new_custom(b: Box<Custom>) -> Self {
         Self(Inner::Custom(b))
     }
@@ -41,7 +45,7 @@ impl Repr {
             Inner::Os(c) => ErrorData::Os(*c),
             Inner::Simple(k) => ErrorData::Simple(*k),
             Inner::SimpleMessage(m) => ErrorData::SimpleMessage(*m),
-            Inner::Custom(m) => ErrorData::Custom(&*m),
+            Inner::Custom(m) => ErrorData::Custom(&**m),
             Inner::SgxStatus(s) => ErrorData::SgxStatus(*s),
         }
     }
diff --git a/sgx_tstd/src/io/impls.rs b/sgx_tstd/src/io/impls.rs
index 2a8ebc6d..57b13d8b 100644
--- a/sgx_tstd/src/io/impls.rs
+++ b/sgx_tstd/src/io/impls.rs
@@ -17,9 +17,10 @@
 
 use crate::alloc::Allocator;
 use crate::cmp;
+use crate::collections::VecDeque;
 use crate::fmt;
 use crate::io::{
-    self, BufRead, ErrorKind, IoSlice, IoSliceMut, Read, ReadBuf, Seek, SeekFrom, Write,
+    self, BorrowedCursor, BufRead, ErrorKind, IoSlice, IoSliceMut, Read, Seek, SeekFrom, Write,
 };
 use crate::mem;
 
@@ -33,8 +34,8 @@ impl<R: Read + ?Sized> Read for &mut R {
     }
 
     #[inline]
-    fn read_buf(&mut self, buf: &mut ReadBuf<'_>) -> io::Result<()> {
-        (**self).read_buf(buf)
+    fn read_buf(&mut self, cursor: BorrowedCursor<'_>) -> io::Result<()> {
+        (**self).read_buf(cursor)
     }
 
     #[inline]
@@ -136,8 +137,8 @@ impl<R: Read + ?Sized> Read for Box<R> {
     }
 
     #[inline]
-    fn read_buf(&mut self, buf: &mut ReadBuf<'_>) -> io::Result<()> {
-        (**self).read_buf(buf)
+    fn read_buf(&mut self, cursor: BorrowedCursor<'_>) -> io::Result<()> {
+        (**self).read_buf(cursor)
     }
 
     #[inline]
@@ -259,11 +260,11 @@ impl Read for &[u8] {
     }
 
     #[inline]
-    fn read_buf(&mut self, buf: &mut ReadBuf<'_>) -> io::Result<()> {
-        let amt = cmp::min(buf.remaining(), self.len());
+    fn read_buf(&mut self, mut cursor: BorrowedCursor<'_>) -> io::Result<()> {
+        let amt = cmp::min(cursor.capacity(), self.len());
         let (a, b) = self.split_at(amt);
 
-        buf.append(a);
+        cursor.append(a);
 
         *self = b;
         Ok(())
@@ -418,4 +419,47 @@ impl<A: Allocator> Write for Vec<u8, A> {
     fn flush(&mut self) -> io::Result<()> {
         Ok(())
     }
-}
\ No newline at end of file
+}
+
+/// Read is implemented for `VecDeque<u8>` by consuming bytes from the front of the `VecDeque`.
+impl<A: Allocator> Read for VecDeque<u8, A> {
+    /// Fill `buf` with the contents of the "front" slice as returned by
+    /// [`as_slices`][`VecDeque::as_slices`]. If the contained byte slices of the `VecDeque` are
+    /// discontiguous, multiple calls to `read` will be needed to read the entire content.
+    #[inline]
+    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
+        let (ref mut front, _) = self.as_slices();
+        let n = Read::read(front, buf)?;
+        self.drain(..n);
+        Ok(n)
+    }
+
+    #[inline]
+    fn read_buf(&mut self, cursor: BorrowedCursor<'_>) -> io::Result<()> {
+        let (ref mut front, _) = self.as_slices();
+        let n = cmp::min(cursor.capacity(), front.len());
+        Read::read_buf(front, cursor)?;
+        self.drain(..n);
+        Ok(())
+    }
+}
+
+/// Write is implemented for `VecDeque<u8>` by appending to the `VecDeque`, growing it as needed.
+impl<A: Allocator> Write for VecDeque<u8, A> {
+    #[inline]
+    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+        self.extend(buf);
+        Ok(buf.len())
+    }
+
+    #[inline]
+    fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
+        self.extend(buf);
+        Ok(())
+    }
+
+    #[inline]
+    fn flush(&mut self) -> io::Result<()> {
+        Ok(())
+    }
+}
diff --git a/sgx_tstd/src/io/mod.rs b/sgx_tstd/src/io/mod.rs
index 2497f3db..313e0cd2 100644
--- a/sgx_tstd/src/io/mod.rs
+++ b/sgx_tstd/src/io/mod.rs
@@ -108,7 +108,7 @@
 //!     // read a line into buffer
 //!     reader.read_line(&mut buffer)?;
 //!
-//!     println!("{}", buffer);
+//!     println!("{buffer}");
 //!     Ok(())
 //! }
 //! ```
@@ -264,7 +264,6 @@
 //! [`.unwrap()`]: crate::result::Result::unwrap
 
 use crate::cmp;
-use crate::convert::TryInto;
 use crate::fmt;
 use crate::mem::replace;
 use crate::ops::{Deref, DerefMut};
@@ -273,13 +272,14 @@ use crate::str;
 use crate::sys;
 use crate::sys_common::memchr;
 
-
 pub use self::buffered::WriterPanicked;
-
 #[cfg(feature = "stdio")]
-pub use self::stdio::{_eprint, _print};
+#[allow(unused_imports)]
+pub(crate) use self::stdio::attempt_print_to_stderr;
 #[cfg(feature = "stdio")]
-pub use self::stdio::{stderr_locked, stdin_locked, stdout_locked};
+pub use self::stdio::set_output_capture;
+#[cfg(feature = "stdio")]
+pub use self::stdio::{_eprint, _print};
 #[cfg(feature = "stdio")]
 pub use self::stdio::{stderr, stdin, stdout, Stderr, StderrLock, Stdin, StdinLock, Stdout, StdoutLock};
 pub use self::{
@@ -290,7 +290,7 @@ pub use self::{
     util::{empty, repeat, sink, Empty, Repeat, Sink},
 };
 
-pub use self::readbuf::ReadBuf;
+pub use self::readbuf::{BorrowedBuf, BorrowedCursor};
 pub(crate) use error::const_io_error;
 
 mod buffered;
@@ -304,6 +304,15 @@ mod readbuf;
 mod stdio;
 mod util;
 
+pub trait IsTerminal: crate::sealed::Sealed {
+    /// Returns `true` if the descriptor/handle refers to a terminal/tty.
+    ///
+    /// On platforms where Rust does not know how to detect a terminal yet, this will return
+    /// `false`. This will also return `false` if an unexpected error occurred, such as from
+    /// passing an invalid file descriptor.
+    fn is_terminal(&self) -> bool;
+}
+
 const DEFAULT_BUF_SIZE: usize = crate::sys_common::io::DEFAULT_BUF_SIZE;
 
 #[cfg(feature = "stdio")]
@@ -376,29 +385,30 @@ pub(crate) fn default_read_to_end<R: Read + ?Sized>(r: &mut R, buf: &mut Vec<u8>
             buf.reserve(32); // buf is full, need more space
         }
 
-        let mut read_buf = ReadBuf::uninit(buf.spare_capacity_mut());
+        let mut read_buf: BorrowedBuf<'_> = buf.spare_capacity_mut().into();
 
         // SAFETY: These bytes were initialized but not filled in the previous loop
         unsafe {
-            read_buf.assume_init(initialized);
+            read_buf.set_init(initialized);
         }
 
-        match r.read_buf(&mut read_buf) {
+        let mut cursor = read_buf.unfilled();
+        match r.read_buf(cursor.reborrow()) {
             Ok(()) => {}
             Err(e) if e.kind() == ErrorKind::Interrupted => continue,
             Err(e) => return Err(e),
         }
 
-        if read_buf.filled_len() == 0 {
+        if cursor.written() == 0 {
             return Ok(buf.len() - start_len);
         }
 
         // store how much was initialized but not filled
-        initialized = read_buf.initialized_len() - read_buf.filled_len();
-        let new_len = read_buf.filled_len() + buf.len();
+        initialized = cursor.init_ref().len();
 
-        // SAFETY: ReadBuf's invariants mean this much memory is init
+        // SAFETY: BorrowedBuf's invariants mean this much memory is initialized.
         unsafe {
+            let new_len = read_buf.filled().len() + buf.len();
             buf.set_len(new_len);
         }
 
@@ -475,12 +485,15 @@ pub(crate) fn default_read_exact<R: Read + ?Sized>(this: &mut R, mut buf: &mut [
     }
 }
 
-pub(crate) fn default_read_buf<F>(read: F, buf: &mut ReadBuf<'_>) -> Result<()>
+pub(crate) fn default_read_buf<F>(read: F, mut cursor: BorrowedCursor<'_>) -> Result<()>
 where
     F: FnOnce(&mut [u8]) -> Result<usize>,
 {
-    let n = read(buf.initialize_unfilled())?;
-    buf.add_filled(n);
+    let n = read(cursor.ensure_init().init_mut())?;
+    unsafe {
+        // SAFETY: we initialised using `ensure_init` so there is no uninit data to advance to.
+        cursor.advance(n);
+    }
     Ok(())
 }
 
@@ -809,28 +822,28 @@ pub trait Read {
 
     /// Pull some bytes from this source into the specified buffer.
     ///
-    /// This is equivalent to the [`read`](Read::read) method, except that it is passed a [`ReadBuf`] rather than `[u8]` to allow use
+    /// This is equivalent to the [`read`](Read::read) method, except that it is passed a [`BorrowedCursor`] rather than `[u8]` to allow use
     /// with uninitialized buffers. The new data will be appended to any existing contents of `buf`.
     ///
     /// The default implementation delegates to `read`.
-    fn read_buf(&mut self, buf: &mut ReadBuf<'_>) -> Result<()> {
+    fn read_buf(&mut self, buf: BorrowedCursor<'_>) -> Result<()> {
         default_read_buf(|b| self.read(b), buf)
     }
 
-    /// Read the exact number of bytes required to fill `buf`.
+    /// Read the exact number of bytes required to fill `cursor`.
     ///
-    /// This is equivalent to the [`read_exact`](Read::read_exact) method, except that it is passed a [`ReadBuf`] rather than `[u8]` to
+    /// This is equivalent to the [`read_exact`](Read::read_exact) method, except that it is passed a [`BorrowedCursor`] rather than `[u8]` to
     /// allow use with uninitialized buffers.
-    fn read_buf_exact(&mut self, buf: &mut ReadBuf<'_>) -> Result<()> {
-        while buf.remaining() > 0 {
-            let prev_filled = buf.filled().len();
-            match self.read_buf(buf) {
+    fn read_buf_exact(&mut self, mut cursor: BorrowedCursor<'_>) -> Result<()> {
+        while cursor.capacity() > 0 {
+            let prev_written = cursor.written();
+            match self.read_buf(cursor.reborrow()) {
                 Ok(()) => {}
                 Err(e) if e.kind() == ErrorKind::Interrupted => continue,
                 Err(e) => return Err(e),
             }
 
-            if buf.filled().len() == prev_filled {
+            if cursor.written() == prev_written {
                 return Err(Error::new(ErrorKind::UnexpectedEof, "failed to fill buffer"));
             }
         }
@@ -886,6 +899,10 @@ pub trait Read {
     /// The yielded item is [`Ok`] if a byte was successfully read and [`Err`]
     /// otherwise. EOF is mapped to returning [`None`] from this iterator.
     ///
+    /// The default implementation calls `read` for each byte,
+    /// which can be very inefficient for data that's not in memory,
+    /// such as [`File`]. Consider using a [`BufReader`] in such cases.
+    ///
     /// # Examples
     ///
     /// [`File`]s implement `Read`:
@@ -898,10 +915,11 @@ pub trait Read {
     /// ```no_run
     /// use std::io;
     /// use std::io::prelude::*;
+    /// use std::io::BufReader;
     /// use std::fs::File;
     ///
     /// fn main() -> io::Result<()> {
-    ///     let mut f = File::open("foo.txt")?;
+    ///     let f = BufReader::new(File::open("foo.txt")?);
     ///
     ///     for byte in f.bytes() {
     ///         println!("{}", byte.unwrap());
@@ -934,8 +952,8 @@ pub trait Read {
     /// use std::fs::File;
     ///
     /// fn main() -> io::Result<()> {
-    ///     let mut f1 = File::open("foo.txt")?;
-    ///     let mut f2 = File::open("bar.txt")?;
+    ///     let f1 = File::open("foo.txt")?;
+    ///     let f2 = File::open("bar.txt")?;
     ///
     ///     let mut handle = f1.chain(f2);
     ///     let mut buffer = String::new();
@@ -974,7 +992,7 @@ pub trait Read {
     /// use std::fs::File;
     ///
     /// fn main() -> io::Result<()> {
-    ///     let mut f = File::open("foo.txt")?;
+    ///     let f = File::open("foo.txt")?;
     ///     let mut buffer = [0; 5];
     ///
     ///     // read at most five bytes
@@ -1028,13 +1046,11 @@ pub trait Read {
 /// # Examples
 ///
 /// ```no_run
-/// #![feature(io_read_to_string)]
-///
 /// # use std::io;
 /// fn main() -> io::Result<()> {
 ///     let stdin = io::read_to_string(io::stdin())?;
 ///     println!("Stdin was:");
-///     println!("{}", stdin);
+///     println!("{stdin}");
 ///     Ok(())
 /// }
 /// ```
@@ -1078,6 +1094,10 @@ impl<'a> IoSliceMut<'a> {
     /// Also see [`IoSliceMut::advance_slices`] to advance the cursors of
     /// multiple buffers.
     ///
+    /// # Panics
+    ///
+    /// Panics when trying to advance beyond the end of the slice.
+    ///
     /// # Examples
     ///
     /// ```
@@ -1098,15 +1118,18 @@ impl<'a> IoSliceMut<'a> {
         self.0.advance(n)
     }
 
-    /// Advance the internal cursor of the slices.
+    /// Advance a slice of slices.
     ///
-    /// # Notes
+    /// Shrinks the slice to remove any `IoSliceMut`s that are fully advanced over.
+    /// If the cursor ends up in the middle of an `IoSliceMut`, it is modified
+    /// to start at that cursor.
+    ///
+    /// For example, if we have a slice of two 8-byte `IoSliceMut`s, and we advance by 10 bytes,
+    /// the result will only include the second `IoSliceMut`, advanced by 2 bytes.
     ///
-    /// Elements in the slice may be modified if the cursor is not advanced to
-    /// the end of the slice. For example if we have a slice of buffers with 2
-    /// `IoSliceMut`s, both of length 8, and we advance the cursor by 10 bytes
-    /// the first `IoSliceMut` will be untouched however the second will be
-    /// modified to remove the first 2 bytes (10 - 8).
+    /// # Panics
+    ///
+    /// Panics when trying to advance beyond the end of the slices.
     ///
     /// # Examples
     ///
@@ -1147,7 +1170,9 @@ impl<'a> IoSliceMut<'a> {
         }
 
         *bufs = &mut replace(bufs, &mut [])[remove..];
-        if !bufs.is_empty() {
+        if bufs.is_empty() {
+            assert!(n == accumulated_len, "advancing io slices beyond their length");
+        } else {
             bufs[0].advance(n - accumulated_len)
         }
     }
@@ -1205,6 +1230,10 @@ impl<'a> IoSlice<'a> {
     /// Also see [`IoSlice::advance_slices`] to advance the cursors of multiple
     /// buffers.
     ///
+    /// # Panics
+    ///
+    /// Panics when trying to advance beyond the end of the slice.
+    ///
     /// # Examples
     ///
     /// ```
@@ -1213,8 +1242,8 @@ impl<'a> IoSlice<'a> {
     /// use std::io::IoSlice;
     /// use std::ops::Deref;
     ///
-    /// let mut data = [1; 8];
-    /// let mut buf = IoSlice::new(&mut data);
+    /// let data = [1; 8];
+    /// let mut buf = IoSlice::new(&data);
     ///
     /// // Mark 3 bytes as read.
     /// buf.advance(3);
@@ -1225,15 +1254,18 @@ impl<'a> IoSlice<'a> {
         self.0.advance(n)
     }
 
-    /// Advance the internal cursor of the slices.
+    /// Advance a slice of slices.
     ///
-    /// # Notes
+    /// Shrinks the slice to remove any `IoSlice`s that are fully advanced over.
+    /// If the cursor ends up in the middle of an `IoSlice`, it is modified
+    /// to start at that cursor.
+    ///
+    /// For example, if we have a slice of two 8-byte `IoSlice`s, and we advance by 10 bytes,
+    /// the result will only include the second `IoSlice`, advanced by 2 bytes.
+    ///
+    /// # Panics
     ///
-    /// Elements in the slice may be modified if the cursor is not advanced to
-    /// the end of the slice. For example if we have a slice of buffers with 2
-    /// `IoSlice`s, both of length 8, and we advance the cursor by 10 bytes the
-    /// first `IoSlice` will be untouched however the second will be modified to
-    /// remove the first 2 bytes (10 - 8).
+    /// Panics when trying to advance beyond the end of the slices.
     ///
     /// # Examples
     ///
@@ -1273,7 +1305,9 @@ impl<'a> IoSlice<'a> {
         }
 
         *bufs = &mut replace(bufs, &mut [])[remove..];
-        if !bufs.is_empty() {
+        if bufs.is_empty() {
+            assert!(n == accumulated_len, "advancing io slices beyond their length");
+        } else {
             bufs[0].advance(n - accumulated_len)
         }
     }
@@ -1398,10 +1432,10 @@ pub trait Write {
     /// use std::fs::File;
     ///
     /// fn main() -> std::io::Result<()> {
-    ///     let mut data1 = [1; 8];
-    ///     let mut data2 = [15; 8];
-    ///     let io_slice1 = IoSlice::new(&mut data1);
-    ///     let io_slice2 = IoSlice::new(&mut data2);
+    ///     let data1 = [1; 8];
+    ///     let data2 = [15; 8];
+    ///     let io_slice1 = IoSlice::new(&data1);
+    ///     let io_slice2 = IoSlice::new(&data2);
     ///
     ///     let mut buffer = File::create("foo.txt")?;
     ///
@@ -1732,7 +1766,7 @@ pub trait Seek {
     ///     .open("foo.txt").unwrap();
     ///
     /// let hello = "Hello!\n";
-    /// write!(f, "{}", hello).unwrap();
+    /// write!(f, "{hello}").unwrap();
     /// f.rewind().unwrap();
     ///
     /// let mut buf = String::new();
@@ -1774,7 +1808,7 @@ pub trait Seek {
     ///     let mut f = File::open("foo.txt")?;
     ///
     ///     let len = f.stream_len()?;
-    ///     println!("The file is currently {} bytes long", len);
+    ///     println!("The file is currently {len} bytes long");
     ///     Ok(())
     /// }
     /// ```
@@ -1951,7 +1985,7 @@ pub trait BufRead: Read {
     /// let buffer = stdin.fill_buf().unwrap();
     ///
     /// // work with buffer
-    /// println!("{:?}", buffer);
+    /// println!("{buffer:?}");
     ///
     /// // ensure the bytes we worked with aren't returned again later
     /// let length = buffer.len();
@@ -2003,7 +2037,7 @@ pub trait BufRead: Read {
     ///     let mut line = String::new();
     ///     stdin.read_line(&mut line).unwrap();
     ///     // work with line
-    ///     println!("{:?}", line);
+    ///     println!("{line:?}");
     /// }
     /// ```
     fn has_data_left(&mut self) -> Result<bool> {
@@ -2069,7 +2103,8 @@ pub trait BufRead: Read {
     }
 
     /// Read all bytes until a newline (the `0xA` byte) is reached, and append
-    /// them to the provided buffer.
+    /// them to the provided buffer. You do not need to clear the buffer before
+    /// appending.
     ///
     /// This function will read bytes from the underlying stream until the
     /// newline delimiter (the `0xA` byte) or EOF is found. Once found, all bytes
@@ -2502,54 +2537,53 @@ impl<T: Read> Read for Take<T> {
 
         let max = cmp::min(buf.len() as u64, self.limit) as usize;
         let n = self.inner.read(&mut buf[..max])?;
+        assert!(n as u64 <= self.limit, "number of read bytes exceeds limit");
         self.limit -= n as u64;
         Ok(n)
     }
 
-    fn read_buf(&mut self, buf: &mut ReadBuf<'_>) -> Result<()> {
+    fn read_buf(&mut self, mut buf: BorrowedCursor<'_>) -> Result<()> {
         // Don't call into inner reader at all at EOF because it may still block
         if self.limit == 0 {
             return Ok(());
         }
 
-        let prev_filled = buf.filled_len();
-
-        if self.limit <= buf.remaining() as u64 {
+        if self.limit <= buf.capacity() as u64 {
             // if we just use an as cast to convert, limit may wrap around on a 32 bit target
             let limit = cmp::min(self.limit, usize::MAX as u64) as usize;
 
-            let extra_init = cmp::min(limit as usize, buf.initialized_len() - buf.filled_len());
+            let extra_init = cmp::min(limit, buf.init_ref().len());
 
             // SAFETY: no uninit data is written to ibuf
-            let ibuf = unsafe { &mut buf.unfilled_mut()[..limit] };
+            let ibuf = unsafe { &mut buf.as_mut()[..limit] };
 
-            let mut sliced_buf = ReadBuf::uninit(ibuf);
+            let mut sliced_buf: BorrowedBuf<'_> = ibuf.into();
 
             // SAFETY: extra_init bytes of ibuf are known to be initialized
             unsafe {
-                sliced_buf.assume_init(extra_init);
+                sliced_buf.set_init(extra_init);
             }
 
-            self.inner.read_buf(&mut sliced_buf)?;
+            let mut cursor = sliced_buf.unfilled();
+            self.inner.read_buf(cursor.reborrow())?;
 
-            let new_init = sliced_buf.initialized_len();
-            let filled = sliced_buf.filled_len();
+            let new_init = cursor.init_ref().len();
+            let filled = sliced_buf.len();
 
-            // sliced_buf / ibuf must drop here
+            // cursor / sliced_buf / ibuf must drop here
 
-            // SAFETY: new_init bytes of buf's unfilled buffer have been initialized
             unsafe {
-                buf.assume_init(new_init);
+                // SAFETY: filled bytes have been filled and therefore initialized
+                buf.advance(filled);
+                // SAFETY: new_init bytes of buf's unfilled buffer have been initialized
+                buf.set_init(new_init);
             }
 
-            buf.add_filled(filled);
-
             self.limit -= filled as u64;
         } else {
-            self.inner.read_buf(buf)?;
-
-            //inner may unfill
-            self.limit -= buf.filled_len().saturating_sub(prev_filled) as u64;
+            let written = buf.written();
+            self.inner.read_buf(buf.reborrow())?;
+            self.limit -= (buf.written() - written) as u64;
         }
 
         Ok(())
diff --git a/sgx_tstd/src/io/readbuf.rs b/sgx_tstd/src/io/readbuf.rs
index db776d76..5889ee95 100644
--- a/sgx_tstd/src/io/readbuf.rs
+++ b/sgx_tstd/src/io/readbuf.rs
@@ -15,11 +15,12 @@
 // specific language governing permissions and limitations
 // under the License..
 
-use crate::cmp;
 use crate::fmt::{self, Debug, Formatter};
-use crate::mem::MaybeUninit;
+use crate::io::{Result, Write};
+use crate::mem::{self, MaybeUninit};
+use crate::{cmp, ptr};
 
-/// A wrapper around a byte buffer that is incrementally filled and initialized.
+/// A borrowed byte buffer which is incrementally filled and initialized.
 ///
 /// This type is a sort of "double cursor". It tracks three regions in the buffer: a region at the beginning of the
 /// buffer that has been logically filled with data, a region that has been initialized at some point but not yet
@@ -32,226 +33,289 @@ use crate::mem::MaybeUninit;
 /// [ filled |         unfilled         ]
 /// [    initialized    | uninitialized ]
 /// ```
-pub struct ReadBuf<'a> {
-    buf: &'a mut [MaybeUninit<u8>],
+///
+/// A `BorrowedBuf` is created around some existing data (or capacity for data) via a unique reference
+/// (`&mut`). The `BorrowedBuf` can be configured (e.g., using `clear` or `set_init`), but cannot be
+/// directly written. To write into the buffer, use `unfilled` to create a `BorrowedCursor`. The cursor
+/// has write-only access to the unfilled portion of the buffer (you can think of it as a
+/// write-only iterator).
+///
+/// The lifetime `'data` is a bound on the lifetime of the underlying data.
+pub struct BorrowedBuf<'data> {
+    /// The buffer's underlying data.
+    buf: &'data mut [MaybeUninit<u8>],
+    /// The length of `self.buf` which is known to be filled.
     filled: usize,
-    initialized: usize,
+    /// The length of `self.buf` which is known to be initialized.
+    init: usize,
 }
 
-impl Debug for ReadBuf<'_> {
+impl Debug for BorrowedBuf<'_> {
     fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
-        f.debug_struct("ReadBuf")
-            .field("init", &self.initialized())
+        f.debug_struct("BorrowedBuf")
+            .field("init", &self.init)
             .field("filled", &self.filled)
             .field("capacity", &self.capacity())
             .finish()
     }
 }
 
-impl<'a> ReadBuf<'a> {
-    /// Creates a new `ReadBuf` from a fully initialized buffer.
+/// Create a new `BorrowedBuf` from a fully initialized slice.
+impl<'data> From<&'data mut [u8]> for BorrowedBuf<'data> {
     #[inline]
-    pub fn new(buf: &'a mut [u8]) -> ReadBuf<'a> {
-        let len = buf.len();
+    fn from(slice: &'data mut [u8]) -> BorrowedBuf<'data> {
+        let len = slice.len();
 
-        ReadBuf {
-            //SAFETY: initialized data never becoming uninitialized is an invariant of ReadBuf
-            buf: unsafe { (buf as *mut [u8]).as_uninit_slice_mut().unwrap() },
+        BorrowedBuf {
+            // SAFETY: initialized data never becoming uninitialized is an invariant of BorrowedBuf
+            buf: unsafe { (slice as *mut [u8]).as_uninit_slice_mut().unwrap() },
             filled: 0,
-            initialized: len,
+            init: len,
         }
     }
+}
 
-    /// Creates a new `ReadBuf` from a fully uninitialized buffer.
-    ///
-    /// Use `assume_init` if part of the buffer is known to be already initialized.
+/// Create a new `BorrowedBuf` from an uninitialized buffer.
+///
+/// Use `set_init` if part of the buffer is known to be already initialized.
+impl<'data> From<&'data mut [MaybeUninit<u8>]> for BorrowedBuf<'data> {
     #[inline]
-    pub fn uninit(buf: &'a mut [MaybeUninit<u8>]) -> ReadBuf<'a> {
-        ReadBuf { buf, filled: 0, initialized: 0 }
+    fn from(buf: &'data mut [MaybeUninit<u8>]) -> BorrowedBuf<'data> {
+        BorrowedBuf { buf, filled: 0, init: 0 }
     }
+}
 
+impl<'data> BorrowedBuf<'data> {
     /// Returns the total capacity of the buffer.
     #[inline]
     pub fn capacity(&self) -> usize {
         self.buf.len()
     }
 
+    /// Returns the length of the filled part of the buffer.
+    #[inline]
+    pub fn len(&self) -> usize {
+        self.filled
+    }
+
+    /// Returns the length of the initialized part of the buffer.
+    #[inline]
+    pub fn init_len(&self) -> usize {
+        self.init
+    }
+
     /// Returns a shared reference to the filled portion of the buffer.
     #[inline]
     pub fn filled(&self) -> &[u8] {
-        //SAFETY: We only slice the filled part of the buffer, which is always valid
+        // SAFETY: We only slice the filled part of the buffer, which is always valid
         unsafe { MaybeUninit::slice_assume_init_ref(&self.buf[0..self.filled]) }
     }
 
-    /// Returns a mutable reference to the filled portion of the buffer.
+    /// Returns a cursor over the unfilled part of the buffer.
     #[inline]
-    pub fn filled_mut(&mut self) -> &mut [u8] {
-        //SAFETY: We only slice the filled part of the buffer, which is always valid
-        unsafe { MaybeUninit::slice_assume_init_mut(&mut self.buf[0..self.filled]) }
+    pub fn unfilled<'this>(&'this mut self) -> BorrowedCursor<'this> {
+        BorrowedCursor {
+            start: self.filled,
+            // SAFETY: we never assign into `BorrowedCursor::buf`, so treating its
+            // lifetime covariantly is safe.
+            buf: unsafe {
+                mem::transmute::<&'this mut BorrowedBuf<'data>, &'this mut BorrowedBuf<'this>>(self)
+            },
+        }
     }
 
-    /// Returns a shared reference to the initialized portion of the buffer.
+    /// Clears the buffer, resetting the filled region to empty.
     ///
-    /// This includes the filled portion.
+    /// The number of initialized bytes is not changed, and the contents of the buffer are not modified.
     #[inline]
-    pub fn initialized(&self) -> &[u8] {
-        //SAFETY: We only slice the initialized part of the buffer, which is always valid
-        unsafe { MaybeUninit::slice_assume_init_ref(&self.buf[0..self.initialized]) }
+    pub fn clear(&mut self) -> &mut Self {
+        self.filled = 0;
+        self
     }
 
-    /// Returns a mutable reference to the initialized portion of the buffer.
+    /// Asserts that the first `n` bytes of the buffer are initialized.
     ///
-    /// This includes the filled portion.
-    #[inline]
-    pub fn initialized_mut(&mut self) -> &mut [u8] {
-        //SAFETY: We only slice the initialized part of the buffer, which is always valid
-        unsafe { MaybeUninit::slice_assume_init_mut(&mut self.buf[0..self.initialized]) }
-    }
-
-    /// Returns a mutable reference to the unfilled part of the buffer without ensuring that it has been fully
-    /// initialized.
+    /// `BorrowedBuf` assumes that bytes are never de-initialized, so this method does nothing when called with fewer
+    /// bytes than are already known to be initialized.
     ///
     /// # Safety
     ///
-    /// The caller must not de-initialize portions of the buffer that have already been initialized.
+    /// The caller must ensure that the first `n` unfilled bytes of the buffer have already been initialized.
     #[inline]
-    pub unsafe fn unfilled_mut(&mut self) -> &mut [MaybeUninit<u8>] {
-        &mut self.buf[self.filled..]
+    pub unsafe fn set_init(&mut self, n: usize) -> &mut Self {
+        self.init = cmp::max(self.init, n);
+        self
     }
+}
+
+/// A writeable view of the unfilled portion of a [`BorrowedBuf`](BorrowedBuf).
+///
+/// Provides access to the initialized and uninitialized parts of the underlying `BorrowedBuf`.
+/// Data can be written directly to the cursor by using [`append`](BorrowedCursor::append) or
+/// indirectly by getting a slice of part or all of the cursor and writing into the slice. In the
+/// indirect case, the caller must call [`advance`](BorrowedCursor::advance) after writing to inform
+/// the cursor how many bytes have been written.
+///
+/// Once data is written to the cursor, it becomes part of the filled portion of the underlying
+/// `BorrowedBuf` and can no longer be accessed or re-written by the cursor. I.e., the cursor tracks
+/// the unfilled part of the underlying `BorrowedBuf`.
+///
+/// The lifetime `'a` is a bound on the lifetime of the underlying buffer (which means it is a bound
+/// on the data in that buffer by transitivity).
+#[derive(Debug)]
+pub struct BorrowedCursor<'a> {
+    /// The underlying buffer.
+    // Safety invariant: we treat the type of buf as covariant in the lifetime of `BorrowedBuf` when
+    // we create a `BorrowedCursor`. This is only safe if we never replace `buf` by assigning into
+    // it, so don't do that!
+    buf: &'a mut BorrowedBuf<'a>,
+    /// The length of the filled portion of the underlying buffer at the time of the cursor's
+    /// creation.
+    start: usize,
+}
 
-    /// Returns a mutable reference to the uninitialized part of the buffer.
+impl<'a> BorrowedCursor<'a> {
+    /// Reborrow this cursor by cloning it with a smaller lifetime.
     ///
-    /// It is safe to uninitialize any of these bytes.
+    /// Since a cursor maintains unique access to its underlying buffer, the borrowed cursor is
+    /// not accessible while the new cursor exists.
     #[inline]
-    pub fn uninitialized_mut(&mut self) -> &mut [MaybeUninit<u8>] {
-        &mut self.buf[self.initialized..]
+    pub fn reborrow<'this>(&'this mut self) -> BorrowedCursor<'this> {
+        BorrowedCursor {
+            // SAFETY: we never assign into `BorrowedCursor::buf`, so treating its
+            // lifetime covariantly is safe.
+            buf: unsafe {
+                mem::transmute::<&'this mut BorrowedBuf<'a>, &'this mut BorrowedBuf<'this>>(
+                    self.buf,
+                )
+            },
+            start: self.start,
+        }
     }
 
-    /// Returns a mutable reference to the unfilled part of the buffer, ensuring it is fully initialized.
-    ///
-    /// Since `ReadBuf` tracks the region of the buffer that has been initialized, this is effectively "free" after
-    /// the first use.
+    /// Returns the available space in the cursor.
     #[inline]
-    pub fn initialize_unfilled(&mut self) -> &mut [u8] {
-        // should optimize out the assertion
-        self.initialize_unfilled_to(self.remaining())
+    pub fn capacity(&self) -> usize {
+        self.buf.capacity() - self.buf.filled
     }
 
-    /// Returns a mutable reference to the first `n` bytes of the unfilled part of the buffer, ensuring it is
-    /// fully initialized.
-    ///
-    /// # Panics
+    /// Returns the number of bytes written to this cursor since it was created from a `BorrowedBuf`.
     ///
-    /// Panics if `self.remaining()` is less than `n`.
+    /// Note that if this cursor is a reborrowed clone of another, then the count returned is the
+    /// count written via either cursor, not the count since the cursor was reborrowed.
     #[inline]
-    pub fn initialize_unfilled_to(&mut self, n: usize) -> &mut [u8] {
-        assert!(self.remaining() >= n);
-
-        let extra_init = self.initialized - self.filled;
-        // If we don't have enough initialized, do zeroing
-        if n > extra_init {
-            let uninit = n - extra_init;
-            let unfilled = &mut self.uninitialized_mut()[0..uninit];
-
-            for byte in unfilled.iter_mut() {
-                byte.write(0);
-            }
-
-            // SAFETY: we just initialized uninit bytes, and the previous bytes were already init
-            unsafe {
-                self.assume_init(n);
-            }
-        }
-
-        let filled = self.filled;
+    pub fn written(&self) -> usize {
+        self.buf.filled - self.start
+    }
 
-        &mut self.initialized_mut()[filled..filled + n]
+    /// Returns a shared reference to the initialized portion of the cursor.
+    #[inline]
+    pub fn init_ref(&self) -> &[u8] {
+        // SAFETY: We only slice the initialized part of the buffer, which is always valid
+        unsafe { MaybeUninit::slice_assume_init_ref(&self.buf.buf[self.buf.filled..self.buf.init]) }
     }
 
-    /// Returns the number of bytes at the end of the slice that have not yet been filled.
+    /// Returns a mutable reference to the initialized portion of the cursor.
     #[inline]
-    pub fn remaining(&self) -> usize {
-        self.capacity() - self.filled
+    pub fn init_mut(&mut self) -> &mut [u8] {
+        // SAFETY: We only slice the initialized part of the buffer, which is always valid
+        unsafe {
+            MaybeUninit::slice_assume_init_mut(&mut self.buf.buf[self.buf.filled..self.buf.init])
+        }
     }
 
-    /// Clears the buffer, resetting the filled region to empty.
+    /// Returns a mutable reference to the uninitialized part of the cursor.
     ///
-    /// The number of initialized bytes is not changed, and the contents of the buffer are not modified.
+    /// It is safe to uninitialize any of these bytes.
     #[inline]
-    pub fn clear(&mut self) {
-        self.set_filled(0); // The assertion in `set_filled` is optimized out
+    pub fn uninit_mut(&mut self) -> &mut [MaybeUninit<u8>] {
+        &mut self.buf.buf[self.buf.init..]
     }
 
-    /// Increases the size of the filled region of the buffer.
-    ///
-    /// The number of initialized bytes is not changed.
+    /// Returns a mutable reference to the whole cursor.
     ///
-    /// # Panics
+    /// # Safety
     ///
-    /// Panics if the filled region of the buffer would become larger than the initialized region.
+    /// The caller must not uninitialize any bytes in the initialized portion of the cursor.
     #[inline]
-    pub fn add_filled(&mut self, n: usize) {
-        self.set_filled(self.filled + n);
+    pub unsafe fn as_mut(&mut self) -> &mut [MaybeUninit<u8>] {
+        &mut self.buf.buf[self.buf.filled..]
     }
 
-    /// Sets the size of the filled region of the buffer.
+    /// Advance the cursor by asserting that `n` bytes have been filled.
     ///
-    /// The number of initialized bytes is not changed.
+    /// After advancing, the `n` bytes are no longer accessible via the cursor and can only be
+    /// accessed via the underlying buffer. I.e., the buffer's filled portion grows by `n` elements
+    /// and its unfilled portion (and the capacity of this cursor) shrinks by `n` elements.
     ///
-    /// Note that this can be used to *shrink* the filled region of the buffer in addition to growing it (for
-    /// example, by a `Read` implementation that compresses data in-place).
-    ///
-    /// # Panics
+    /// # Safety
     ///
-    /// Panics if the filled region of the buffer would become larger than the initialized region.
+    /// The caller must ensure that the first `n` bytes of the cursor have been properly
+    /// initialised.
+    #[inline]
+    pub unsafe fn advance(&mut self, n: usize) -> &mut Self {
+        self.buf.filled += n;
+        self.buf.init = cmp::max(self.buf.init, self.buf.filled);
+        self
+    }
+
+    /// Initializes all bytes in the cursor.
     #[inline]
-    pub fn set_filled(&mut self, n: usize) {
-        assert!(n <= self.initialized);
+    pub fn ensure_init(&mut self) -> &mut Self {
+        let uninit = self.uninit_mut();
+        // SAFETY: 0 is a valid value for MaybeUninit<u8> and the length matches the allocation
+        // since it is comes from a slice reference.
+        unsafe {
+            ptr::write_bytes(uninit.as_mut_ptr(), 0, uninit.len());
+        }
+        self.buf.init = self.buf.capacity();
 
-        self.filled = n;
+        self
     }
 
-    /// Asserts that the first `n` unfilled bytes of the buffer are initialized.
+    /// Asserts that the first `n` unfilled bytes of the cursor are initialized.
     ///
-    /// `ReadBuf` assumes that bytes are never de-initialized, so this method does nothing when called with fewer
-    /// bytes than are already known to be initialized.
+    /// `BorrowedBuf` assumes that bytes are never de-initialized, so this method does nothing when
+    /// called with fewer bytes than are already known to be initialized.
     ///
     /// # Safety
     ///
-    /// The caller must ensure that the first `n` unfilled bytes of the buffer have already been initialized.
+    /// The caller must ensure that the first `n` bytes of the buffer have already been initialized.
     #[inline]
-    pub unsafe fn assume_init(&mut self, n: usize) {
-        self.initialized = cmp::max(self.initialized, self.filled + n);
+    pub unsafe fn set_init(&mut self, n: usize) -> &mut Self {
+        self.buf.init = cmp::max(self.buf.init, self.buf.filled + n);
+        self
     }
 
-    /// Appends data to the buffer, advancing the written position and possibly also the initialized position.
+    /// Appends data to the cursor, advancing position within its buffer.
     ///
     /// # Panics
     ///
-    /// Panics if `self.remaining()` is less than `buf.len()`.
+    /// Panics if `self.capacity()` is less than `buf.len()`.
     #[inline]
     pub fn append(&mut self, buf: &[u8]) {
-        assert!(self.remaining() >= buf.len());
+        assert!(self.capacity() >= buf.len());
 
         // SAFETY: we do not de-initialize any of the elements of the slice
         unsafe {
-            MaybeUninit::write_slice(&mut self.unfilled_mut()[..buf.len()], buf);
+            MaybeUninit::write_slice(&mut self.as_mut()[..buf.len()], buf);
         }
 
         // SAFETY: We just added the entire contents of buf to the filled section.
-        unsafe { self.assume_init(buf.len()) }
-        self.add_filled(buf.len());
+        unsafe {
+            self.set_init(buf.len());
+        }
+        self.buf.filled += buf.len();
     }
+}
 
-    /// Returns the amount of bytes that have been filled.
-    #[inline]
-    pub fn filled_len(&self) -> usize {
-        self.filled
+impl<'a> Write for BorrowedCursor<'a> {
+    fn write(&mut self, buf: &[u8]) -> Result<usize> {
+        self.append(buf);
+        Ok(buf.len())
     }
 
-    /// Returns the amount of bytes that have been initialized.
-    #[inline]
-    pub fn initialized_len(&self) -> usize {
-        self.initialized
+    fn flush(&mut self) -> Result<()> {
+        Ok(())
     }
 }
diff --git a/sgx_tstd/src/io/stdio.rs b/sgx_tstd/src/io/stdio.rs
index 8a18478f..646d0bd6 100644
--- a/sgx_tstd/src/io/stdio.rs
+++ b/sgx_tstd/src/io/stdio.rs
@@ -17,14 +17,37 @@
 
 use crate::io::prelude::*;
 
-use crate::cell::RefCell;
+use crate::cell::{Cell, RefCell};
 use crate::fmt;
+use crate::fs::File;
 use crate::io::{self, BufReader, IoSlice, IoSliceMut, LineWriter, Lines};
-use crate::lazy::SyncOnceCell;
-use crate::pin::Pin;
-use crate::sync::{SgxMutex as Mutex, SgxMutexGuard as MutexGuard};
+use crate::sync::atomic::{AtomicBool, Ordering};
+use crate::sync::{Arc, SgxMutex as Mutex, SgxMutexGuard as MutexGuard, OnceLock};
 use crate::sys::stdio;
-use crate::sys_common::remutex::{SgxReentrantMutex as ReentrantMutex, SgxReentrantMutexGuard as ReentrantMutexGuard};
+use crate::sys_common::remutex::{ReentrantMutex, ReentrantMutexGuard};
+
+type LocalStream = Arc<Mutex<Vec<u8>>>;
+
+thread_local! {
+    /// Used by the test crate to capture the output of the print macros and panics.
+    static OUTPUT_CAPTURE: Cell<Option<LocalStream>> = {
+        Cell::new(None)
+    }
+}
+
+/// Flag to indicate OUTPUT_CAPTURE is used.
+///
+/// If it is None and was never set on any thread, this flag is set to false,
+/// and OUTPUT_CAPTURE can be safely ignored on all threads, saving some time
+/// and memory registering an unused thread local.
+///
+/// Note about memory ordering: This contains information about whether a
+/// thread local variable might be in use. Although this is a global flag, the
+/// memory ordering between threads does not matter: we only want this flag to
+/// have a consistent order between set_output_capture and print_to *within
+/// the same thread*. Within the same thread, things always have a perfectly
+/// consistent order. So Ordering::Relaxed is fine.
+static OUTPUT_CAPTURE_USED: AtomicBool = AtomicBool::new(false);
 
 /// A handle to a raw instance of the standard input stream of this process.
 ///
@@ -187,12 +210,18 @@ fn handle_ebadf<T>(r: io::Result<T>, default: T) -> io::Result<T> {
 ///
 /// [`io::stdin`]: stdin
 ///
-/// ### Note: Windows Portability Consideration
+/// ### Note: Windows Portability Considerations
 ///
 /// When operating in a console, the Windows implementation of this stream does not support
 /// non-UTF-8 byte sequences. Attempting to read bytes that are not valid UTF-8 will return
 /// an error.
 ///
+/// In a process with a detached console, such as one using
+/// `#![windows_subsystem = "windows"]`, or in a child process spawned from such a process,
+/// the contained handle will be null. In such cases, the standard library's `Read` and
+/// `Write` will do nothing and silently succeed. All other I/O operations, via the
+/// standard library or via raw Windows API calls, will fail.
+///
 /// # Examples
 ///
 /// ```no_run
@@ -200,7 +229,7 @@ fn handle_ebadf<T>(r: io::Result<T>, default: T) -> io::Result<T> {
 ///
 /// fn main() -> io::Result<()> {
 ///     let mut buffer = String::new();
-///     let mut stdin = io::stdin(); // We get `Stdin` here.
+///     let stdin = io::stdin(); // We get `Stdin` here.
 ///     stdin.read_line(&mut buffer)?;
 ///     Ok(())
 /// }
@@ -214,12 +243,18 @@ pub struct Stdin {
 /// This handle implements both the [`Read`] and [`BufRead`] traits, and
 /// is constructed via the [`Stdin::lock`] method.
 ///
-/// ### Note: Windows Portability Consideration
+/// ### Note: Windows Portability Considerations
 ///
 /// When operating in a console, the Windows implementation of this stream does not support
 /// non-UTF-8 byte sequences. Attempting to read bytes that are not valid UTF-8 will return
 /// an error.
 ///
+/// In a process with a detached console, such as one using
+/// `#![windows_subsystem = "windows"]`, or in a child process spawned from such a process,
+/// the contained handle will be null. In such cases, the standard library's `Read` and
+/// `Write` will do nothing and silently succeed. All other I/O operations, via the
+/// standard library or via raw Windows API calls, will fail.
+///
 /// # Examples
 ///
 /// ```no_run
@@ -246,11 +281,18 @@ pub struct StdinLock<'a> {
 /// is synchronized via a mutex. If you need more explicit control over
 /// locking, see the [`Stdin::lock`] method.
 ///
-/// ### Note: Windows Portability Consideration
+/// ### Note: Windows Portability Considerations
+///
 /// When operating in a console, the Windows implementation of this stream does not support
 /// non-UTF-8 byte sequences. Attempting to read bytes that are not valid UTF-8 will return
 /// an error.
 ///
+/// In a process with a detached console, such as one using
+/// `#![windows_subsystem = "windows"]`, or in a child process spawned from such a process,
+/// the contained handle will be null. In such cases, the standard library's `Read` and
+/// `Write` will do nothing and silently succeed. All other I/O operations, via the
+/// standard library or via raw Windows API calls, will fail.
+///
 /// # Examples
 ///
 /// Using implicit synchronization:
@@ -281,7 +323,7 @@ pub struct StdinLock<'a> {
 /// ```
 #[must_use]
 pub fn stdin() -> Stdin {
-    static INSTANCE: SyncOnceCell<Mutex<BufReader<StdinRaw>>> = SyncOnceCell::new();
+    static INSTANCE: OnceLock<Mutex<BufReader<StdinRaw>>> = OnceLock::new();
     Stdin {
         inner: INSTANCE.get_or_init(|| {
             Mutex::new(BufReader::with_capacity(stdio::STDIN_BUF_SIZE, stdin_raw()))
@@ -289,47 +331,6 @@ pub fn stdin() -> Stdin {
     }
 }
 
-/// Constructs a new locked handle to the standard input of the current
-/// process.
-///
-/// Each handle returned is a guard granting locked access to a shared
-/// global buffer whose access is synchronized via a mutex. If you need
-/// more explicit control over locking, for example, in a multi-threaded
-/// program, use the [`io::stdin`] function to obtain an unlocked handle,
-/// along with the [`Stdin::lock`] method.
-///
-/// The lock is released when the returned guard goes out of scope. The
-/// returned guard also implements the [`Read`] and [`BufRead`] traits for
-/// accessing the underlying data.
-///
-/// **Note**: The mutex locked by this handle is not reentrant. Even in a
-/// single-threaded program, calling other code that accesses [`Stdin`]
-/// could cause a deadlock or panic, if this locked handle is held across
-/// that call.
-///
-/// ### Note: Windows Portability Consideration
-/// When operating in a console, the Windows implementation of this stream does not support
-/// non-UTF-8 byte sequences. Attempting to read bytes that are not valid UTF-8 will return
-/// an error.
-///
-/// # Examples
-///
-/// ```no_run
-/// #![feature(stdio_locked)]
-/// use std::io::{self, BufRead};
-///
-/// fn main() -> io::Result<()> {
-///     let mut buffer = String::new();
-///     let mut handle = io::stdin_locked();
-///
-///     handle.read_line(&mut buffer)?;
-///     Ok(())
-/// }
-/// ```
-pub fn stdin_locked() -> StdinLock<'static> {
-    stdin().into_locked()
-}
-
 impl Stdin {
     /// Locks this handle to the standard input stream, returning a readable
     /// guard.
@@ -352,8 +353,10 @@ impl Stdin {
     ///     Ok(())
     /// }
     /// ```
-    pub fn lock(&self) -> StdinLock<'_> {
-        self.lock_any()
+    pub fn lock(&self) -> StdinLock<'static> {
+        // Locks this handle with 'static lifetime. This depends on the
+        // implementation detail that the underlying `Mutex` is static.
+        StdinLock { inner: self.inner.lock().unwrap_or_else(|e| e.into_inner()) }
     }
 
     /// Locks this handle and reads a line of input, appending it to the specified buffer.
@@ -369,10 +372,10 @@ impl Stdin {
     /// let mut input = String::new();
     /// match io::stdin().read_line(&mut input) {
     ///     Ok(n) => {
-    ///         println!("{} bytes read", n);
-    ///         println!("{}", input);
+    ///         println!("{n} bytes read");
+    ///         println!("{input}");
     ///     }
-    ///     Err(error) => println!("error: {}", error),
+    ///     Err(error) => println!("error: {error}"),
     /// }
     /// ```
     ///
@@ -386,42 +389,6 @@ impl Stdin {
         self.lock().read_line(buf)
     }
 
-    // Locks this handle with any lifetime. This depends on the
-    // implementation detail that the underlying `Mutex` is static.
-    fn lock_any<'a>(&self) -> StdinLock<'a> {
-        StdinLock { inner: self.inner.lock().unwrap_or_else(|e| e.into_inner()) }
-    }
-
-    /// Consumes this handle to the standard input stream, locking the
-    /// shared global buffer associated with the stream and returning a
-    /// readable guard.
-    ///
-    /// The lock is released when the returned guard goes out of scope. The
-    /// returned guard also implements the [`Read`] and [`BufRead`] traits
-    /// for accessing the underlying data.
-    ///
-    /// It is often simpler to directly get a locked handle using the
-    /// [`stdin_locked`] function instead, unless nearby code also needs to
-    /// use an unlocked handle.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// #![feature(stdio_locked)]
-    /// use std::io::{self, BufRead};
-    ///
-    /// fn main() -> io::Result<()> {
-    ///     let mut buffer = String::new();
-    ///     let mut handle = io::stdin().into_locked();
-    ///
-    ///     handle.read_line(&mut buffer)?;
-    ///     Ok(())
-    /// }
-    /// ```
-    pub fn into_locked(self) -> StdinLock<'static> {
-        self.lock_any()
-    }
-
     /// Consumes this handle and returns an iterator over input lines.
     ///
     /// For detailed semantics of this method, see the documentation on
@@ -430,7 +397,6 @@ impl Stdin {
     /// # Examples
     ///
     /// ```no_run
-    /// #![feature(stdin_forwarders)]
     /// use std::io;
     ///
     /// let lines = io::stdin().lines();
@@ -440,7 +406,7 @@ impl Stdin {
     /// ```
     #[must_use = "`self` will be dropped if the result is not used"]
     pub fn lines(self) -> Lines<StdinLock<'static>> {
-        self.into_locked().lines()
+        self.lock().lines()
     }
 }
 
@@ -538,18 +504,25 @@ impl fmt::Debug for StdinLock<'_> {
 ///
 /// Created by the [`io::stdout`] method.
 ///
-/// ### Note: Windows Portability Consideration
+/// ### Note: Windows Portability Considerations
+///
 /// When operating in a console, the Windows implementation of this stream does not support
 /// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return
 /// an error.
 ///
+/// In a process with a detached console, such as one using
+/// `#![windows_subsystem = "windows"]`, or in a child process spawned from such a process,
+/// the contained handle will be null. In such cases, the standard library's `Read` and
+/// `Write` will do nothing and silently succeed. All other I/O operations, via the
+/// standard library or via raw Windows API calls, will fail.
+///
 /// [`lock`]: Stdout::lock
 /// [`io::stdout`]: stdout
 pub struct Stdout {
     // FIXME: this should be LineWriter or BufWriter depending on the state of
     //        stdout (tty or not). Note that if this is not line buffered it
     //        should also flush-on-panic or some form of flush-on-abort.
-    inner: Pin<&'static ReentrantMutex<RefCell<LineWriter<StdoutRaw>>>>,
+    inner: &'static ReentrantMutex<RefCell<LineWriter<StdoutRaw>>>,
 }
 
 /// A locked reference to the [`Stdout`] handle.
@@ -557,16 +530,23 @@ pub struct Stdout {
 /// This handle implements the [`Write`] trait, and is constructed via
 /// the [`Stdout::lock`] method. See its documentation for more.
 ///
-/// ### Note: Windows Portability Consideration
+/// ### Note: Windows Portability Considerations
+///
 /// When operating in a console, the Windows implementation of this stream does not support
 /// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return
 /// an error.
+///
+/// In a process with a detached console, such as one using
+/// `#![windows_subsystem = "windows"]`, or in a child process spawned from such a process,
+/// the contained handle will be null. In such cases, the standard library's `Read` and
+/// `Write` will do nothing and silently succeed. All other I/O operations, via the
+/// standard library or via raw Windows API calls, will fail.
 #[must_use = "if unused stdout will immediately unlock"]
 pub struct StdoutLock<'a> {
     inner: ReentrantMutexGuard<'a, RefCell<LineWriter<StdoutRaw>>>,
 }
 
-static STDOUT: SyncOnceCell<ReentrantMutex<RefCell<LineWriter<StdoutRaw>>>> = SyncOnceCell::new();
+static STDOUT: OnceLock<ReentrantMutex<RefCell<LineWriter<StdoutRaw>>>> = OnceLock::new();
 
 /// Constructs a new handle to the standard output of the current process.
 ///
@@ -574,11 +554,18 @@ static STDOUT: SyncOnceCell<ReentrantMutex<RefCell<LineWriter<StdoutRaw>>>> = Sy
 /// is synchronized via a mutex. If you need more explicit control over
 /// locking, see the [`Stdout::lock`] method.
 ///
-/// ### Note: Windows Portability Consideration
+/// ### Note: Windows Portability Considerations
+///
 /// When operating in a console, the Windows implementation of this stream does not support
 /// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return
 /// an error.
 ///
+/// In a process with a detached console, such as one using
+/// `#![windows_subsystem = "windows"]`, or in a child process spawned from such a process,
+/// the contained handle will be null. In such cases, the standard library's `Read` and
+/// `Write` will do nothing and silently succeed. All other I/O operations, via the
+/// standard library or via raw Windows API calls, will fail.
+///
 /// # Examples
 ///
 /// Using implicit synchronization:
@@ -610,57 +597,27 @@ static STDOUT: SyncOnceCell<ReentrantMutex<RefCell<LineWriter<StdoutRaw>>>> = Sy
 #[must_use]
 pub fn stdout() -> Stdout {
     Stdout {
-        inner: Pin::static_ref(&STDOUT).get_or_init_pin(
-            || ReentrantMutex::new(RefCell::new(LineWriter::new(stdout_raw()))),
-            |_| (),
-        ),
+        inner: STDOUT
+            .get_or_init(|| ReentrantMutex::new(RefCell::new(LineWriter::new(stdout_raw())))),
     }
 }
 
-/// Constructs a new locked handle to the standard output of the current
-/// process.
-///
-/// Each handle returned is a guard granting locked access to a shared
-/// global buffer whose access is synchronized via a mutex. If you need
-/// more explicit control over locking, for example, in a multi-threaded
-/// program, use the [`io::stdout`] function to obtain an unlocked handle,
-/// along with the [`Stdout::lock`] method.
-///
-/// The lock is released when the returned guard goes out of scope. The
-/// returned guard also implements the [`Write`] trait for writing data.
-///
-/// ### Note: Windows Portability Consideration
-/// When operating in a console, the Windows implementation of this stream does not support
-/// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return
-/// an error.
-///
-/// # Examples
-///
-/// ```no_run
-/// #![feature(stdio_locked)]
-/// use std::io::{self, Write};
-///
-/// fn main() -> io::Result<()> {
-///     let mut handle = io::stdout_locked();
-///
-///     handle.write_all(b"hello world")?;
-///
-///     Ok(())
-/// }
-/// ```
-pub fn stdout_locked() -> StdoutLock<'static> {
-    stdout().into_locked()
-}
-
+// Flush the data and disable buffering during shutdown
+// by replacing the line writer by one with zero
+// buffering capacity.
 pub fn cleanup() {
-    if let Some(instance) = STDOUT.get() {
-        // Flush the data and disable buffering during shutdown
-        // by replacing the line writer by one with zero
-        // buffering capacity.
+    let mut initialized = false;
+    let stdout = STDOUT.get_or_init(|| {
+        initialized = true;
+        ReentrantMutex::new(RefCell::new(LineWriter::with_capacity(0, stdout_raw())))
+    });
+
+    if !initialized {
+        // The buffer was previously initialized, overwrite it here.
         // We use try_lock() instead of lock(), because someone
         // might have leaked a StdoutLock, which would
         // otherwise cause a deadlock here.
-        if let Some(lock) = Pin::static_ref(instance).try_lock() {
+        if let Some(lock) = stdout.try_lock() {
             *lock.borrow_mut() = LineWriter::with_capacity(0, stdout_raw());
         }
     }
@@ -679,53 +636,19 @@ impl Stdout {
     /// use std::io::{self, Write};
     ///
     /// fn main() -> io::Result<()> {
-    ///     let stdout = io::stdout();
-    ///     let mut handle = stdout.lock();
+    ///     let mut stdout = io::stdout().lock();
     ///
-    ///     handle.write_all(b"hello world")?;
+    ///     stdout.write_all(b"hello world")?;
     ///
     ///     Ok(())
     /// }
     /// ```
-    pub fn lock(&self) -> StdoutLock<'_> {
-        self.lock_any()
-    }
-
-    // Locks this handle with any lifetime. This depends on the
-    // implementation detail that the underlying `ReentrantMutex` is
-    // static.
-    fn lock_any<'a>(&self) -> StdoutLock<'a> {
+    pub fn lock(&self) -> StdoutLock<'static> {
+        // Locks this handle with 'static lifetime. This depends on the
+        // implementation detail that the underlying `ReentrantMutex` is
+        // static.
         StdoutLock { inner: self.inner.lock() }
     }
-
-    /// Consumes this handle to the standard output stream, locking the
-    /// shared global buffer associated with the stream and returning a
-    /// writable guard.
-    ///
-    /// The lock is released when the returned lock goes out of scope. The
-    /// returned guard also implements the [`Write`] trait for writing data.
-    ///
-    /// It is often simpler to directly get a locked handle using the
-    /// [`io::stdout_locked`] function instead, unless nearby code also
-    /// needs to use an unlocked handle.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// #![feature(stdio_locked)]
-    /// use std::io::{self, Write};
-    ///
-    /// fn main() -> io::Result<()> {
-    ///     let mut handle = io::stdout().into_locked();
-    ///
-    ///     handle.write_all(b"hello world")?;
-    ///
-    ///     Ok(())
-    /// }
-    /// ```
-    pub fn into_locked(self) -> StdoutLock<'static> {
-        self.lock_any()
-    }
 }
 
 impl fmt::Debug for Stdout {
@@ -743,7 +666,7 @@ impl Write for Stdout {
     }
     #[inline]
     fn is_write_vectored(&self) -> bool {
-        io::Write::is_write_vectored(&&*self)
+        io::Write::is_write_vectored(&self)
     }
     fn flush(&mut self) -> io::Result<()> {
         (&*self).flush()
@@ -818,12 +741,19 @@ impl fmt::Debug for StdoutLock<'_> {
 ///
 /// [`io::stderr`]: stderr
 ///
-/// ### Note: Windows Portability Consideration
+/// ### Note: Windows Portability Considerations
+///
 /// When operating in a console, the Windows implementation of this stream does not support
 /// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return
 /// an error.
+///
+/// In a process with a detached console, such as one using
+/// `#![windows_subsystem = "windows"]`, or in a child process spawned from such a process,
+/// the contained handle will be null. In such cases, the standard library's `Read` and
+/// `Write` will do nothing and silently succeed. All other I/O operations, via the
+/// standard library or via raw Windows API calls, will fail.
 pub struct Stderr {
-    inner: Pin<&'static ReentrantMutex<RefCell<StderrRaw>>>,
+    inner: &'static ReentrantMutex<RefCell<StderrRaw>>,
 }
 
 /// A locked reference to the [`Stderr`] handle.
@@ -831,10 +761,17 @@ pub struct Stderr {
 /// This handle implements the [`Write`] trait and is constructed via
 /// the [`Stderr::lock`] method. See its documentation for more.
 ///
-/// ### Note: Windows Portability Consideration
+/// ### Note: Windows Portability Considerations
+///
 /// When operating in a console, the Windows implementation of this stream does not support
 /// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return
 /// an error.
+///
+/// In a process with a detached console, such as one using
+/// `#![windows_subsystem = "windows"]`, or in a child process spawned from such a process,
+/// the contained handle will be null. In such cases, the standard library's `Read` and
+/// `Write` will do nothing and silently succeed. All other I/O operations, via the
+/// standard library or via raw Windows API calls, will fail.
 #[must_use = "if unused stderr will immediately unlock"]
 pub struct StderrLock<'a> {
     inner: ReentrantMutexGuard<'a, RefCell<StderrRaw>>,
@@ -844,11 +781,18 @@ pub struct StderrLock<'a> {
 ///
 /// This handle is not buffered.
 ///
-/// ### Note: Windows Portability Consideration
+/// ### Note: Windows Portability Considerations
+///
 /// When operating in a console, the Windows implementation of this stream does not support
 /// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return
 /// an error.
 ///
+/// In a process with a detached console, such as one using
+/// `#![windows_subsystem = "windows"]`, or in a child process spawned from such a process,
+/// the contained handle will be null. In such cases, the standard library's `Read` and
+/// `Write` will do nothing and silently succeed. All other I/O operations, via the
+/// standard library or via raw Windows API calls, will fail.
+///
 /// # Examples
 ///
 /// Using implicit synchronization:
@@ -880,44 +824,12 @@ pub struct StderrLock<'a> {
 #[must_use]
 pub fn stderr() -> Stderr {
     // Note that unlike `stdout()` we don't use `at_exit` here to register a
-    // destructor. Stderr is not buffered , so there's no need to run a
+    // destructor. Stderr is not buffered, so there's no need to run a
     // destructor for flushing the buffer
-    static INSTANCE: SyncOnceCell<ReentrantMutex<RefCell<StderrRaw>>> = SyncOnceCell::new();
+    static INSTANCE: ReentrantMutex<RefCell<StderrRaw>> =
+        ReentrantMutex::new(RefCell::new(stderr_raw()));
 
-    Stderr {
-        inner: Pin::static_ref(&INSTANCE).get_or_init_pin(
-            || ReentrantMutex::new(RefCell::new(stderr_raw())),
-            |_| (),
-        ),
-    }
-}
-
-/// Constructs a new locked handle to the standard error of the current
-/// process.
-///
-/// This handle is not buffered.
-///
-/// ### Note: Windows Portability Consideration
-/// When operating in a console, the Windows implementation of this stream does not support
-/// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return
-/// an error.
-///
-/// # Example
-///
-/// ```no_run
-/// #![feature(stdio_locked)]
-/// use std::io::{self, Write};
-///
-/// fn main() -> io::Result<()> {
-///     let mut handle = io::stderr_locked();
-///
-///     handle.write_all(b"hello world")?;
-///
-///     Ok(())
-/// }
-/// ```
-pub fn stderr_locked() -> StderrLock<'static> {
-    stderr().into_locked()
+    Stderr { inner: &INSTANCE }
... 14276 lines suppressed ...


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@teaclave.apache.org
For additional commands, e-mail: commits-help@teaclave.apache.org


[incubator-teaclave-sgx-sdk] 02/03: Add epoll_create for sgx_libc

Posted by rd...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rduan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-teaclave-sgx-sdk.git

commit 5346c066d04da618056f116d859be62ad5163eb2
Author: volcano0dr <vo...@163.com>
AuthorDate: Sat Nov 5 17:54:27 2022 +0800

    Add epoll_create for sgx_libc
---
 sgx_libc/src/android/mod.rs        | 2 +-
 sgx_libc/src/linux/x86_64/mod.rs   | 4 +---
 sgx_libc/src/linux/x86_64/ocall.rs | 8 ++++++++
 3 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/sgx_libc/src/android/mod.rs b/sgx_libc/src/android/mod.rs
index 49d57470..010f4f33 100644
--- a/sgx_libc/src/android/mod.rs
+++ b/sgx_libc/src/android/mod.rs
@@ -22,4 +22,4 @@ cfg_if! {
     } else {
 
     }
-}
\ No newline at end of file
+}
diff --git a/sgx_libc/src/linux/x86_64/mod.rs b/sgx_libc/src/linux/x86_64/mod.rs
index 213c2064..104ebb87 100644
--- a/sgx_libc/src/linux/x86_64/mod.rs
+++ b/sgx_libc/src/linux/x86_64/mod.rs
@@ -1649,9 +1649,7 @@ pub unsafe fn CMSG_NXTHDR(mhdr: *const msghdr, cmsg: *const cmsghdr) -> *mut cms
     };
     let next = (cmsg as usize + CMSG_ALIGN((*cmsg).cmsg_len)) as *mut cmsghdr;
     let max = (*mhdr).msg_control as usize + (*mhdr).msg_controllen;
-    if (next.offset(1)) as usize > max
-        || next as usize + CMSG_ALIGN((*next).cmsg_len) > max
-    {
+    if (next.offset(1)) as usize > max || next as usize + CMSG_ALIGN((*next).cmsg_len) > max {
         ptr::null_mut::<cmsghdr>()
     } else {
         next as *mut cmsghdr
diff --git a/sgx_libc/src/linux/x86_64/ocall.rs b/sgx_libc/src/linux/x86_64/ocall.rs
index 422a5f82..b2da65dc 100644
--- a/sgx_libc/src/linux/x86_64/ocall.rs
+++ b/sgx_libc/src/linux/x86_64/ocall.rs
@@ -3599,6 +3599,14 @@ pub unsafe fn poll(fds: *mut pollfd, nfds: nfds_t, timeout: c_int) -> c_int {
     result
 }
 
+pub unsafe fn epoll_create(size: c_int) -> c_int {
+    if size <= 0 {
+        set_errno(EINVAL);
+        return -1;
+    }
+    epoll_create1(0)
+}
+
 pub unsafe fn epoll_create1(flags: c_int) -> c_int {
     let mut result: c_int = 0;
     let mut error: c_int = 0;


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@teaclave.apache.org
For additional commands, e-mail: commits-help@teaclave.apache.org