diff --git a/dockerfile/Dockerfile.1804.nightly b/dockerfile/Dockerfile.1804.nightly index e3ea18874..7618c9807 100644 --- a/dockerfile/Dockerfile.1804.nightly +++ b/dockerfile/Dockerfile.1804.nightly @@ -31,7 +31,7 @@ RUN bash /root/04_psw.sh # Seventh, Rust -ENV rust_toolchain nightly-2021-11-01 +ENV rust_toolchain nightly-2022-02-23 ADD 05_rust.sh /root RUN bash /root/05_rust.sh diff --git a/dockerfile/Dockerfile.2004.nightly b/dockerfile/Dockerfile.2004.nightly index 2ffc20bd2..62036705e 100644 --- a/dockerfile/Dockerfile.2004.nightly +++ b/dockerfile/Dockerfile.2004.nightly @@ -34,7 +34,7 @@ RUN bash /root/04_psw.sh # Seventh, Rust -ENV rust_toolchain nightly-2021-11-01 +ENV rust_toolchain nightly-2022-02-23 ADD 05_rust.sh /root RUN bash /root/05_rust.sh diff --git a/dockerfile/Dockerfile.centos8.nightly b/dockerfile/Dockerfile.centos8.nightly index bd107c2ef..939f94849 100644 --- a/dockerfile/Dockerfile.centos8.nightly +++ b/dockerfile/Dockerfile.centos8.nightly @@ -22,7 +22,7 @@ ENV PSW_REPO="https://download.01.org/intel-sgx/sgx-linux/2.16/distro/centos-str ADD 04_psw_rpm.sh /root RUN bash /root/04_psw_rpm.sh -ENV rust_toolchain nightly-2021-11-01 +ENV rust_toolchain nightly-2022-02-23 ADD 05_rust.sh /root RUN bash /root/05_rust.sh diff --git a/edl/sgx_file.edl b/edl/sgx_file.edl index 07fb1eb17..c70ec599a 100644 --- a/edl/sgx_file.edl +++ b/edl/sgx_file.edl @@ -27,6 +27,7 @@ enclave { untrusted { int u_open_ocall([out] int *error, [in, string] const char *pathname, int flags); int u_open64_ocall([out] int *error, [in, string] const char *path, int oflag, int mode); + int u_openat_ocall([out] int *error, int dirfd, [in, string] const char *pathname, int flags); int u_fstat_ocall([out] int *error, int fd, [out] struct stat_t *buf); int u_fstat64_ocall([out] int *error, int fd, [out] struct stat64_t *buf); @@ -46,6 +47,7 @@ enclave { int u_fchmod_ocall([out] int *error, int fd, uint32_t mode); int u_unlink_ocall([out] int *error, [in, string] const char *pathname); int u_link_ocall([out] int *error, [in, string] const char *oldpath, [in, string] const char *newpath); + int u_unlinkat_ocall([out] int *error, int dirfd, [in, string] const char *pathname, int flags); int u_linkat_ocall([out] int *error, int olddirfd, [in, string] const char *oldpath, int newdirfd, [in, string] const char *newpath, int flags); int u_rename_ocall([out] int *error, [in, string] const char *oldpath, [in, string] const char *newpath); int u_chmod_ocall([out] int *error, [in, string] const char *path, uint32_t mode); @@ -54,6 +56,7 @@ enclave { char *u_realpath_ocall([out] int *error, [in, string] const char *pathname); int u_mkdir_ocall([out] int *error, [in, string] const char *pathname, uint32_t mode); int u_rmdir_ocall([out] int *error, [in, string] const char *pathname); + void *u_fdopendir_ocall([out] int *error, int fd); void *u_opendir_ocall([out] int *error, [in, string] const char *pathname); int u_readdir64_r_ocall([user_check] void *dirp, [in, out] struct dirent64_t *entry, [out] struct dirent64_t **result); int u_closedir_ocall([out] int *error, [user_check] void *dirp); diff --git a/rust-toolchain b/rust-toolchain index 7cc42efde..4e7e21b01 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1 +1 @@ -nightly-2021-11-01 +nightly-2022-02-23 \ No newline at end of file diff --git a/samplecode/backtrace/enclave/Cargo.toml b/samplecode/backtrace/enclave/Cargo.toml index 00b1f7bc2..ef0574e14 100644 --- a/samplecode/backtrace/enclave/Cargo.toml +++ b/samplecode/backtrace/enclave/Cargo.toml @@ -16,6 +16,7 @@ sgx_tstd = { git = "https://github.com/apache/teaclave-sgx-sdk.git", features = sgx_backtrace = { git = "https://github.com/apache/teaclave-sgx-sdk.git" } [patch.'https://github.com/apache/teaclave-sgx-sdk.git'] +sgx_align_struct_attribute = { path = "../../../sgx_align_struct_attribute" } sgx_alloc = { path = "../../../sgx_alloc" } sgx_backtrace = { path = "../../../sgx_backtrace" } sgx_backtrace_sys = { path = "../../../sgx_backtrace_sys" } @@ -24,6 +25,7 @@ sgx_cov = { path = "../../../sgx_cov" } sgx_crypto_helper = { path = "../../../sgx_crypto_helper" } sgx_demangle = { path = "../../../sgx_demangle" } sgx_libc = { path = "../../../sgx_libc" } +sgx_no_tstd = { path = "../../../sgx_no_tstd" } sgx_rand = { path = "../../../sgx_rand" } sgx_rand_derive = { path = "../../../sgx_rand_derive" } sgx_serialize = { path = "../../../sgx_serialize" } diff --git a/samplecode/backtrace/enclave/Xargo.toml b/samplecode/backtrace/enclave/Xargo.toml index abb29c412..13d92c363 100644 --- a/samplecode/backtrace/enclave/Xargo.toml +++ b/samplecode/backtrace/enclave/Xargo.toml @@ -89,6 +89,7 @@ stage = 7 [dependencies.sgx_cov] path = "../../../sgx_cov" stage = 7 + [dependencies.sgx_signal] path = "../../../sgx_signal" stage = 7 diff --git a/samplecode/backtrace/enclave/x86_64-unknown-linux-sgx.json b/samplecode/backtrace/enclave/x86_64-unknown-linux-sgx.json index 69b38be21..53f104e25 100644 --- a/samplecode/backtrace/enclave/x86_64-unknown-linux-sgx.json +++ b/samplecode/backtrace/enclave/x86_64-unknown-linux-sgx.json @@ -1,13 +1,13 @@ { "arch": "x86_64", "cpu": "x86-64", + "crt-static-respected": true, "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128", "dynamic-linking": true, "env": "sgx", - "exe-allocation-crate": "alloc_system", "executables": true, - "has-elf-tls": true, "has-rpath": true, + "has-thread-local": true, "linker-flavor": "gcc", "linker-is-gnu": true, "llvm-target": "x86_64-unknown-linux-gnu", @@ -30,6 +30,13 @@ 1 ] }, + "supported-sanitizers": [ + "address", + "cfi", + "leak", + "memory", + "thread" + ], "target-c-int-width": "32", "target-endian": "little", "target-family": "unix", diff --git a/samplecode/crypto/enclave/Cargo.toml b/samplecode/crypto/enclave/Cargo.toml index b6839c3f6..7bc5264c4 100644 --- a/samplecode/crypto/enclave/Cargo.toml +++ b/samplecode/crypto/enclave/Cargo.toml @@ -17,6 +17,7 @@ sgx_tstd = { git = "https://github.com/apache/teaclave-sgx-sdk.git" } sgx_tcrypto = { git = "https://github.com/apache/teaclave-sgx-sdk.git" } [patch.'https://github.com/apache/teaclave-sgx-sdk.git'] +sgx_align_struct_attribute = { path = "../../../sgx_align_struct_attribute" } sgx_alloc = { path = "../../../sgx_alloc" } sgx_backtrace = { path = "../../../sgx_backtrace" } sgx_backtrace_sys = { path = "../../../sgx_backtrace_sys" } @@ -25,6 +26,7 @@ sgx_cov = { path = "../../../sgx_cov" } sgx_crypto_helper = { path = "../../../sgx_crypto_helper" } sgx_demangle = { path = "../../../sgx_demangle" } sgx_libc = { path = "../../../sgx_libc" } +sgx_no_tstd = { path = "../../../sgx_no_tstd" } sgx_rand = { path = "../../../sgx_rand" } sgx_rand_derive = { path = "../../../sgx_rand_derive" } sgx_serialize = { path = "../../../sgx_serialize" } @@ -41,6 +43,6 @@ sgx_tseal = { path = "../../../sgx_tseal" } sgx_tstd = { path = "../../../sgx_tstd" } sgx_tunittest = { path = "../../../sgx_tunittest" } sgx_types = { path = "../../../sgx_types" } -sgx_ucrypto = { path = "../../../sgx_ucrypto" } +#sgx_ucrypto = { path = "../../../sgx_ucrypto" } sgx_unwind = { path = "../../../sgx_unwind" } -sgx_urts = { path = "../../../sgx_urts" } +#sgx_urts = { path = "../../../sgx_urts" } diff --git a/samplecode/crypto/enclave/x86_64-unknown-linux-sgx.json b/samplecode/crypto/enclave/x86_64-unknown-linux-sgx.json index 69b38be21..53f104e25 100644 --- a/samplecode/crypto/enclave/x86_64-unknown-linux-sgx.json +++ b/samplecode/crypto/enclave/x86_64-unknown-linux-sgx.json @@ -1,13 +1,13 @@ { "arch": "x86_64", "cpu": "x86-64", + "crt-static-respected": true, "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128", "dynamic-linking": true, "env": "sgx", - "exe-allocation-crate": "alloc_system", "executables": true, - "has-elf-tls": true, "has-rpath": true, + "has-thread-local": true, "linker-flavor": "gcc", "linker-is-gnu": true, "llvm-target": "x86_64-unknown-linux-gnu", @@ -30,6 +30,13 @@ 1 ] }, + "supported-sanitizers": [ + "address", + "cfi", + "leak", + "memory", + "thread" + ], "target-c-int-width": "32", "target-endian": "little", "target-family": "unix", diff --git a/samplecode/db-proxy/db-proxy/enclave/Cargo.toml b/samplecode/db-proxy/db-proxy/enclave/Cargo.toml index 7c13f5d2c..9661fe836 100644 --- a/samplecode/db-proxy/db-proxy/enclave/Cargo.toml +++ b/samplecode/db-proxy/db-proxy/enclave/Cargo.toml @@ -15,6 +15,7 @@ sgx_types = { git = "https://github.com/apache/teaclave-sgx-sdk.git" } sgx_tstd = { git = "https://github.com/apache/teaclave-sgx-sdk.git" } [patch.'https://github.com/apache/teaclave-sgx-sdk.git'] +sgx_align_struct_attribute = { path = "../../../../sgx_align_struct_attribute" } sgx_alloc = { path = "../../../../sgx_alloc" } sgx_backtrace = { path = "../../../../sgx_backtrace" } sgx_backtrace_sys = { path = "../../../../sgx_backtrace_sys" } @@ -23,6 +24,7 @@ sgx_cov = { path = "../../../../sgx_cov" } sgx_crypto_helper = { path = "../../../../sgx_crypto_helper" } sgx_demangle = { path = "../../../../sgx_demangle" } sgx_libc = { path = "../../../../sgx_libc" } +sgx_no_tstd = { path = "../../../../sgx_no_tstd" } sgx_rand = { path = "../../../../sgx_rand" } sgx_rand_derive = { path = "../../../../sgx_rand_derive" } sgx_serialize = { path = "../../../../sgx_serialize" } @@ -41,4 +43,4 @@ sgx_tunittest = { path = "../../../../sgx_tunittest" } sgx_types = { path = "../../../../sgx_types" } #sgx_ucrypto = { path = "../../../../sgx_ucrypto" } sgx_unwind = { path = "../../../../sgx_unwind" } -#sgx_urts = { path = "../../../../sgx_urts" } +#sgx_urts = { path = "../../../../sgx_urts" } \ No newline at end of file diff --git a/samplecode/db-proxy/db-proxy/enclave/x86_64-unknown-linux-sgx.json b/samplecode/db-proxy/db-proxy/enclave/x86_64-unknown-linux-sgx.json index 69b38be21..53f104e25 100644 --- a/samplecode/db-proxy/db-proxy/enclave/x86_64-unknown-linux-sgx.json +++ b/samplecode/db-proxy/db-proxy/enclave/x86_64-unknown-linux-sgx.json @@ -1,13 +1,13 @@ { "arch": "x86_64", "cpu": "x86-64", + "crt-static-respected": true, "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128", "dynamic-linking": true, "env": "sgx", - "exe-allocation-crate": "alloc_system", "executables": true, - "has-elf-tls": true, "has-rpath": true, + "has-thread-local": true, "linker-flavor": "gcc", "linker-is-gnu": true, "llvm-target": "x86_64-unknown-linux-gnu", @@ -30,6 +30,13 @@ 1 ] }, + "supported-sanitizers": [ + "address", + "cfi", + "leak", + "memory", + "thread" + ], "target-c-int-width": "32", "target-endian": "little", "target-family": "unix", diff --git a/samplecode/dcap-pckretrieval/enclave/x86_64-unknown-linux-sgx.json b/samplecode/dcap-pckretrieval/enclave/x86_64-unknown-linux-sgx.json index 69b38be21..53f104e25 100644 --- a/samplecode/dcap-pckretrieval/enclave/x86_64-unknown-linux-sgx.json +++ b/samplecode/dcap-pckretrieval/enclave/x86_64-unknown-linux-sgx.json @@ -1,13 +1,13 @@ { "arch": "x86_64", "cpu": "x86-64", + "crt-static-respected": true, "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128", "dynamic-linking": true, "env": "sgx", - "exe-allocation-crate": "alloc_system", "executables": true, - "has-elf-tls": true, "has-rpath": true, + "has-thread-local": true, "linker-flavor": "gcc", "linker-is-gnu": true, "llvm-target": "x86_64-unknown-linux-gnu", @@ -30,6 +30,13 @@ 1 ] }, + "supported-sanitizers": [ + "address", + "cfi", + "leak", + "memory", + "thread" + ], "target-c-int-width": "32", "target-endian": "little", "target-family": "unix", diff --git a/samplecode/file/enclave/Cargo.toml b/samplecode/file/enclave/Cargo.toml index 3bac2bfdc..09ece4c2d 100644 --- a/samplecode/file/enclave/Cargo.toml +++ b/samplecode/file/enclave/Cargo.toml @@ -20,6 +20,7 @@ sgx_rand_derive = { git = "https://github.com/apache/teaclave-sgx-sdk.git" } sgx_serialize_derive = { git = "https://github.com/apache/teaclave-sgx-sdk.git" } [patch.'https://github.com/apache/teaclave-sgx-sdk.git'] +sgx_align_struct_attribute = { path = "../../../sgx_align_struct_attribute" } sgx_alloc = { path = "../../../sgx_alloc" } sgx_backtrace = { path = "../../../sgx_backtrace" } sgx_backtrace_sys = { path = "../../../sgx_backtrace_sys" } @@ -28,6 +29,7 @@ sgx_cov = { path = "../../../sgx_cov" } sgx_crypto_helper = { path = "../../../sgx_crypto_helper" } sgx_demangle = { path = "../../../sgx_demangle" } sgx_libc = { path = "../../../sgx_libc" } +sgx_no_tstd = { path = "../../../sgx_no_tstd" } sgx_rand = { path = "../../../sgx_rand" } sgx_rand_derive = { path = "../../../sgx_rand_derive" } sgx_serialize = { path = "../../../sgx_serialize" } diff --git a/samplecode/file/enclave/x86_64-unknown-linux-sgx.json b/samplecode/file/enclave/x86_64-unknown-linux-sgx.json index 69b38be21..53f104e25 100644 --- a/samplecode/file/enclave/x86_64-unknown-linux-sgx.json +++ b/samplecode/file/enclave/x86_64-unknown-linux-sgx.json @@ -1,13 +1,13 @@ { "arch": "x86_64", "cpu": "x86-64", + "crt-static-respected": true, "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128", "dynamic-linking": true, "env": "sgx", - "exe-allocation-crate": "alloc_system", "executables": true, - "has-elf-tls": true, "has-rpath": true, + "has-thread-local": true, "linker-flavor": "gcc", "linker-is-gnu": true, "llvm-target": "x86_64-unknown-linux-gnu", @@ -30,6 +30,13 @@ 1 ] }, + "supported-sanitizers": [ + "address", + "cfi", + "leak", + "memory", + "thread" + ], "target-c-int-width": "32", "target-endian": "little", "target-family": "unix", diff --git a/samplecode/hello-regex/enclave/Cargo.toml b/samplecode/hello-regex/enclave/Cargo.toml index 9e6cfc3d8..7a7da4448 100644 --- a/samplecode/hello-regex/enclave/Cargo.toml +++ b/samplecode/hello-regex/enclave/Cargo.toml @@ -18,6 +18,7 @@ sgx_types = { git = "https://github.com/apache/teaclave-sgx-sdk.git" } sgx_tstd = { git = "https://github.com/apache/teaclave-sgx-sdk.git" } [patch.'https://github.com/apache/teaclave-sgx-sdk.git'] +sgx_align_struct_attribute = { path = "../../../sgx_align_struct_attribute" } sgx_alloc = { path = "../../../sgx_alloc" } sgx_backtrace = { path = "../../../sgx_backtrace" } sgx_backtrace_sys = { path = "../../../sgx_backtrace_sys" } @@ -26,6 +27,7 @@ sgx_cov = { path = "../../../sgx_cov" } sgx_crypto_helper = { path = "../../../sgx_crypto_helper" } sgx_demangle = { path = "../../../sgx_demangle" } sgx_libc = { path = "../../../sgx_libc" } +sgx_no_tstd = { path = "../../../sgx_no_tstd" } sgx_rand = { path = "../../../sgx_rand" } sgx_rand_derive = { path = "../../../sgx_rand_derive" } sgx_serialize = { path = "../../../sgx_serialize" } diff --git a/samplecode/hello-regex/enclave/x86_64-unknown-linux-sgx.json b/samplecode/hello-regex/enclave/x86_64-unknown-linux-sgx.json index 69b38be21..53f104e25 100644 --- a/samplecode/hello-regex/enclave/x86_64-unknown-linux-sgx.json +++ b/samplecode/hello-regex/enclave/x86_64-unknown-linux-sgx.json @@ -1,13 +1,13 @@ { "arch": "x86_64", "cpu": "x86-64", + "crt-static-respected": true, "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128", "dynamic-linking": true, "env": "sgx", - "exe-allocation-crate": "alloc_system", "executables": true, - "has-elf-tls": true, "has-rpath": true, + "has-thread-local": true, "linker-flavor": "gcc", "linker-is-gnu": true, "llvm-target": "x86_64-unknown-linux-gnu", @@ -30,6 +30,13 @@ 1 ] }, + "supported-sanitizers": [ + "address", + "cfi", + "leak", + "memory", + "thread" + ], "target-c-int-width": "32", "target-endian": "little", "target-family": "unix", diff --git a/samplecode/hello-rust-vscode-debug/Cargo.toml b/samplecode/hello-rust-vscode-debug/Cargo.toml index 50897b466..f5ecf2cff 100644 --- a/samplecode/hello-rust-vscode-debug/Cargo.toml +++ b/samplecode/hello-rust-vscode-debug/Cargo.toml @@ -4,29 +4,3 @@ members = [ "app", "enclave", ] - -[patch.'https://github.com/apache/teaclave-sgx-sdk.git'] -sgx_alloc = { path = "../../sgx_alloc" } -sgx_build_helper = { path = "../../sgx_build_helper" } -sgx_cov = { path = "../../sgx_cov" } -sgx_crypto_helper = { path = "../../sgx_crypto_helper" } -sgx_libc = { path = "../../sgx_libc" } -sgx_rand = { path = "../../sgx_rand" } -sgx_rand_derive = { path = "../../sgx_rand_derive" } -sgx_serialize = { path = "../../sgx_serialize" } -sgx_serialize_derive = { path = "../../sgx_serialize_derive" } -sgx_serialize_derive_internals = { path = "../../sgx_serialize_derive_internals" } -sgx_tcrypto = { path = "../../sgx_tcrypto" } -sgx_tcrypto_helper = { path = "../../sgx_tcrypto_helper" } -sgx_tdh = { path = "../../sgx_tdh" } -sgx_tkey_exchange = { path = "../../sgx_tkey_exchange" } -sgx_tprotected_fs = { path = "../../sgx_tprotected_fs" } -sgx_trts = { path = "../../sgx_trts" } -sgx_tse = { path = "../../sgx_tse" } -sgx_tseal = { path = "../../sgx_tseal" } -sgx_tstd = { path = "../../sgx_tstd" } -sgx_tunittest = { path = "../../sgx_tunittest" } -sgx_types = { path = "../../sgx_types" } -sgx_ucrypto = { path = "../../sgx_ucrypto" } -sgx_unwind = { path = "../../sgx_unwind" } -sgx_urts = { path = "../../sgx_urts" } diff --git a/samplecode/hello-rust-vscode-debug/enclave/Cargo.toml b/samplecode/hello-rust-vscode-debug/enclave/Cargo.toml index f4f32244b..c5477784e 100644 --- a/samplecode/hello-rust-vscode-debug/enclave/Cargo.toml +++ b/samplecode/hello-rust-vscode-debug/enclave/Cargo.toml @@ -15,6 +15,7 @@ sgx_types = { git = "https://github.com/apache/teaclave-sgx-sdk.git" } sgx_tstd = { git = "https://github.com/apache/teaclave-sgx-sdk.git" } [patch.'https://github.com/apache/teaclave-sgx-sdk.git'] +sgx_align_struct_attribute = { path = "../../../sgx_align_struct_attribute" } sgx_alloc = { path = "../../../sgx_alloc" } sgx_backtrace = { path = "../../../sgx_backtrace" } sgx_backtrace_sys = { path = "../../../sgx_backtrace_sys" } @@ -23,6 +24,7 @@ sgx_cov = { path = "../../../sgx_cov" } sgx_crypto_helper = { path = "../../../sgx_crypto_helper" } sgx_demangle = { path = "../../../sgx_demangle" } sgx_libc = { path = "../../../sgx_libc" } +sgx_no_tstd = { path = "../../../sgx_no_tstd" } sgx_rand = { path = "../../../sgx_rand" } sgx_rand_derive = { path = "../../../sgx_rand_derive" } sgx_serialize = { path = "../../../sgx_serialize" } diff --git a/samplecode/hello-rust-vscode-debug/enclave/x86_64-unknown-linux-sgx.json b/samplecode/hello-rust-vscode-debug/enclave/x86_64-unknown-linux-sgx.json index 69b38be21..53f104e25 100644 --- a/samplecode/hello-rust-vscode-debug/enclave/x86_64-unknown-linux-sgx.json +++ b/samplecode/hello-rust-vscode-debug/enclave/x86_64-unknown-linux-sgx.json @@ -1,13 +1,13 @@ { "arch": "x86_64", "cpu": "x86-64", + "crt-static-respected": true, "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128", "dynamic-linking": true, "env": "sgx", - "exe-allocation-crate": "alloc_system", "executables": true, - "has-elf-tls": true, "has-rpath": true, + "has-thread-local": true, "linker-flavor": "gcc", "linker-is-gnu": true, "llvm-target": "x86_64-unknown-linux-gnu", @@ -30,6 +30,13 @@ 1 ] }, + "supported-sanitizers": [ + "address", + "cfi", + "leak", + "memory", + "thread" + ], "target-c-int-width": "32", "target-endian": "little", "target-family": "unix", diff --git a/samplecode/hello-rust/enclave/Cargo.toml b/samplecode/hello-rust/enclave/Cargo.toml index 8e7afa9ec..fe0ebe308 100644 --- a/samplecode/hello-rust/enclave/Cargo.toml +++ b/samplecode/hello-rust/enclave/Cargo.toml @@ -12,14 +12,19 @@ default = [] [target.'cfg(not(target_env = "sgx"))'.dependencies] sgx_types = { git = "https://github.com/apache/teaclave-sgx-sdk.git" } -sgx_tstd = { git = "https://github.com/apache/teaclave-sgx-sdk.git", features = ["backtrace"] } -sgx_trts = { git = "https://github.com/apache/teaclave-sgx-sdk.git" } +sgx_tstd = { git = "https://github.com/apache/teaclave-sgx-sdk.git" } + [patch.'https://github.com/apache/teaclave-sgx-sdk.git'] +sgx_align_struct_attribute = { path = "../../../sgx_align_struct_attribute" } sgx_alloc = { path = "../../../sgx_alloc" } +sgx_backtrace = { path = "../../../sgx_backtrace" } +sgx_backtrace_sys = { path = "../../../sgx_backtrace_sys" } sgx_build_helper = { path = "../../../sgx_build_helper" } sgx_cov = { path = "../../../sgx_cov" } sgx_crypto_helper = { path = "../../../sgx_crypto_helper" } +sgx_demangle = { path = "../../../sgx_demangle" } sgx_libc = { path = "../../../sgx_libc" } +sgx_no_tstd = { path = "../../../sgx_no_tstd" } sgx_rand = { path = "../../../sgx_rand" } sgx_rand_derive = { path = "../../../sgx_rand_derive" } sgx_serialize = { path = "../../../sgx_serialize" } @@ -36,6 +41,6 @@ sgx_tseal = { path = "../../../sgx_tseal" } sgx_tstd = { path = "../../../sgx_tstd" } sgx_tunittest = { path = "../../../sgx_tunittest" } sgx_types = { path = "../../../sgx_types" } -sgx_ucrypto = { path = "../../../sgx_ucrypto" } +#sgx_ucrypto = { path = "../../../sgx_ucrypto" } sgx_unwind = { path = "../../../sgx_unwind" } -sgx_urts = { path = "../../../sgx_urts" } +#sgx_urts = { path = "../../../sgx_urts" } \ No newline at end of file diff --git a/samplecode/hello-rust/enclave/x86_64-unknown-linux-sgx.json b/samplecode/hello-rust/enclave/x86_64-unknown-linux-sgx.json index 69b38be21..53f104e25 100644 --- a/samplecode/hello-rust/enclave/x86_64-unknown-linux-sgx.json +++ b/samplecode/hello-rust/enclave/x86_64-unknown-linux-sgx.json @@ -1,13 +1,13 @@ { "arch": "x86_64", "cpu": "x86-64", + "crt-static-respected": true, "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128", "dynamic-linking": true, "env": "sgx", - "exe-allocation-crate": "alloc_system", "executables": true, - "has-elf-tls": true, "has-rpath": true, + "has-thread-local": true, "linker-flavor": "gcc", "linker-is-gnu": true, "llvm-target": "x86_64-unknown-linux-gnu", @@ -30,6 +30,13 @@ 1 ] }, + "supported-sanitizers": [ + "address", + "cfi", + "leak", + "memory", + "thread" + ], "target-c-int-width": "32", "target-endian": "little", "target-family": "unix", diff --git a/samplecode/helloworld/enclave/Cargo.toml b/samplecode/helloworld/enclave/Cargo.toml index f4f32244b..c5477784e 100644 --- a/samplecode/helloworld/enclave/Cargo.toml +++ b/samplecode/helloworld/enclave/Cargo.toml @@ -15,6 +15,7 @@ sgx_types = { git = "https://github.com/apache/teaclave-sgx-sdk.git" } sgx_tstd = { git = "https://github.com/apache/teaclave-sgx-sdk.git" } [patch.'https://github.com/apache/teaclave-sgx-sdk.git'] +sgx_align_struct_attribute = { path = "../../../sgx_align_struct_attribute" } sgx_alloc = { path = "../../../sgx_alloc" } sgx_backtrace = { path = "../../../sgx_backtrace" } sgx_backtrace_sys = { path = "../../../sgx_backtrace_sys" } @@ -23,6 +24,7 @@ sgx_cov = { path = "../../../sgx_cov" } sgx_crypto_helper = { path = "../../../sgx_crypto_helper" } sgx_demangle = { path = "../../../sgx_demangle" } sgx_libc = { path = "../../../sgx_libc" } +sgx_no_tstd = { path = "../../../sgx_no_tstd" } sgx_rand = { path = "../../../sgx_rand" } sgx_rand_derive = { path = "../../../sgx_rand_derive" } sgx_serialize = { path = "../../../sgx_serialize" } diff --git a/samplecode/helloworld/enclave/x86_64-unknown-linux-sgx.json b/samplecode/helloworld/enclave/x86_64-unknown-linux-sgx.json index 69b38be21..53f104e25 100644 --- a/samplecode/helloworld/enclave/x86_64-unknown-linux-sgx.json +++ b/samplecode/helloworld/enclave/x86_64-unknown-linux-sgx.json @@ -1,13 +1,13 @@ { "arch": "x86_64", "cpu": "x86-64", + "crt-static-respected": true, "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128", "dynamic-linking": true, "env": "sgx", - "exe-allocation-crate": "alloc_system", "executables": true, - "has-elf-tls": true, "has-rpath": true, + "has-thread-local": true, "linker-flavor": "gcc", "linker-is-gnu": true, "llvm-target": "x86_64-unknown-linux-gnu", @@ -30,6 +30,13 @@ 1 ] }, + "supported-sanitizers": [ + "address", + "cfi", + "leak", + "memory", + "thread" + ], "target-c-int-width": "32", "target-endian": "little", "target-family": "unix", diff --git a/samplecode/http_req/Makefile b/samplecode/http_req/Makefile index fee080ae8..4d150cb04 100644 --- a/samplecode/http_req/Makefile +++ b/samplecode/http_req/Makefile @@ -1,5 +1,4 @@ ######## SGX SDK Settings ######## -SGX_SDK_RUST ?= $(HOME)/sgx SGX_SDK ?= /opt/sgxsdk SGX_MODE ?= HW SGX_ARCH ?= x64 @@ -46,8 +45,8 @@ SGX_COMMON_CFLAGS += -fstack-protector CUSTOM_LIBRARY_PATH := ./lib CUSTOM_BIN_PATH := ./bin -CUSTOM_EDL_PATH := $(SGX_SDK_RUST)/edl -CUSTOM_COMMON_PATH := $(SGX_SDK_RUST)/common +CUSTOM_EDL_PATH := ../../edl +CUSTOM_COMMON_PATH := ../../common ######## EDL Settings ######## diff --git a/samplecode/http_req/enclave/Cargo.toml b/samplecode/http_req/enclave/Cargo.toml index e0cfa8c35..9cca0f10b 100644 --- a/samplecode/http_req/enclave/Cargo.toml +++ b/samplecode/http_req/enclave/Cargo.toml @@ -16,6 +16,7 @@ sgx_types = { git = "https://github.com/apache/teaclave-sgx-sdk.git" } sgx_tstd = { git = "https://github.com/apache/teaclave-sgx-sdk.git", features = ["net"] } [patch.'https://github.com/apache/teaclave-sgx-sdk.git'] +sgx_align_struct_attribute = { path = "../../../sgx_align_struct_attribute" } sgx_alloc = { path = "../../../sgx_alloc" } sgx_backtrace = { path = "../../../sgx_backtrace" } sgx_backtrace_sys = { path = "../../../sgx_backtrace_sys" } @@ -24,6 +25,7 @@ sgx_cov = { path = "../../../sgx_cov" } sgx_crypto_helper = { path = "../../../sgx_crypto_helper" } sgx_demangle = { path = "../../../sgx_demangle" } sgx_libc = { path = "../../../sgx_libc" } +sgx_no_tstd = { path = "../../../sgx_no_tstd" } sgx_rand = { path = "../../../sgx_rand" } sgx_rand_derive = { path = "../../../sgx_rand_derive" } sgx_serialize = { path = "../../../sgx_serialize" } diff --git a/samplecode/http_req/enclave/x86_64-unknown-linux-sgx.json b/samplecode/http_req/enclave/x86_64-unknown-linux-sgx.json index 69b38be21..53f104e25 100644 --- a/samplecode/http_req/enclave/x86_64-unknown-linux-sgx.json +++ b/samplecode/http_req/enclave/x86_64-unknown-linux-sgx.json @@ -1,13 +1,13 @@ { "arch": "x86_64", "cpu": "x86-64", + "crt-static-respected": true, "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128", "dynamic-linking": true, "env": "sgx", - "exe-allocation-crate": "alloc_system", "executables": true, - "has-elf-tls": true, "has-rpath": true, + "has-thread-local": true, "linker-flavor": "gcc", "linker-is-gnu": true, "llvm-target": "x86_64-unknown-linux-gnu", @@ -30,6 +30,13 @@ 1 ] }, + "supported-sanitizers": [ + "address", + "cfi", + "leak", + "memory", + "thread" + ], "target-c-int-width": "32", "target-endian": "little", "target-family": "unix", diff --git a/samplecode/hugemem/enclave/Cargo.toml b/samplecode/hugemem/enclave/Cargo.toml index 76f7695cc..548a28a1a 100644 --- a/samplecode/hugemem/enclave/Cargo.toml +++ b/samplecode/hugemem/enclave/Cargo.toml @@ -15,6 +15,7 @@ sgx_types = { git = "https://github.com/apache/teaclave-sgx-sdk.git" } sgx_tstd = { git = "https://github.com/apache/teaclave-sgx-sdk.git" } [patch.'https://github.com/apache/teaclave-sgx-sdk.git'] +sgx_align_struct_attribute = { path = "../../../sgx_align_struct_attribute" } sgx_alloc = { path = "../../../sgx_alloc" } sgx_backtrace = { path = "../../../sgx_backtrace" } sgx_backtrace_sys = { path = "../../../sgx_backtrace_sys" } @@ -23,6 +24,7 @@ sgx_cov = { path = "../../../sgx_cov" } sgx_crypto_helper = { path = "../../../sgx_crypto_helper" } sgx_demangle = { path = "../../../sgx_demangle" } sgx_libc = { path = "../../../sgx_libc" } +sgx_no_tstd = { path = "../../../sgx_no_tstd" } sgx_rand = { path = "../../../sgx_rand" } sgx_rand_derive = { path = "../../../sgx_rand_derive" } sgx_serialize = { path = "../../../sgx_serialize" } diff --git a/samplecode/hugemem/enclave/x86_64-unknown-linux-sgx.json b/samplecode/hugemem/enclave/x86_64-unknown-linux-sgx.json index 69b38be21..53f104e25 100644 --- a/samplecode/hugemem/enclave/x86_64-unknown-linux-sgx.json +++ b/samplecode/hugemem/enclave/x86_64-unknown-linux-sgx.json @@ -1,13 +1,13 @@ { "arch": "x86_64", "cpu": "x86-64", + "crt-static-respected": true, "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128", "dynamic-linking": true, "env": "sgx", - "exe-allocation-crate": "alloc_system", "executables": true, - "has-elf-tls": true, "has-rpath": true, + "has-thread-local": true, "linker-flavor": "gcc", "linker-is-gnu": true, "llvm-target": "x86_64-unknown-linux-gnu", @@ -30,6 +30,13 @@ 1 ] }, + "supported-sanitizers": [ + "address", + "cfi", + "leak", + "memory", + "thread" + ], "target-c-int-width": "32", "target-endian": "little", "target-family": "unix", diff --git a/samplecode/kvdb-memdb/enclave/Cargo.toml b/samplecode/kvdb-memdb/enclave/Cargo.toml index 0bc002cae..2f9d9a007 100644 --- a/samplecode/kvdb-memdb/enclave/Cargo.toml +++ b/samplecode/kvdb-memdb/enclave/Cargo.toml @@ -20,6 +20,7 @@ sgx_types = { git = "https://github.com/apache/teaclave-sgx-sdk.git" } sgx_tstd = { git = "https://github.com/apache/teaclave-sgx-sdk.git" } [patch.'https://github.com/apache/teaclave-sgx-sdk.git'] +sgx_align_struct_attribute = { path = "../../../sgx_align_struct_attribute" } sgx_alloc = { path = "../../../sgx_alloc" } sgx_backtrace = { path = "../../../sgx_backtrace" } sgx_backtrace_sys = { path = "../../../sgx_backtrace_sys" } @@ -28,6 +29,7 @@ sgx_cov = { path = "../../../sgx_cov" } sgx_crypto_helper = { path = "../../../sgx_crypto_helper" } sgx_demangle = { path = "../../../sgx_demangle" } sgx_libc = { path = "../../../sgx_libc" } +sgx_no_tstd = { path = "../../../sgx_no_tstd" } sgx_rand = { path = "../../../sgx_rand" } sgx_rand_derive = { path = "../../../sgx_rand_derive" } sgx_serialize = { path = "../../../sgx_serialize" } diff --git a/samplecode/kvdb-memdb/enclave/x86_64-unknown-linux-sgx.json b/samplecode/kvdb-memdb/enclave/x86_64-unknown-linux-sgx.json index 69b38be21..53f104e25 100644 --- a/samplecode/kvdb-memdb/enclave/x86_64-unknown-linux-sgx.json +++ b/samplecode/kvdb-memdb/enclave/x86_64-unknown-linux-sgx.json @@ -1,13 +1,13 @@ { "arch": "x86_64", "cpu": "x86-64", + "crt-static-respected": true, "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128", "dynamic-linking": true, "env": "sgx", - "exe-allocation-crate": "alloc_system", "executables": true, - "has-elf-tls": true, "has-rpath": true, + "has-thread-local": true, "linker-flavor": "gcc", "linker-is-gnu": true, "llvm-target": "x86_64-unknown-linux-gnu", @@ -30,6 +30,13 @@ 1 ] }, + "supported-sanitizers": [ + "address", + "cfi", + "leak", + "memory", + "thread" + ], "target-c-int-width": "32", "target-endian": "little", "target-family": "unix", diff --git a/samplecode/localattestation/attestation/Cargo.toml b/samplecode/localattestation/attestation/Cargo.toml index 0fe7a5340..a41ecb6dc 100644 --- a/samplecode/localattestation/attestation/Cargo.toml +++ b/samplecode/localattestation/attestation/Cargo.toml @@ -14,6 +14,7 @@ sgx_tstd = { git = "https://github.com/apache/teaclave-sgx-sdk.git" } sgx_tdh = { git = "https://github.com/apache/teaclave-sgx-sdk.git" } [patch.'https://github.com/apache/teaclave-sgx-sdk.git'] +sgx_align_struct_attribute = { path = "../../../sgx_align_struct_attribute" } sgx_alloc = { path = "../../../sgx_alloc" } sgx_backtrace = { path = "../../../sgx_backtrace" } sgx_backtrace_sys = { path = "../../../sgx_backtrace_sys" } @@ -22,6 +23,7 @@ sgx_cov = { path = "../../../sgx_cov" } sgx_crypto_helper = { path = "../../../sgx_crypto_helper" } sgx_demangle = { path = "../../../sgx_demangle" } sgx_libc = { path = "../../../sgx_libc" } +sgx_no_tstd = { path = "../../../sgx_no_tstd" } sgx_rand = { path = "../../../sgx_rand" } sgx_rand_derive = { path = "../../../sgx_rand_derive" } sgx_serialize = { path = "../../../sgx_serialize" } diff --git a/samplecode/localattestation/enclave1/Cargo.toml b/samplecode/localattestation/enclave1/Cargo.toml index 9da182ede..8abbd2c4f 100644 --- a/samplecode/localattestation/enclave1/Cargo.toml +++ b/samplecode/localattestation/enclave1/Cargo.toml @@ -17,6 +17,7 @@ sgx_types = { git = "https://github.com/apache/teaclave-sgx-sdk.git" } attestation = {path = "../attestation/"} [patch.'https://github.com/apache/teaclave-sgx-sdk.git'] +sgx_align_struct_attribute = { path = "../../../sgx_align_struct_attribute" } sgx_alloc = { path = "../../../sgx_alloc" } sgx_backtrace = { path = "../../../sgx_backtrace" } sgx_backtrace_sys = { path = "../../../sgx_backtrace_sys" } @@ -25,6 +26,7 @@ sgx_cov = { path = "../../../sgx_cov" } sgx_crypto_helper = { path = "../../../sgx_crypto_helper" } sgx_demangle = { path = "../../../sgx_demangle" } sgx_libc = { path = "../../../sgx_libc" } +sgx_no_tstd = { path = "../../../sgx_no_tstd" } sgx_rand = { path = "../../../sgx_rand" } sgx_rand_derive = { path = "../../../sgx_rand_derive" } sgx_serialize = { path = "../../../sgx_serialize" } diff --git a/samplecode/localattestation/enclave1/Xargo.toml b/samplecode/localattestation/enclave1/Xargo.toml index 31fb7d4a6..cd02285d5 100644 --- a/samplecode/localattestation/enclave1/Xargo.toml +++ b/samplecode/localattestation/enclave1/Xargo.toml @@ -88,6 +88,7 @@ stage = 7 [dependencies.sgx_cov] path = "../../../sgx_cov" stage = 7 + [dependencies.sgx_signal] path = "../../../sgx_signal" stage = 7 diff --git a/samplecode/localattestation/enclave1/x86_64-unknown-linux-sgx.json b/samplecode/localattestation/enclave1/x86_64-unknown-linux-sgx.json index 69b38be21..53f104e25 100644 --- a/samplecode/localattestation/enclave1/x86_64-unknown-linux-sgx.json +++ b/samplecode/localattestation/enclave1/x86_64-unknown-linux-sgx.json @@ -1,13 +1,13 @@ { "arch": "x86_64", "cpu": "x86-64", + "crt-static-respected": true, "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128", "dynamic-linking": true, "env": "sgx", - "exe-allocation-crate": "alloc_system", "executables": true, - "has-elf-tls": true, "has-rpath": true, + "has-thread-local": true, "linker-flavor": "gcc", "linker-is-gnu": true, "llvm-target": "x86_64-unknown-linux-gnu", @@ -30,6 +30,13 @@ 1 ] }, + "supported-sanitizers": [ + "address", + "cfi", + "leak", + "memory", + "thread" + ], "target-c-int-width": "32", "target-endian": "little", "target-family": "unix", diff --git a/samplecode/localattestation/enclave2/Cargo.toml b/samplecode/localattestation/enclave2/Cargo.toml index 214479d41..86ca0fbff 100644 --- a/samplecode/localattestation/enclave2/Cargo.toml +++ b/samplecode/localattestation/enclave2/Cargo.toml @@ -17,6 +17,7 @@ sgx_types = { git = "https://github.com/apache/teaclave-sgx-sdk.git" } attestation = {path = "../attestation/"} [patch.'https://github.com/apache/teaclave-sgx-sdk.git'] +sgx_align_struct_attribute = { path = "../../../sgx_align_struct_attribute" } sgx_alloc = { path = "../../../sgx_alloc" } sgx_backtrace = { path = "../../../sgx_backtrace" } sgx_backtrace_sys = { path = "../../../sgx_backtrace_sys" } @@ -25,6 +26,7 @@ sgx_cov = { path = "../../../sgx_cov" } sgx_crypto_helper = { path = "../../../sgx_crypto_helper" } sgx_demangle = { path = "../../../sgx_demangle" } sgx_libc = { path = "../../../sgx_libc" } +sgx_no_tstd = { path = "../../../sgx_no_tstd" } sgx_rand = { path = "../../../sgx_rand" } sgx_rand_derive = { path = "../../../sgx_rand_derive" } sgx_serialize = { path = "../../../sgx_serialize" } diff --git a/samplecode/localattestation/enclave2/Xargo.toml b/samplecode/localattestation/enclave2/Xargo.toml index 31fb7d4a6..cd02285d5 100644 --- a/samplecode/localattestation/enclave2/Xargo.toml +++ b/samplecode/localattestation/enclave2/Xargo.toml @@ -88,6 +88,7 @@ stage = 7 [dependencies.sgx_cov] path = "../../../sgx_cov" stage = 7 + [dependencies.sgx_signal] path = "../../../sgx_signal" stage = 7 diff --git a/samplecode/localattestation/enclave2/x86_64-unknown-linux-sgx.json b/samplecode/localattestation/enclave2/x86_64-unknown-linux-sgx.json index 69b38be21..53f104e25 100644 --- a/samplecode/localattestation/enclave2/x86_64-unknown-linux-sgx.json +++ b/samplecode/localattestation/enclave2/x86_64-unknown-linux-sgx.json @@ -1,13 +1,13 @@ { "arch": "x86_64", "cpu": "x86-64", + "crt-static-respected": true, "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128", "dynamic-linking": true, "env": "sgx", - "exe-allocation-crate": "alloc_system", "executables": true, - "has-elf-tls": true, "has-rpath": true, + "has-thread-local": true, "linker-flavor": "gcc", "linker-is-gnu": true, "llvm-target": "x86_64-unknown-linux-gnu", @@ -30,6 +30,13 @@ 1 ] }, + "supported-sanitizers": [ + "address", + "cfi", + "leak", + "memory", + "thread" + ], "target-c-int-width": "32", "target-endian": "little", "target-family": "unix", diff --git a/samplecode/localattestation/enclave3/Cargo.toml b/samplecode/localattestation/enclave3/Cargo.toml index bf9a48581..e9d06b4ba 100644 --- a/samplecode/localattestation/enclave3/Cargo.toml +++ b/samplecode/localattestation/enclave3/Cargo.toml @@ -17,6 +17,7 @@ sgx_types = { git = "https://github.com/apache/teaclave-sgx-sdk.git" } attestation = {path = "../attestation/"} [patch.'https://github.com/apache/teaclave-sgx-sdk.git'] +sgx_align_struct_attribute = { path = "../../../sgx_align_struct_attribute" } sgx_alloc = { path = "../../../sgx_alloc" } sgx_backtrace = { path = "../../../sgx_backtrace" } sgx_backtrace_sys = { path = "../../../sgx_backtrace_sys" } @@ -25,6 +26,7 @@ sgx_cov = { path = "../../../sgx_cov" } sgx_crypto_helper = { path = "../../../sgx_crypto_helper" } sgx_demangle = { path = "../../../sgx_demangle" } sgx_libc = { path = "../../../sgx_libc" } +sgx_no_tstd = { path = "../../../sgx_no_tstd" } sgx_rand = { path = "../../../sgx_rand" } sgx_rand_derive = { path = "../../../sgx_rand_derive" } sgx_serialize = { path = "../../../sgx_serialize" } diff --git a/samplecode/localattestation/enclave3/Xargo.toml b/samplecode/localattestation/enclave3/Xargo.toml index 31fb7d4a6..cd02285d5 100644 --- a/samplecode/localattestation/enclave3/Xargo.toml +++ b/samplecode/localattestation/enclave3/Xargo.toml @@ -88,6 +88,7 @@ stage = 7 [dependencies.sgx_cov] path = "../../../sgx_cov" stage = 7 + [dependencies.sgx_signal] path = "../../../sgx_signal" stage = 7 diff --git a/samplecode/localattestation/enclave3/x86_64-unknown-linux-sgx.json b/samplecode/localattestation/enclave3/x86_64-unknown-linux-sgx.json index 69b38be21..53f104e25 100644 --- a/samplecode/localattestation/enclave3/x86_64-unknown-linux-sgx.json +++ b/samplecode/localattestation/enclave3/x86_64-unknown-linux-sgx.json @@ -1,13 +1,13 @@ { "arch": "x86_64", "cpu": "x86-64", + "crt-static-respected": true, "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128", "dynamic-linking": true, "env": "sgx", - "exe-allocation-crate": "alloc_system", "executables": true, - "has-elf-tls": true, "has-rpath": true, + "has-thread-local": true, "linker-flavor": "gcc", "linker-is-gnu": true, "llvm-target": "x86_64-unknown-linux-gnu", @@ -30,6 +30,13 @@ 1 ] }, + "supported-sanitizers": [ + "address", + "cfi", + "leak", + "memory", + "thread" + ], "target-c-int-width": "32", "target-endian": "little", "target-family": "unix", diff --git a/samplecode/logger/enclave/Cargo.toml b/samplecode/logger/enclave/Cargo.toml index 4c7e6a77b..ab40428ac 100644 --- a/samplecode/logger/enclave/Cargo.toml +++ b/samplecode/logger/enclave/Cargo.toml @@ -19,6 +19,7 @@ log = { git = "https://github.com/mesalock-linux/log-sgx" } env_logger = { git = "https://github.com/mesalock-linux/env_logger-sgx" } [patch.'https://github.com/apache/teaclave-sgx-sdk.git'] +sgx_align_struct_attribute = { path = "../../../sgx_align_struct_attribute" } sgx_alloc = { path = "../../../sgx_alloc" } sgx_backtrace = { path = "../../../sgx_backtrace" } sgx_backtrace_sys = { path = "../../../sgx_backtrace_sys" } @@ -27,6 +28,7 @@ sgx_cov = { path = "../../../sgx_cov" } sgx_crypto_helper = { path = "../../../sgx_crypto_helper" } sgx_demangle = { path = "../../../sgx_demangle" } sgx_libc = { path = "../../../sgx_libc" } +sgx_no_tstd = { path = "../../../sgx_no_tstd" } sgx_rand = { path = "../../../sgx_rand" } sgx_rand_derive = { path = "../../../sgx_rand_derive" } sgx_serialize = { path = "../../../sgx_serialize" } diff --git a/samplecode/logger/enclave/Xargo.toml b/samplecode/logger/enclave/Xargo.toml index 31fb7d4a6..cd02285d5 100644 --- a/samplecode/logger/enclave/Xargo.toml +++ b/samplecode/logger/enclave/Xargo.toml @@ -88,6 +88,7 @@ stage = 7 [dependencies.sgx_cov] path = "../../../sgx_cov" stage = 7 + [dependencies.sgx_signal] path = "../../../sgx_signal" stage = 7 diff --git a/samplecode/logger/enclave/x86_64-unknown-linux-sgx.json b/samplecode/logger/enclave/x86_64-unknown-linux-sgx.json index 69b38be21..53f104e25 100644 --- a/samplecode/logger/enclave/x86_64-unknown-linux-sgx.json +++ b/samplecode/logger/enclave/x86_64-unknown-linux-sgx.json @@ -1,13 +1,13 @@ { "arch": "x86_64", "cpu": "x86-64", + "crt-static-respected": true, "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128", "dynamic-linking": true, "env": "sgx", - "exe-allocation-crate": "alloc_system", "executables": true, - "has-elf-tls": true, "has-rpath": true, + "has-thread-local": true, "linker-flavor": "gcc", "linker-is-gnu": true, "llvm-target": "x86_64-unknown-linux-gnu", @@ -30,6 +30,13 @@ 1 ] }, + "supported-sanitizers": [ + "address", + "cfi", + "leak", + "memory", + "thread" + ], "target-c-int-width": "32", "target-endian": "little", "target-family": "unix", diff --git a/samplecode/machine-learning/enclave/Cargo.toml b/samplecode/machine-learning/enclave/Cargo.toml index 9c9f363ff..d8721b992 100644 --- a/samplecode/machine-learning/enclave/Cargo.toml +++ b/samplecode/machine-learning/enclave/Cargo.toml @@ -10,6 +10,9 @@ crate-type = ["staticlib"] [features] default = [] +[profile.release] +lto = true + [target.'cfg(not(target_env = "sgx"))'.dependencies] sgx_tstd = { git = "https://github.com/apache/teaclave-sgx-sdk.git" } sgx_types = { git = "https://github.com/apache/teaclave-sgx-sdk.git" } @@ -25,6 +28,7 @@ serde = { git = "https://github.com/mesalock-linux/serde-sgx" } serde_json = { git = "https://github.com/mesalock-linux/serde-json-sgx" } [patch.'https://github.com/apache/teaclave-sgx-sdk.git'] +sgx_align_struct_attribute = { path = "../../../sgx_align_struct_attribute" } sgx_alloc = { path = "../../../sgx_alloc" } sgx_backtrace = { path = "../../../sgx_backtrace" } sgx_backtrace_sys = { path = "../../../sgx_backtrace_sys" } @@ -33,6 +37,7 @@ sgx_cov = { path = "../../../sgx_cov" } sgx_crypto_helper = { path = "../../../sgx_crypto_helper" } sgx_demangle = { path = "../../../sgx_demangle" } sgx_libc = { path = "../../../sgx_libc" } +sgx_no_tstd = { path = "../../../sgx_no_tstd" } sgx_rand = { path = "../../../sgx_rand" } sgx_rand_derive = { path = "../../../sgx_rand_derive" } sgx_serialize = { path = "../../../sgx_serialize" } diff --git a/samplecode/machine-learning/enclave/Xargo.toml b/samplecode/machine-learning/enclave/Xargo.toml index 31fb7d4a6..cd02285d5 100644 --- a/samplecode/machine-learning/enclave/Xargo.toml +++ b/samplecode/machine-learning/enclave/Xargo.toml @@ -88,6 +88,7 @@ stage = 7 [dependencies.sgx_cov] path = "../../../sgx_cov" stage = 7 + [dependencies.sgx_signal] path = "../../../sgx_signal" stage = 7 diff --git a/samplecode/machine-learning/enclave/x86_64-unknown-linux-sgx.json b/samplecode/machine-learning/enclave/x86_64-unknown-linux-sgx.json index 69b38be21..53f104e25 100644 --- a/samplecode/machine-learning/enclave/x86_64-unknown-linux-sgx.json +++ b/samplecode/machine-learning/enclave/x86_64-unknown-linux-sgx.json @@ -1,13 +1,13 @@ { "arch": "x86_64", "cpu": "x86-64", + "crt-static-respected": true, "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128", "dynamic-linking": true, "env": "sgx", - "exe-allocation-crate": "alloc_system", "executables": true, - "has-elf-tls": true, "has-rpath": true, + "has-thread-local": true, "linker-flavor": "gcc", "linker-is-gnu": true, "llvm-target": "x86_64-unknown-linux-gnu", @@ -30,6 +30,13 @@ 1 ] }, + "supported-sanitizers": [ + "address", + "cfi", + "leak", + "memory", + "thread" + ], "target-c-int-width": "32", "target-endian": "little", "target-family": "unix", diff --git a/samplecode/mio/client/enclave/Cargo.toml b/samplecode/mio/client/enclave/Cargo.toml index 6c83e90ff..8aa09c6fd 100644 --- a/samplecode/mio/client/enclave/Cargo.toml +++ b/samplecode/mio/client/enclave/Cargo.toml @@ -20,11 +20,16 @@ webpki = { git = "https://github.com/mesalock-linux/webpki", branch = "mesalock_ log = { git = "https://github.com/mesalock-linux/log-sgx" } [patch.'https://github.com/apache/teaclave-sgx-sdk.git'] +sgx_align_struct_attribute = { path = "../../../../sgx_align_struct_attribute" } sgx_alloc = { path = "../../../../sgx_alloc" } +sgx_backtrace = { path = "../../../../sgx_backtrace" } +sgx_backtrace_sys = { path = "../../../../sgx_backtrace_sys" } sgx_build_helper = { path = "../../../../sgx_build_helper" } sgx_cov = { path = "../../../../sgx_cov" } sgx_crypto_helper = { path = "../../../../sgx_crypto_helper" } +sgx_demangle = { path = "../../../../sgx_demangle" } sgx_libc = { path = "../../../../sgx_libc" } +sgx_no_tstd = { path = "../../../../sgx_no_tstd" } sgx_rand = { path = "../../../../sgx_rand" } sgx_rand_derive = { path = "../../../../sgx_rand_derive" } sgx_serialize = { path = "../../../../sgx_serialize" } diff --git a/samplecode/mio/client/enclave/Xargo.toml b/samplecode/mio/client/enclave/Xargo.toml index 989d7960e..795f1f06f 100644 --- a/samplecode/mio/client/enclave/Xargo.toml +++ b/samplecode/mio/client/enclave/Xargo.toml @@ -89,6 +89,7 @@ stage = 7 [dependencies.sgx_cov] path = "../../../../sgx_cov" stage = 7 + [dependencies.sgx_signal] path = "../../../../sgx_signal" stage = 7 diff --git a/samplecode/mio/client/enclave/x86_64-unknown-linux-sgx.json b/samplecode/mio/client/enclave/x86_64-unknown-linux-sgx.json index 69b38be21..53f104e25 100644 --- a/samplecode/mio/client/enclave/x86_64-unknown-linux-sgx.json +++ b/samplecode/mio/client/enclave/x86_64-unknown-linux-sgx.json @@ -1,13 +1,13 @@ { "arch": "x86_64", "cpu": "x86-64", + "crt-static-respected": true, "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128", "dynamic-linking": true, "env": "sgx", - "exe-allocation-crate": "alloc_system", "executables": true, - "has-elf-tls": true, "has-rpath": true, + "has-thread-local": true, "linker-flavor": "gcc", "linker-is-gnu": true, "llvm-target": "x86_64-unknown-linux-gnu", @@ -30,6 +30,13 @@ 1 ] }, + "supported-sanitizers": [ + "address", + "cfi", + "leak", + "memory", + "thread" + ], "target-c-int-width": "32", "target-endian": "little", "target-family": "unix", diff --git a/samplecode/mio/server/enclave/Cargo.toml b/samplecode/mio/server/enclave/Cargo.toml index a703daf90..9540bee30 100644 --- a/samplecode/mio/server/enclave/Cargo.toml +++ b/samplecode/mio/server/enclave/Cargo.toml @@ -21,6 +21,7 @@ webpki = { git = "https://github.com/mesalock-linux/webpki", branch = "mesalock_ log = { git = "https://github.com/mesalock-linux/log-sgx" } [patch.'https://github.com/apache/teaclave-sgx-sdk.git'] +sgx_align_struct_attribute = { path = "../../../../sgx_align_struct_attribute" } sgx_alloc = { path = "../../../../sgx_alloc" } sgx_backtrace = { path = "../../../../sgx_backtrace" } sgx_backtrace_sys = { path = "../../../../sgx_backtrace_sys" } @@ -29,6 +30,7 @@ sgx_cov = { path = "../../../../sgx_cov" } sgx_crypto_helper = { path = "../../../../sgx_crypto_helper" } sgx_demangle = { path = "../../../../sgx_demangle" } sgx_libc = { path = "../../../../sgx_libc" } +sgx_no_tstd = { path = "../../../../sgx_no_tstd" } sgx_rand = { path = "../../../../sgx_rand" } sgx_rand_derive = { path = "../../../../sgx_rand_derive" } sgx_serialize = { path = "../../../../sgx_serialize" } diff --git a/samplecode/mio/server/enclave/Xargo.toml b/samplecode/mio/server/enclave/Xargo.toml index 989d7960e..795f1f06f 100644 --- a/samplecode/mio/server/enclave/Xargo.toml +++ b/samplecode/mio/server/enclave/Xargo.toml @@ -89,6 +89,7 @@ stage = 7 [dependencies.sgx_cov] path = "../../../../sgx_cov" stage = 7 + [dependencies.sgx_signal] path = "../../../../sgx_signal" stage = 7 diff --git a/samplecode/mio/server/enclave/x86_64-unknown-linux-sgx.json b/samplecode/mio/server/enclave/x86_64-unknown-linux-sgx.json index 69b38be21..53f104e25 100644 --- a/samplecode/mio/server/enclave/x86_64-unknown-linux-sgx.json +++ b/samplecode/mio/server/enclave/x86_64-unknown-linux-sgx.json @@ -1,13 +1,13 @@ { "arch": "x86_64", "cpu": "x86-64", + "crt-static-respected": true, "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128", "dynamic-linking": true, "env": "sgx", - "exe-allocation-crate": "alloc_system", "executables": true, - "has-elf-tls": true, "has-rpath": true, + "has-thread-local": true, "linker-flavor": "gcc", "linker-is-gnu": true, "llvm-target": "x86_64-unknown-linux-gnu", @@ -30,6 +30,13 @@ 1 ] }, + "supported-sanitizers": [ + "address", + "cfi", + "leak", + "memory", + "thread" + ], "target-c-int-width": "32", "target-endian": "little", "target-family": "unix", diff --git a/samplecode/mutual-ra/enclave/Cargo.toml b/samplecode/mutual-ra/enclave/Cargo.toml index 24aece4e3..009732ba9 100644 --- a/samplecode/mutual-ra/enclave/Cargo.toml +++ b/samplecode/mutual-ra/enclave/Cargo.toml @@ -37,6 +37,7 @@ branch = "mesalock_sgx" features = ["dangerous_configuration"] [patch.'https://github.com/apache/teaclave-sgx-sdk.git'] +sgx_align_struct_attribute = { path = "../../../sgx_align_struct_attribute" } sgx_alloc = { path = "../../../sgx_alloc" } sgx_backtrace = { path = "../../../sgx_backtrace" } sgx_backtrace_sys = { path = "../../../sgx_backtrace_sys" } @@ -45,6 +46,7 @@ sgx_cov = { path = "../../../sgx_cov" } sgx_crypto_helper = { path = "../../../sgx_crypto_helper" } sgx_demangle = { path = "../../../sgx_demangle" } sgx_libc = { path = "../../../sgx_libc" } +sgx_no_tstd = { path = "../../../sgx_no_tstd" } sgx_rand = { path = "../../../sgx_rand" } sgx_rand_derive = { path = "../../../sgx_rand_derive" } sgx_serialize = { path = "../../../sgx_serialize" } diff --git a/samplecode/mutual-ra/enclave/Xargo.toml b/samplecode/mutual-ra/enclave/Xargo.toml index 333a0077a..ec653dfcb 100644 --- a/samplecode/mutual-ra/enclave/Xargo.toml +++ b/samplecode/mutual-ra/enclave/Xargo.toml @@ -89,6 +89,7 @@ stage = 7 [dependencies.sgx_cov] path = "../../../sgx_cov" stage = 7 + [dependencies.sgx_signal] path = "../../../sgx_signal" stage = 7 diff --git a/samplecode/mutual-ra/enclave/x86_64-unknown-linux-sgx.json b/samplecode/mutual-ra/enclave/x86_64-unknown-linux-sgx.json index 69b38be21..53f104e25 100644 --- a/samplecode/mutual-ra/enclave/x86_64-unknown-linux-sgx.json +++ b/samplecode/mutual-ra/enclave/x86_64-unknown-linux-sgx.json @@ -1,13 +1,13 @@ { "arch": "x86_64", "cpu": "x86-64", + "crt-static-respected": true, "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128", "dynamic-linking": true, "env": "sgx", - "exe-allocation-crate": "alloc_system", "executables": true, - "has-elf-tls": true, "has-rpath": true, + "has-thread-local": true, "linker-flavor": "gcc", "linker-is-gnu": true, "llvm-target": "x86_64-unknown-linux-gnu", @@ -30,6 +30,13 @@ 1 ] }, + "supported-sanitizers": [ + "address", + "cfi", + "leak", + "memory", + "thread" + ], "target-c-int-width": "32", "target-endian": "little", "target-family": "unix", diff --git a/samplecode/net2/enclave/Cargo.toml b/samplecode/net2/enclave/Cargo.toml index 5b89b2a68..07e8b3379 100644 --- a/samplecode/net2/enclave/Cargo.toml +++ b/samplecode/net2/enclave/Cargo.toml @@ -18,6 +18,7 @@ sgx_tstd = { git = "https://github.com/apache/teaclave-sgx-sdk.git", features = sgx_types = { git = "https://github.com/apache/teaclave-sgx-sdk.git" } [patch.'https://github.com/apache/teaclave-sgx-sdk.git'] +sgx_align_struct_attribute = { path = "../../../sgx_align_struct_attribute" } sgx_alloc = { path = "../../../sgx_alloc" } sgx_backtrace = { path = "../../../sgx_backtrace" } sgx_backtrace_sys = { path = "../../../sgx_backtrace_sys" } @@ -26,6 +27,7 @@ sgx_cov = { path = "../../../sgx_cov" } sgx_crypto_helper = { path = "../../../sgx_crypto_helper" } sgx_demangle = { path = "../../../sgx_demangle" } sgx_libc = { path = "../../../sgx_libc" } +sgx_no_tstd = { path = "../../../sgx_no_tstd" } sgx_rand = { path = "../../../sgx_rand" } sgx_rand_derive = { path = "../../../sgx_rand_derive" } sgx_serialize = { path = "../../../sgx_serialize" } diff --git a/samplecode/net2/enclave/Xargo.toml b/samplecode/net2/enclave/Xargo.toml index 80745aa02..26fd2ceaa 100644 --- a/samplecode/net2/enclave/Xargo.toml +++ b/samplecode/net2/enclave/Xargo.toml @@ -89,6 +89,7 @@ stage = 7 [dependencies.sgx_cov] path = "../../../sgx_cov" stage = 7 + [dependencies.sgx_signal] path = "../../../sgx_signal" stage = 7 diff --git a/samplecode/net2/enclave/x86_64-unknown-linux-sgx.json b/samplecode/net2/enclave/x86_64-unknown-linux-sgx.json index 69b38be21..53f104e25 100644 --- a/samplecode/net2/enclave/x86_64-unknown-linux-sgx.json +++ b/samplecode/net2/enclave/x86_64-unknown-linux-sgx.json @@ -1,13 +1,13 @@ { "arch": "x86_64", "cpu": "x86-64", + "crt-static-respected": true, "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128", "dynamic-linking": true, "env": "sgx", - "exe-allocation-crate": "alloc_system", "executables": true, - "has-elf-tls": true, "has-rpath": true, + "has-thread-local": true, "linker-flavor": "gcc", "linker-is-gnu": true, "llvm-target": "x86_64-unknown-linux-gnu", @@ -30,6 +30,13 @@ 1 ] }, + "supported-sanitizers": [ + "address", + "cfi", + "leak", + "memory", + "thread" + ], "target-c-int-width": "32", "target-endian": "little", "target-family": "unix", diff --git a/samplecode/pcl/encrypted-hello/enclave/Cargo.toml b/samplecode/pcl/encrypted-hello/enclave/Cargo.toml index abe33c00e..9ab56c7de 100644 --- a/samplecode/pcl/encrypted-hello/enclave/Cargo.toml +++ b/samplecode/pcl/encrypted-hello/enclave/Cargo.toml @@ -15,11 +15,16 @@ sgx_types = { git = "https://github.com/apache/teaclave-sgx-sdk.git" } sgx_tstd = { git = "https://github.com/apache/teaclave-sgx-sdk.git" } [patch.'https://github.com/apache/teaclave-sgx-sdk.git'] +sgx_align_struct_attribute = { path = "../../../../sgx_align_struct_attribute" } sgx_alloc = { path = "../../../../sgx_alloc" } +sgx_backtrace = { path = "../../../../sgx_backtrace" } +sgx_backtrace_sys = { path = "../../../../sgx_backtrace_sys" } sgx_build_helper = { path = "../../../../sgx_build_helper" } sgx_cov = { path = "../../../../sgx_cov" } sgx_crypto_helper = { path = "../../../../sgx_crypto_helper" } +sgx_demangle = { path = "../../../../sgx_demangle" } sgx_libc = { path = "../../../../sgx_libc" } +sgx_no_tstd = { path = "../../../../sgx_no_tstd" } sgx_rand = { path = "../../../../sgx_rand" } sgx_rand_derive = { path = "../../../../sgx_rand_derive" } sgx_serialize = { path = "../../../../sgx_serialize" } @@ -36,6 +41,6 @@ sgx_tseal = { path = "../../../../sgx_tseal" } sgx_tstd = { path = "../../../../sgx_tstd" } sgx_tunittest = { path = "../../../../sgx_tunittest" } sgx_types = { path = "../../../../sgx_types" } -sgx_ucrypto = { path = "../../../../sgx_ucrypto" } +#sgx_ucrypto = { path = "../../../../sgx_ucrypto" } sgx_unwind = { path = "../../../../sgx_unwind" } -sgx_urts = { path = "../../../../sgx_urts" } +#sgx_urts = { path = "../../../../sgx_urts" } diff --git a/samplecode/pcl/encrypted-hello/enclave/Xargo.toml b/samplecode/pcl/encrypted-hello/enclave/Xargo.toml index 29ccfac42..c578b6ce8 100644 --- a/samplecode/pcl/encrypted-hello/enclave/Xargo.toml +++ b/samplecode/pcl/encrypted-hello/enclave/Xargo.toml @@ -88,6 +88,7 @@ stage = 7 [dependencies.sgx_cov] path = "../../../../sgx_cov" stage = 7 + [dependencies.sgx_signal] path = "../../../../sgx_signal" stage = 7 diff --git a/samplecode/pcl/encrypted-hello/enclave/x86_64-unknown-linux-sgx.json b/samplecode/pcl/encrypted-hello/enclave/x86_64-unknown-linux-sgx.json index 69b38be21..53f104e25 100644 --- a/samplecode/pcl/encrypted-hello/enclave/x86_64-unknown-linux-sgx.json +++ b/samplecode/pcl/encrypted-hello/enclave/x86_64-unknown-linux-sgx.json @@ -1,13 +1,13 @@ { "arch": "x86_64", "cpu": "x86-64", + "crt-static-respected": true, "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128", "dynamic-linking": true, "env": "sgx", - "exe-allocation-crate": "alloc_system", "executables": true, - "has-elf-tls": true, "has-rpath": true, + "has-thread-local": true, "linker-flavor": "gcc", "linker-is-gnu": true, "llvm-target": "x86_64-unknown-linux-gnu", @@ -30,6 +30,13 @@ 1 ] }, + "supported-sanitizers": [ + "address", + "cfi", + "leak", + "memory", + "thread" + ], "target-c-int-width": "32", "target-endian": "little", "target-family": "unix", diff --git a/samplecode/pcl/pcl-seal/enclave/Cargo.toml b/samplecode/pcl/pcl-seal/enclave/Cargo.toml index 57127e860..1b85d0a0d 100644 --- a/samplecode/pcl/pcl-seal/enclave/Cargo.toml +++ b/samplecode/pcl/pcl-seal/enclave/Cargo.toml @@ -32,11 +32,16 @@ webpki-roots = { git = "https://github.com/mesalock-linux/webpki-roots", bran ue_send_recv = { path = "ue_send_recv" } [patch.'https://github.com/apache/teaclave-sgx-sdk.git'] +sgx_align_struct_attribute = { path = "../../../../sgx_align_struct_attribute" } sgx_alloc = { path = "../../../../sgx_alloc" } +sgx_backtrace = { path = "../../../../sgx_backtrace" } +sgx_backtrace_sys = { path = "../../../../sgx_backtrace_sys" } sgx_build_helper = { path = "../../../../sgx_build_helper" } sgx_cov = { path = "../../../../sgx_cov" } sgx_crypto_helper = { path = "../../../../sgx_crypto_helper" } +sgx_demangle = { path = "../../../../sgx_demangle" } sgx_libc = { path = "../../../../sgx_libc" } +sgx_no_tstd = { path = "../../../../sgx_no_tstd" } sgx_rand = { path = "../../../../sgx_rand" } sgx_rand_derive = { path = "../../../../sgx_rand_derive" } sgx_serialize = { path = "../../../../sgx_serialize" } @@ -53,6 +58,6 @@ sgx_tseal = { path = "../../../../sgx_tseal" } sgx_tstd = { path = "../../../../sgx_tstd" } sgx_tunittest = { path = "../../../../sgx_tunittest" } sgx_types = { path = "../../../../sgx_types" } -sgx_ucrypto = { path = "../../../../sgx_ucrypto" } +#sgx_ucrypto = { path = "../../../../sgx_ucrypto" } sgx_unwind = { path = "../../../../sgx_unwind" } -sgx_urts = { path = "../../../../sgx_urts" } +#sgx_urts = { path = "../../../../sgx_urts" } diff --git a/samplecode/pcl/pcl-seal/enclave/Xargo.toml b/samplecode/pcl/pcl-seal/enclave/Xargo.toml index 989d7960e..795f1f06f 100644 --- a/samplecode/pcl/pcl-seal/enclave/Xargo.toml +++ b/samplecode/pcl/pcl-seal/enclave/Xargo.toml @@ -89,6 +89,7 @@ stage = 7 [dependencies.sgx_cov] path = "../../../../sgx_cov" stage = 7 + [dependencies.sgx_signal] path = "../../../../sgx_signal" stage = 7 diff --git a/samplecode/pcl/pcl-seal/enclave/ue_send_recv/Cargo.toml b/samplecode/pcl/pcl-seal/enclave/ue_send_recv/Cargo.toml index 431344144..0bc6a3eaa 100644 --- a/samplecode/pcl/pcl-seal/enclave/ue_send_recv/Cargo.toml +++ b/samplecode/pcl/pcl-seal/enclave/ue_send_recv/Cargo.toml @@ -20,11 +20,16 @@ cfg-if = "*" sgx_tstd = { git = "https://github.com/apache/teaclave-sgx-sdk.git" } [patch.'https://github.com/apache/teaclave-sgx-sdk.git'] +sgx_align_struct_attribute = { path = "../../../../../sgx_align_struct_attribute" } sgx_alloc = { path = "../../../../../sgx_alloc" } +sgx_backtrace = { path = "../../../../../sgx_backtrace" } +sgx_backtrace_sys = { path = "../../../../../sgx_backtrace_sys" } sgx_build_helper = { path = "../../../../../sgx_build_helper" } sgx_cov = { path = "../../../../../sgx_cov" } sgx_crypto_helper = { path = "../../../../../sgx_crypto_helper" } +sgx_demangle = { path = "../../../../../sgx_demangle" } sgx_libc = { path = "../../../../../sgx_libc" } +sgx_no_tstd = { path = "../../../../../sgx_no_tstd" } sgx_rand = { path = "../../../../../sgx_rand" } sgx_rand_derive = { path = "../../../../../sgx_rand_derive" } sgx_serialize = { path = "../../../../../sgx_serialize" } @@ -41,6 +46,6 @@ sgx_tseal = { path = "../../../../../sgx_tseal" } sgx_tstd = { path = "../../../../../sgx_tstd" } sgx_tunittest = { path = "../../../../../sgx_tunittest" } sgx_types = { path = "../../../../../sgx_types" } -sgx_ucrypto = { path = "../../../../../sgx_ucrypto" } +#sgx_ucrypto = { path = "../../../../../sgx_ucrypto" } sgx_unwind = { path = "../../../../../sgx_unwind" } -sgx_urts = { path = "../../../../../sgx_urts" } +#sgx_urts = { path = "../../../../../sgx_urts" } diff --git a/samplecode/pcl/pcl-seal/enclave/x86_64-unknown-linux-sgx.json b/samplecode/pcl/pcl-seal/enclave/x86_64-unknown-linux-sgx.json index 69b38be21..53f104e25 100644 --- a/samplecode/pcl/pcl-seal/enclave/x86_64-unknown-linux-sgx.json +++ b/samplecode/pcl/pcl-seal/enclave/x86_64-unknown-linux-sgx.json @@ -1,13 +1,13 @@ { "arch": "x86_64", "cpu": "x86-64", + "crt-static-respected": true, "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128", "dynamic-linking": true, "env": "sgx", - "exe-allocation-crate": "alloc_system", "executables": true, - "has-elf-tls": true, "has-rpath": true, + "has-thread-local": true, "linker-flavor": "gcc", "linker-is-gnu": true, "llvm-target": "x86_64-unknown-linux-gnu", @@ -30,6 +30,13 @@ 1 ] }, + "supported-sanitizers": [ + "address", + "cfi", + "leak", + "memory", + "thread" + ], "target-c-int-width": "32", "target-endian": "little", "target-family": "unix", diff --git a/samplecode/project_template/app/rust-toolchain b/samplecode/project_template/app/rust-toolchain index e966e30c2..4e7e21b01 100644 --- a/samplecode/project_template/app/rust-toolchain +++ b/samplecode/project_template/app/rust-toolchain @@ -1 +1 @@ -nightly-2020-10-25 \ No newline at end of file +nightly-2022-02-23 \ No newline at end of file diff --git a/samplecode/project_template/enclave/rust-toolchain b/samplecode/project_template/enclave/rust-toolchain index e966e30c2..4e7e21b01 100644 --- a/samplecode/project_template/enclave/rust-toolchain +++ b/samplecode/project_template/enclave/rust-toolchain @@ -1 +1 @@ -nightly-2020-10-25 \ No newline at end of file +nightly-2022-02-23 \ No newline at end of file diff --git a/samplecode/prost-protobuf/enclave/Cargo.toml b/samplecode/prost-protobuf/enclave/Cargo.toml index 120ec2c33..ef0d25635 100644 --- a/samplecode/prost-protobuf/enclave/Cargo.toml +++ b/samplecode/prost-protobuf/enclave/Cargo.toml @@ -23,11 +23,16 @@ sgx_types = { git = "https://github.com/apache/teaclave-sgx-sdk.git" } sgx_tstd = { git = "https://github.com/apache/teaclave-sgx-sdk.git" } [patch.'https://github.com/apache/teaclave-sgx-sdk.git'] +sgx_align_struct_attribute = { path = "../../../sgx_align_struct_attribute" } sgx_alloc = { path = "../../../sgx_alloc" } +sgx_backtrace = { path = "../../../sgx_backtrace" } +sgx_backtrace_sys = { path = "../../../sgx_backtrace_sys" } sgx_build_helper = { path = "../../../sgx_build_helper" } sgx_cov = { path = "../../../sgx_cov" } sgx_crypto_helper = { path = "../../../sgx_crypto_helper" } +sgx_demangle = { path = "../../../sgx_demangle" } sgx_libc = { path = "../../../sgx_libc" } +sgx_no_tstd = { path = "../../../sgx_no_tstd" } sgx_rand = { path = "../../../sgx_rand" } sgx_rand_derive = { path = "../../../sgx_rand_derive" } sgx_serialize = { path = "../../../sgx_serialize" } diff --git a/samplecode/prost-protobuf/enclave/x86_64-unknown-linux-sgx.json b/samplecode/prost-protobuf/enclave/x86_64-unknown-linux-sgx.json index 69b38be21..53f104e25 100644 --- a/samplecode/prost-protobuf/enclave/x86_64-unknown-linux-sgx.json +++ b/samplecode/prost-protobuf/enclave/x86_64-unknown-linux-sgx.json @@ -1,13 +1,13 @@ { "arch": "x86_64", "cpu": "x86-64", + "crt-static-respected": true, "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128", "dynamic-linking": true, "env": "sgx", - "exe-allocation-crate": "alloc_system", "executables": true, - "has-elf-tls": true, "has-rpath": true, + "has-thread-local": true, "linker-flavor": "gcc", "linker-is-gnu": true, "llvm-target": "x86_64-unknown-linux-gnu", @@ -30,6 +30,13 @@ 1 ] }, + "supported-sanitizers": [ + "address", + "cfi", + "leak", + "memory", + "thread" + ], "target-c-int-width": "32", "target-endian": "little", "target-family": "unix", diff --git a/samplecode/protobuf/enclave/Cargo.toml b/samplecode/protobuf/enclave/Cargo.toml index e78579dda..e31301c85 100644 --- a/samplecode/protobuf/enclave/Cargo.toml +++ b/samplecode/protobuf/enclave/Cargo.toml @@ -18,6 +18,7 @@ sgx_tstd = { path = "../../../sgx_tstd" } protobuf = { git = "https://github.com/mesalock-linux/rust-protobuf-sgx", branch = "v2.8" } [patch.'https://github.com/apache/teaclave-sgx-sdk.git'] +sgx_align_struct_attribute = { path = "../../../sgx_align_struct_attribute" } sgx_alloc = { path = "../../../sgx_alloc" } sgx_backtrace = { path = "../../../sgx_backtrace" } sgx_backtrace_sys = { path = "../../../sgx_backtrace_sys" } @@ -26,6 +27,7 @@ sgx_cov = { path = "../../../sgx_cov" } sgx_crypto_helper = { path = "../../../sgx_crypto_helper" } sgx_demangle = { path = "../../../sgx_demangle" } sgx_libc = { path = "../../../sgx_libc" } +sgx_no_tstd = { path = "../../../sgx_no_tstd" } sgx_rand = { path = "../../../sgx_rand" } sgx_rand_derive = { path = "../../../sgx_rand_derive" } sgx_serialize = { path = "../../../sgx_serialize" } diff --git a/samplecode/protobuf/enclave/Xargo.toml b/samplecode/protobuf/enclave/Xargo.toml index 31fb7d4a6..cd02285d5 100644 --- a/samplecode/protobuf/enclave/Xargo.toml +++ b/samplecode/protobuf/enclave/Xargo.toml @@ -88,6 +88,7 @@ stage = 7 [dependencies.sgx_cov] path = "../../../sgx_cov" stage = 7 + [dependencies.sgx_signal] path = "../../../sgx_signal" stage = 7 diff --git a/samplecode/protobuf/enclave/x86_64-unknown-linux-sgx.json b/samplecode/protobuf/enclave/x86_64-unknown-linux-sgx.json index 69b38be21..53f104e25 100644 --- a/samplecode/protobuf/enclave/x86_64-unknown-linux-sgx.json +++ b/samplecode/protobuf/enclave/x86_64-unknown-linux-sgx.json @@ -1,13 +1,13 @@ { "arch": "x86_64", "cpu": "x86-64", + "crt-static-respected": true, "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128", "dynamic-linking": true, "env": "sgx", - "exe-allocation-crate": "alloc_system", "executables": true, - "has-elf-tls": true, "has-rpath": true, + "has-thread-local": true, "linker-flavor": "gcc", "linker-is-gnu": true, "llvm-target": "x86_64-unknown-linux-gnu", @@ -30,6 +30,13 @@ 1 ] }, + "supported-sanitizers": [ + "address", + "cfi", + "leak", + "memory", + "thread" + ], "target-c-int-width": "32", "target-endian": "little", "target-family": "unix", diff --git a/samplecode/psi/SMCServer/enclave/Cargo.toml b/samplecode/psi/SMCServer/enclave/Cargo.toml index b6e7db2e0..d00ec7ef9 100644 --- a/samplecode/psi/SMCServer/enclave/Cargo.toml +++ b/samplecode/psi/SMCServer/enclave/Cargo.toml @@ -20,6 +20,7 @@ sgx_tkey_exchange = { git = "https://github.com/apache/teaclave-sgx-sdk.git" } sgx_rand = { git = "https://github.com/apache/teaclave-sgx-sdk.git" } [patch.'https://github.com/apache/teaclave-sgx-sdk.git'] +sgx_align_struct_attribute = { path = "../../../../sgx_align_struct_attribute" } sgx_alloc = { path = "../../../../sgx_alloc" } sgx_backtrace = { path = "../../../../sgx_backtrace" } sgx_backtrace_sys = { path = "../../../../sgx_backtrace_sys" } @@ -28,6 +29,7 @@ sgx_cov = { path = "../../../../sgx_cov" } sgx_crypto_helper = { path = "../../../../sgx_crypto_helper" } sgx_demangle = { path = "../../../../sgx_demangle" } sgx_libc = { path = "../../../../sgx_libc" } +sgx_no_tstd = { path = "../../../../sgx_no_tstd" } sgx_rand = { path = "../../../../sgx_rand" } sgx_rand_derive = { path = "../../../../sgx_rand_derive" } sgx_serialize = { path = "../../../../sgx_serialize" } diff --git a/samplecode/psi/SMCServer/enclave/Xargo.toml b/samplecode/psi/SMCServer/enclave/Xargo.toml index 29ccfac42..c578b6ce8 100644 --- a/samplecode/psi/SMCServer/enclave/Xargo.toml +++ b/samplecode/psi/SMCServer/enclave/Xargo.toml @@ -88,6 +88,7 @@ stage = 7 [dependencies.sgx_cov] path = "../../../../sgx_cov" stage = 7 + [dependencies.sgx_signal] path = "../../../../sgx_signal" stage = 7 diff --git a/samplecode/psi/SMCServer/enclave/x86_64-unknown-linux-sgx.json b/samplecode/psi/SMCServer/enclave/x86_64-unknown-linux-sgx.json index 69b38be21..53f104e25 100644 --- a/samplecode/psi/SMCServer/enclave/x86_64-unknown-linux-sgx.json +++ b/samplecode/psi/SMCServer/enclave/x86_64-unknown-linux-sgx.json @@ -1,13 +1,13 @@ { "arch": "x86_64", "cpu": "x86-64", + "crt-static-respected": true, "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128", "dynamic-linking": true, "env": "sgx", - "exe-allocation-crate": "alloc_system", "executables": true, - "has-elf-tls": true, "has-rpath": true, + "has-thread-local": true, "linker-flavor": "gcc", "linker-is-gnu": true, "llvm-target": "x86_64-unknown-linux-gnu", @@ -30,6 +30,13 @@ 1 ] }, + "supported-sanitizers": [ + "address", + "cfi", + "leak", + "memory", + "thread" + ], "target-c-int-width": "32", "target-endian": "little", "target-family": "unix", diff --git a/samplecode/remoteattestation/Application/Makefile b/samplecode/remoteattestation/Application/Makefile index 57708facb..14f869acf 100644 --- a/samplecode/remoteattestation/Application/Makefile +++ b/samplecode/remoteattestation/Application/Makefile @@ -17,7 +17,7 @@ ######## SGX SDK Settings ######## SGX_SDK ?= /opt/sgxsdk -SGX_MODE = HW +SGX_MODE ?= HW SGX_ARCH = x64 SGX_PRERELEASE=1 diff --git a/samplecode/remoteattestation/Application/enclave/Cargo.toml b/samplecode/remoteattestation/Application/enclave/Cargo.toml index 6d15c8a5d..c71fdcfd4 100644 --- a/samplecode/remoteattestation/Application/enclave/Cargo.toml +++ b/samplecode/remoteattestation/Application/enclave/Cargo.toml @@ -19,6 +19,7 @@ sgx_tcrypto = { git = "https://github.com/apache/teaclave-sgx-sdk.git" } sgx_tkey_exchange = { git = "https://github.com/apache/teaclave-sgx-sdk.git" } [patch.'https://github.com/apache/teaclave-sgx-sdk.git'] +sgx_align_struct_attribute = { path = "../../../../sgx_align_struct_attribute" } sgx_alloc = { path = "../../../../sgx_alloc" } sgx_backtrace = { path = "../../../../sgx_backtrace" } sgx_backtrace_sys = { path = "../../../../sgx_backtrace_sys" } @@ -27,6 +28,7 @@ sgx_cov = { path = "../../../../sgx_cov" } sgx_crypto_helper = { path = "../../../../sgx_crypto_helper" } sgx_demangle = { path = "../../../../sgx_demangle" } sgx_libc = { path = "../../../../sgx_libc" } +sgx_no_tstd = { path = "../../../../sgx_no_tstd" } sgx_rand = { path = "../../../../sgx_rand" } sgx_rand_derive = { path = "../../../../sgx_rand_derive" } sgx_serialize = { path = "../../../../sgx_serialize" } diff --git a/samplecode/remoteattestation/Application/enclave/Xargo.toml b/samplecode/remoteattestation/Application/enclave/Xargo.toml index 29ccfac42..c578b6ce8 100644 --- a/samplecode/remoteattestation/Application/enclave/Xargo.toml +++ b/samplecode/remoteattestation/Application/enclave/Xargo.toml @@ -88,6 +88,7 @@ stage = 7 [dependencies.sgx_cov] path = "../../../../sgx_cov" stage = 7 + [dependencies.sgx_signal] path = "../../../../sgx_signal" stage = 7 diff --git a/samplecode/remoteattestation/Application/enclave/src/lib.rs b/samplecode/remoteattestation/Application/enclave/src/lib.rs index 7c9f8b6b3..f9553bf82 100644 --- a/samplecode/remoteattestation/Application/enclave/src/lib.rs +++ b/samplecode/remoteattestation/Application/enclave/src/lib.rs @@ -17,78 +17,71 @@ #![crate_name = "raenclave"] #![crate_type = "staticlib"] - #![cfg_attr(not(target_env = "sgx"), no_std)] #![cfg_attr(target_env = "sgx", feature(rustc_private))] - #![allow(unused_variables)] -extern crate sgx_types; extern crate sgx_trts; +extern crate sgx_types; #[cfg(not(target_env = "sgx"))] #[macro_use] extern crate sgx_tstd as std; -extern crate sgx_tdh; extern crate sgx_tcrypto; +extern crate sgx_tdh; extern crate sgx_tkey_exchange; -use sgx_types::*; -use sgx_trts::memeq::ConsttimeMemEq; use sgx_tcrypto::*; use sgx_tkey_exchange::*; +use sgx_trts::memeq::ConsttimeMemEq; +use sgx_types::*; use std::slice; use std::vec::Vec; -const G_SP_PUB_KEY : sgx_ec256_public_t = sgx_ec256_public_t { - gx : [0x72, 0x12, 0x8a, 0x7a, 0x17, 0x52, 0x6e, 0xbf, - 0x85, 0xd0, 0x3a, 0x62, 0x37, 0x30, 0xae, 0xad, - 0x3e, 0x3d, 0xaa, 0xee, 0x9c, 0x60, 0x73, 0x1d, - 0xb0, 0x5b, 0xe8, 0x62, 0x1c, 0x4b, 0xeb, 0x38], - gy : [0xd4, 0x81, 0x40, 0xd9, 0x50, 0xe2, 0x57, 0x7b, - 0x26, 0xee, 0xb7, 0x41, 0xe7, 0xc6, 0x14, 0xe2, - 0x24, 0xb7, 0xbd, 0xc9, 0x03, 0xf2, 0x9a, 0x28, - 0xa8, 0x3c, 0xc8, 0x10, 0x11, 0x14, 0x5e, 0x06] +const G_SP_PUB_KEY: sgx_ec256_public_t = sgx_ec256_public_t { + gx: [ + 0x72, 0x12, 0x8a, 0x7a, 0x17, 0x52, 0x6e, 0xbf, 0x85, 0xd0, 0x3a, 0x62, 0x37, 0x30, 0xae, + 0xad, 0x3e, 0x3d, 0xaa, 0xee, 0x9c, 0x60, 0x73, 0x1d, 0xb0, 0x5b, 0xe8, 0x62, 0x1c, 0x4b, + 0xeb, 0x38, + ], + gy: [ + 0xd4, 0x81, 0x40, 0xd9, 0x50, 0xe2, 0x57, 0x7b, 0x26, 0xee, 0xb7, 0x41, 0xe7, 0xc6, 0x14, + 0xe2, 0x24, 0xb7, 0xbd, 0xc9, 0x03, 0xf2, 0x9a, 0x28, 0xa8, 0x3c, 0xc8, 0x10, 0x11, 0x14, + 0x5e, 0x06, + ], }; #[no_mangle] -pub extern "C" -fn enclave_init_ra(b_pse: i32, p_context: &mut sgx_ra_context_t) -> sgx_status_t { - let mut ret: sgx_status_t = sgx_status_t::SGX_SUCCESS; +pub extern "C" fn enclave_init_ra(b_pse: i32, p_context: &mut sgx_ra_context_t) -> sgx_status_t { match rsgx_ra_init(&G_SP_PUB_KEY, b_pse) { Ok(p) => { *p_context = p; - ret = sgx_status_t::SGX_SUCCESS; - }, - Err(x) => { - ret = x; - return ret; + sgx_status_t::SGX_SUCCESS } + Err(x) => x, } - ret } #[no_mangle] -pub extern "C" -fn enclave_ra_close(context: sgx_ra_context_t) -> sgx_status_t { +pub extern "C" fn enclave_ra_close(context: sgx_ra_context_t) -> sgx_status_t { match rsgx_ra_close(context) { Ok(()) => sgx_status_t::SGX_SUCCESS, - Err(x) => x + Err(x) => x, } } #[no_mangle] -pub extern "C" -fn verify_att_result_mac(context : sgx_ra_context_t, - message : * const u8, - msg_size: size_t, - mac : * const u8, - mac_size: size_t) -> sgx_status_t { - - let ret:sgx_status_t; - let mk_key:sgx_ec_key_128bit_t; +pub extern "C" fn verify_att_result_mac( + context: sgx_ra_context_t, + message: *const u8, + msg_size: size_t, + mac: *const u8, + mac_size: size_t, +) -> sgx_status_t { + let ret: sgx_status_t; + let mk_key: sgx_ec_key_128bit_t; let mac_slice; let message_slice; - let mac_result:sgx_cmac_128bit_tag_t; + let mac_result: sgx_cmac_128bit_tag_t; if mac_size != SGX_MAC_SIZE || msg_size > u32::max_value as usize { ret = sgx_status_t::SGX_ERROR_INVALID_PARAMETER; @@ -100,20 +93,19 @@ fn verify_att_result_mac(context : sgx_ra_context_t, message_slice = slice::from_raw_parts(message, msg_size as usize); } - if mac_slice.len() != SGX_MAC_SIZE as usize || - message_slice.len() != msg_size as usize { + if mac_slice.len() != SGX_MAC_SIZE as usize || message_slice.len() != msg_size as usize { ret = sgx_status_t::SGX_ERROR_INVALID_PARAMETER; return ret; } match rsgx_ra_get_keys(context, sgx_ra_key_type_t::SGX_RA_KEY_MK) { Ok(k) => mk_key = k, - Err(x) => return x + Err(x) => return x, } match rsgx_rijndael128_cmac_slice(&mk_key, message_slice) { Ok(tag) => mac_result = tag, - Err(x) => return x + Err(x) => return x, } if mac_slice.consttime_memeq(&mac_result) == false { @@ -124,25 +116,23 @@ fn verify_att_result_mac(context : sgx_ra_context_t, } #[no_mangle] -pub extern "C" -fn verify_secret_data(context : sgx_ra_context_t, - p_secret: * const u8, - sec_size: u32, - gcm_mac : &[u8;16], - max_vlen: u32, - p_ret : & mut [u8;16]) -> sgx_status_t { - - let ret:sgx_status_t; - let sk_key:sgx_ec_key_128bit_t; +pub extern "C" fn verify_secret_data( + context: sgx_ra_context_t, + p_secret: *const u8, + sec_size: u32, + gcm_mac: &[u8; 16], + max_vlen: u32, + p_ret: &mut [u8; 16], +) -> sgx_status_t { + let ret: sgx_status_t; + let sk_key: sgx_ec_key_128bit_t; match rsgx_ra_get_keys(context, sgx_ra_key_type_t::SGX_RA_KEY_SK) { Ok(key) => sk_key = key, - Err(x) => return x + Err(x) => return x, } - let secret_slice = unsafe { - slice::from_raw_parts(p_secret, sec_size as usize) - }; + let secret_slice = unsafe { slice::from_raw_parts(p_secret, sec_size as usize) }; if secret_slice.len() != sec_size as usize { ret = sgx_status_t::SGX_ERROR_INVALID_PARAMETER; @@ -151,27 +141,22 @@ fn verify_secret_data(context : sgx_ra_context_t, let mut decrypted_vec: Vec = vec![0; sec_size as usize]; let decrypted_slice = &mut decrypted_vec[..]; - let iv = [0;12]; - let aad:[u8;0] = [0;0]; + let iv = [0; 12]; + let aad: [u8; 0] = [0; 0]; - let ret = rsgx_rijndael128GCM_decrypt(&sk_key, - &secret_slice, - &iv, - &aad, - gcm_mac, - decrypted_slice); + let ret = + rsgx_rijndael128GCM_decrypt(&sk_key, &secret_slice, &iv, &aad, gcm_mac, decrypted_slice); match ret { Ok(()) => { if decrypted_slice[0] == 0 && decrypted_slice[1] != 1 { - return sgx_status_t::SGX_ERROR_INVALID_SIGNATURE; - } - else { - return sgx_status_t::SGX_SUCCESS; + sgx_status_t::SGX_ERROR_INVALID_SIGNATURE + } else { + sgx_status_t::SGX_SUCCESS } - }, + } Err(_) => { - return sgx_status_t::SGX_ERROR_UNEXPECTED; + sgx_status_t::SGX_ERROR_UNEXPECTED } } } diff --git a/samplecode/remoteattestation/Application/enclave/x86_64-unknown-linux-sgx.json b/samplecode/remoteattestation/Application/enclave/x86_64-unknown-linux-sgx.json index 69b38be21..53f104e25 100644 --- a/samplecode/remoteattestation/Application/enclave/x86_64-unknown-linux-sgx.json +++ b/samplecode/remoteattestation/Application/enclave/x86_64-unknown-linux-sgx.json @@ -1,13 +1,13 @@ { "arch": "x86_64", "cpu": "x86-64", + "crt-static-respected": true, "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128", "dynamic-linking": true, "env": "sgx", - "exe-allocation-crate": "alloc_system", "executables": true, - "has-elf-tls": true, "has-rpath": true, + "has-thread-local": true, "linker-flavor": "gcc", "linker-is-gnu": true, "llvm-target": "x86_64-unknown-linux-gnu", @@ -30,6 +30,13 @@ 1 ] }, + "supported-sanitizers": [ + "address", + "cfi", + "leak", + "memory", + "thread" + ], "target-c-int-width": "32", "target-endian": "little", "target-family": "unix", diff --git a/samplecode/remoteattestation/GoogleMessages/Messages.pb.cc b/samplecode/remoteattestation/GoogleMessages/Messages.pb.cc index c7ecd4238..147dc4f83 100644 --- a/samplecode/remoteattestation/GoogleMessages/Messages.pb.cc +++ b/samplecode/remoteattestation/GoogleMessages/Messages.pb.cc @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -38,13 +39,11 @@ const ::google::protobuf::internal::GeneratedMessageReflection* const ::google::protobuf::Descriptor* AttestationMessage_descriptor_ = NULL; const ::google::protobuf::internal::GeneratedMessageReflection* AttestationMessage_reflection_ = NULL; -const ::google::protobuf::Descriptor* SecretMessage_descriptor_ = NULL; -const ::google::protobuf::internal::GeneratedMessageReflection* - SecretMessage_reflection_ = NULL; } // namespace +void protobuf_AssignDesc_Messages_2eproto() GOOGLE_ATTRIBUTE_COLD; void protobuf_AssignDesc_Messages_2eproto() { protobuf_AddDesc_Messages_2eproto(); const ::google::protobuf::FileDescriptor* file = @@ -57,16 +56,16 @@ void protobuf_AssignDesc_Messages_2eproto() { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(InitialMessage, size_), }; InitialMessage_reflection_ = - new ::google::protobuf::internal::GeneratedMessageReflection( + ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection( InitialMessage_descriptor_, InitialMessage::default_instance_, InitialMessage_offsets_, GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(InitialMessage, _has_bits_[0]), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(InitialMessage, _unknown_fields_), -1, - ::google::protobuf::DescriptorPool::generated_pool(), - ::google::protobuf::MessageFactory::generated_factory(), - sizeof(InitialMessage)); + -1, + sizeof(InitialMessage), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(InitialMessage, _internal_metadata_), + -1); MessageMsg0_descriptor_ = file->message_type(1); static const int MessageMsg0_offsets_[3] = { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageMsg0, type_), @@ -74,16 +73,16 @@ void protobuf_AssignDesc_Messages_2eproto() { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageMsg0, status_), }; MessageMsg0_reflection_ = - new ::google::protobuf::internal::GeneratedMessageReflection( + ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection( MessageMsg0_descriptor_, MessageMsg0::default_instance_, MessageMsg0_offsets_, GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageMsg0, _has_bits_[0]), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageMsg0, _unknown_fields_), -1, - ::google::protobuf::DescriptorPool::generated_pool(), - ::google::protobuf::MessageFactory::generated_factory(), - sizeof(MessageMsg0)); + -1, + sizeof(MessageMsg0), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageMsg0, _internal_metadata_), + -1); MessageMSG1_descriptor_ = file->message_type(2); static const int MessageMSG1_offsets_[4] = { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageMSG1, type_), @@ -92,16 +91,16 @@ void protobuf_AssignDesc_Messages_2eproto() { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageMSG1, gid_), }; MessageMSG1_reflection_ = - new ::google::protobuf::internal::GeneratedMessageReflection( + ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection( MessageMSG1_descriptor_, MessageMSG1::default_instance_, MessageMSG1_offsets_, GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageMSG1, _has_bits_[0]), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageMSG1, _unknown_fields_), -1, - ::google::protobuf::DescriptorPool::generated_pool(), - ::google::protobuf::MessageFactory::generated_factory(), - sizeof(MessageMSG1)); + -1, + sizeof(MessageMSG1), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageMSG1, _internal_metadata_), + -1); MessageMSG2_descriptor_ = file->message_type(3); static const int MessageMSG2_offsets_[12] = { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageMSG2, type_), @@ -118,16 +117,16 @@ void protobuf_AssignDesc_Messages_2eproto() { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageMSG2, sigrl_), }; MessageMSG2_reflection_ = - new ::google::protobuf::internal::GeneratedMessageReflection( + ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection( MessageMSG2_descriptor_, MessageMSG2::default_instance_, MessageMSG2_offsets_, GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageMSG2, _has_bits_[0]), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageMSG2, _unknown_fields_), -1, - ::google::protobuf::DescriptorPool::generated_pool(), - ::google::protobuf::MessageFactory::generated_factory(), - sizeof(MessageMSG2)); + -1, + sizeof(MessageMSG2), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageMSG2, _internal_metadata_), + -1); MessageMSG3_descriptor_ = file->message_type(4); static const int MessageMSG3_offsets_[7] = { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageMSG3, type_), @@ -139,16 +138,16 @@ void protobuf_AssignDesc_Messages_2eproto() { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageMSG3, quote_), }; MessageMSG3_reflection_ = - new ::google::protobuf::internal::GeneratedMessageReflection( + ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection( MessageMSG3_descriptor_, MessageMSG3::default_instance_, MessageMSG3_offsets_, GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageMSG3, _has_bits_[0]), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageMSG3, _unknown_fields_), -1, - ::google::protobuf::DescriptorPool::generated_pool(), - ::google::protobuf::MessageFactory::generated_factory(), - sizeof(MessageMSG3)); + -1, + sizeof(MessageMSG3), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageMSG3, _internal_metadata_), + -1); AttestationMessage_descriptor_ = file->message_type(5); static const int AttestationMessage_offsets_[16] = { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(AttestationMessage, type_), @@ -169,40 +168,16 @@ void protobuf_AssignDesc_Messages_2eproto() { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(AttestationMessage, payload_), }; AttestationMessage_reflection_ = - new ::google::protobuf::internal::GeneratedMessageReflection( + ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection( AttestationMessage_descriptor_, AttestationMessage::default_instance_, AttestationMessage_offsets_, GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(AttestationMessage, _has_bits_[0]), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(AttestationMessage, _unknown_fields_), -1, - ::google::protobuf::DescriptorPool::generated_pool(), - ::google::protobuf::MessageFactory::generated_factory(), - sizeof(AttestationMessage)); - SecretMessage_descriptor_ = file->message_type(6); - static const int SecretMessage_offsets_[10] = { - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SecretMessage, type_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SecretMessage, size_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SecretMessage, encryped_pkey_size_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SecretMessage, encryped_x509_size_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SecretMessage, encrypted_content_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SecretMessage, mac_smk_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SecretMessage, encrypted_pkey_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SecretMessage, encrypted_pkey_mac_smk_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SecretMessage, encrypted_x509_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SecretMessage, encrypted_x509_mac_smk_), - }; - SecretMessage_reflection_ = - new ::google::protobuf::internal::GeneratedMessageReflection( - SecretMessage_descriptor_, - SecretMessage::default_instance_, - SecretMessage_offsets_, - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SecretMessage, _has_bits_[0]), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SecretMessage, _unknown_fields_), -1, - ::google::protobuf::DescriptorPool::generated_pool(), - ::google::protobuf::MessageFactory::generated_factory(), - sizeof(SecretMessage)); + sizeof(AttestationMessage), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(AttestationMessage, _internal_metadata_), + -1); } namespace { @@ -213,22 +188,21 @@ inline void protobuf_AssignDescriptorsOnce() { &protobuf_AssignDesc_Messages_2eproto); } +void protobuf_RegisterTypes(const ::std::string&) GOOGLE_ATTRIBUTE_COLD; void protobuf_RegisterTypes(const ::std::string&) { protobuf_AssignDescriptorsOnce(); ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( - InitialMessage_descriptor_, &InitialMessage::default_instance()); - ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( - MessageMsg0_descriptor_, &MessageMsg0::default_instance()); + InitialMessage_descriptor_, &InitialMessage::default_instance()); ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( - MessageMSG1_descriptor_, &MessageMSG1::default_instance()); + MessageMsg0_descriptor_, &MessageMsg0::default_instance()); ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( - MessageMSG2_descriptor_, &MessageMSG2::default_instance()); + MessageMSG1_descriptor_, &MessageMSG1::default_instance()); ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( - MessageMSG3_descriptor_, &MessageMSG3::default_instance()); + MessageMSG2_descriptor_, &MessageMSG2::default_instance()); ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( - AttestationMessage_descriptor_, &AttestationMessage::default_instance()); + MessageMSG3_descriptor_, &MessageMSG3::default_instance()); ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( - SecretMessage_descriptor_, &SecretMessage::default_instance()); + AttestationMessage_descriptor_, &AttestationMessage::default_instance()); } } // namespace @@ -246,10 +220,9 @@ void protobuf_ShutdownFile_Messages_2eproto() { delete MessageMSG3_reflection_; delete AttestationMessage::default_instance_; delete AttestationMessage_reflection_; - delete SecretMessage::default_instance_; - delete SecretMessage_reflection_; } +void protobuf_AddDesc_Messages_2eproto() GOOGLE_ATTRIBUTE_COLD; void protobuf_AddDesc_Messages_2eproto() { static bool already_here = false; if (already_here) return; @@ -283,14 +256,7 @@ void protobuf_AddDesc_Messages_2eproto() { "\030\n \003(\rB\002\020\001\022\030\n\014ec_sign256_y\030\013 \003(\rB\002\020\001\022\023\n\007" "mac_smk\030\014 \003(\rB\002\020\001\022\023\n\013result_size\030\r \001(\r\022\024" "\n\010reserved\030\016 \003(\rB\002\020\001\022\027\n\013payload_tag\030\017 \003(" - "\rB\002\020\001\022\023\n\007payload\030\020 \003(\rB\002\020\001\"\227\002\n\rSecretMes" - "sage\022\014\n\004type\030\001 \002(\r\022\014\n\004size\030\002 \002(\r\022\032\n\022encr" - "yped_pkey_size\030\003 \001(\r\022\032\n\022encryped_x509_si" - "ze\030\004 \001(\r\022\035\n\021encrypted_content\030\005 \003(\rB\002\020\001\022" - "\023\n\007mac_smk\030\006 \003(\rB\002\020\001\022\032\n\016encrypted_pkey\030\007" - " \003(\rB\002\020\001\022\"\n\026encrypted_pkey_mac_smk\030\010 \003(\r" - "B\002\020\001\022\032\n\016encrypted_x509\030\t \003(\rB\002\020\001\022\"\n\026encr" - "ypted_x509_mac_smk\030\n \003(\rB\002\020\001", 1348); + "\rB\002\020\001\022\023\n\007payload\030\020 \003(\rB\002\020\001", 1066); ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( "Messages.proto", &protobuf_RegisterTypes); InitialMessage::default_instance_ = new InitialMessage(); @@ -299,14 +265,12 @@ void protobuf_AddDesc_Messages_2eproto() { MessageMSG2::default_instance_ = new MessageMSG2(); MessageMSG3::default_instance_ = new MessageMSG3(); AttestationMessage::default_instance_ = new AttestationMessage(); - SecretMessage::default_instance_ = new SecretMessage(); InitialMessage::default_instance_->InitAsDefaultInstance(); MessageMsg0::default_instance_->InitAsDefaultInstance(); MessageMSG1::default_instance_->InitAsDefaultInstance(); MessageMSG2::default_instance_->InitAsDefaultInstance(); MessageMSG3::default_instance_->InitAsDefaultInstance(); AttestationMessage::default_instance_->InitAsDefaultInstance(); - SecretMessage::default_instance_->InitAsDefaultInstance(); ::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_Messages_2eproto); } @@ -319,13 +283,13 @@ struct StaticDescriptorInitializer_Messages_2eproto { // =================================================================== -#ifndef _MSC_VER +#if !defined(_MSC_VER) || _MSC_VER >= 1900 const int InitialMessage::kTypeFieldNumber; const int InitialMessage::kSizeFieldNumber; -#endif // !_MSC_VER +#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 InitialMessage::InitialMessage() - : ::google::protobuf::Message() { + : ::google::protobuf::Message(), _internal_metadata_(NULL) { SharedCtor(); // @@protoc_insertion_point(constructor:Messages.InitialMessage) } @@ -334,7 +298,8 @@ void InitialMessage::InitAsDefaultInstance() { } InitialMessage::InitialMessage(const InitialMessage& from) - : ::google::protobuf::Message() { + : ::google::protobuf::Message(), + _internal_metadata_(NULL) { SharedCtor(); MergeFrom(from); // @@protoc_insertion_point(copy_constructor:Messages.InitialMessage) @@ -374,33 +339,46 @@ const InitialMessage& InitialMessage::default_instance() { InitialMessage* InitialMessage::default_instance_ = NULL; -InitialMessage* InitialMessage::New() const { - return new InitialMessage; +InitialMessage* InitialMessage::New(::google::protobuf::Arena* arena) const { + InitialMessage* n = new InitialMessage; + if (arena != NULL) { + arena->Own(n); + } + return n; } void InitialMessage::Clear() { -#define OFFSET_OF_FIELD_(f) (reinterpret_cast( \ - &reinterpret_cast(16)->f) - \ - reinterpret_cast(16)) - -#define ZR_(first, last) do { \ - size_t f = OFFSET_OF_FIELD_(first); \ - size_t n = OFFSET_OF_FIELD_(last) - f + sizeof(last); \ - ::memset(&first, 0, n); \ - } while (0) +// @@protoc_insertion_point(message_clear_start:Messages.InitialMessage) +#if defined(__clang__) +#define ZR_HELPER_(f) \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Winvalid-offsetof\"") \ + __builtin_offsetof(InitialMessage, f) \ + _Pragma("clang diagnostic pop") +#else +#define ZR_HELPER_(f) reinterpret_cast(\ + &reinterpret_cast(16)->f) +#endif + +#define ZR_(first, last) do {\ + ::memset(&first, 0,\ + ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\ +} while (0) ZR_(type_, size_); -#undef OFFSET_OF_FIELD_ +#undef ZR_HELPER_ #undef ZR_ ::memset(_has_bits_, 0, sizeof(_has_bits_)); - mutable_unknown_fields()->Clear(); + if (_internal_metadata_.have_unknown_fields()) { + mutable_unknown_fields()->Clear(); + } } bool InitialMessage::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure +#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; // @@protoc_insertion_point(parse_start:Messages.InitialMessage) for (;;) { @@ -472,15 +450,15 @@ void InitialMessage::SerializeWithCachedSizes( ::google::protobuf::internal::WireFormatLite::WriteUInt32(2, this->size(), output); } - if (!unknown_fields().empty()) { + if (_internal_metadata_.have_unknown_fields()) { ::google::protobuf::internal::WireFormat::SerializeUnknownFields( unknown_fields(), output); } // @@protoc_insertion_point(serialize_end:Messages.InitialMessage) } -::google::protobuf::uint8* InitialMessage::SerializeWithCachedSizesToArray( - ::google::protobuf::uint8* target) const { +::google::protobuf::uint8* InitialMessage::InternalSerializeWithCachedSizesToArray( + bool deterministic, ::google::protobuf::uint8* target) const { // @@protoc_insertion_point(serialize_to_array_start:Messages.InitialMessage) // required uint32 type = 1; if (has_type()) { @@ -492,7 +470,7 @@ ::google::protobuf::uint8* InitialMessage::SerializeWithCachedSizesToArray( target = ::google::protobuf::internal::WireFormatLite::WriteUInt32ToArray(2, this->size(), target); } - if (!unknown_fields().empty()) { + if (_internal_metadata_.have_unknown_fields()) { target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( unknown_fields(), target); } @@ -501,25 +479,23 @@ ::google::protobuf::uint8* InitialMessage::SerializeWithCachedSizesToArray( } int InitialMessage::ByteSize() const { +// @@protoc_insertion_point(message_byte_size_start:Messages.InitialMessage) int total_size = 0; - if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { - // required uint32 type = 1; - if (has_type()) { - total_size += 1 + - ::google::protobuf::internal::WireFormatLite::UInt32Size( - this->type()); - } - - // optional uint32 size = 2; - if (has_size()) { - total_size += 1 + - ::google::protobuf::internal::WireFormatLite::UInt32Size( - this->size()); - } - + // required uint32 type = 1; + if (has_type()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::UInt32Size( + this->type()); + } + // optional uint32 size = 2; + if (has_size()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::UInt32Size( + this->size()); } - if (!unknown_fields().empty()) { + + if (_internal_metadata_.have_unknown_fields()) { total_size += ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( unknown_fields()); @@ -531,19 +507,27 @@ int InitialMessage::ByteSize() const { } void InitialMessage::MergeFrom(const ::google::protobuf::Message& from) { - GOOGLE_CHECK_NE(&from, this); - const InitialMessage* source = - ::google::protobuf::internal::dynamic_cast_if_available( - &from); +// @@protoc_insertion_point(generalized_merge_from_start:Messages.InitialMessage) + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } + const InitialMessage* source = + ::google::protobuf::internal::DynamicCastToGenerated( + &from); if (source == NULL) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:Messages.InitialMessage) ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:Messages.InitialMessage) MergeFrom(*source); } } void InitialMessage::MergeFrom(const InitialMessage& from) { - GOOGLE_CHECK_NE(&from, this); +// @@protoc_insertion_point(class_specific_merge_from_start:Messages.InitialMessage) + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { if (from.has_type()) { set_type(from.type()); @@ -552,16 +536,20 @@ void InitialMessage::MergeFrom(const InitialMessage& from) { set_size(from.size()); } } - mutable_unknown_fields()->MergeFrom(from.unknown_fields()); + if (from._internal_metadata_.have_unknown_fields()) { + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); + } } void InitialMessage::CopyFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:Messages.InitialMessage) if (&from == this) return; Clear(); MergeFrom(from); } void InitialMessage::CopyFrom(const InitialMessage& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:Messages.InitialMessage) if (&from == this) return; Clear(); MergeFrom(from); @@ -574,13 +562,15 @@ bool InitialMessage::IsInitialized() const { } void InitialMessage::Swap(InitialMessage* other) { - if (other != this) { - std::swap(type_, other->type_); - std::swap(size_, other->size_); - std::swap(_has_bits_[0], other->_has_bits_[0]); - _unknown_fields_.Swap(&other->_unknown_fields_); - std::swap(_cached_size_, other->_cached_size_); - } + if (other == this) return; + InternalSwap(other); +} +void InitialMessage::InternalSwap(InitialMessage* other) { + std::swap(type_, other->type_); + std::swap(size_, other->size_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _internal_metadata_.Swap(&other->_internal_metadata_); + std::swap(_cached_size_, other->_cached_size_); } ::google::protobuf::Metadata InitialMessage::GetMetadata() const { @@ -591,17 +581,69 @@ ::google::protobuf::Metadata InitialMessage::GetMetadata() const { return metadata; } +#if PROTOBUF_INLINE_NOT_IN_HEADERS +// InitialMessage + +// required uint32 type = 1; +bool InitialMessage::has_type() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +void InitialMessage::set_has_type() { + _has_bits_[0] |= 0x00000001u; +} +void InitialMessage::clear_has_type() { + _has_bits_[0] &= ~0x00000001u; +} +void InitialMessage::clear_type() { + type_ = 0u; + clear_has_type(); +} + ::google::protobuf::uint32 InitialMessage::type() const { + // @@protoc_insertion_point(field_get:Messages.InitialMessage.type) + return type_; +} + void InitialMessage::set_type(::google::protobuf::uint32 value) { + set_has_type(); + type_ = value; + // @@protoc_insertion_point(field_set:Messages.InitialMessage.type) +} + +// optional uint32 size = 2; +bool InitialMessage::has_size() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} +void InitialMessage::set_has_size() { + _has_bits_[0] |= 0x00000002u; +} +void InitialMessage::clear_has_size() { + _has_bits_[0] &= ~0x00000002u; +} +void InitialMessage::clear_size() { + size_ = 0u; + clear_has_size(); +} + ::google::protobuf::uint32 InitialMessage::size() const { + // @@protoc_insertion_point(field_get:Messages.InitialMessage.size) + return size_; +} + void InitialMessage::set_size(::google::protobuf::uint32 value) { + set_has_size(); + size_ = value; + // @@protoc_insertion_point(field_set:Messages.InitialMessage.size) +} + +#endif // PROTOBUF_INLINE_NOT_IN_HEADERS // =================================================================== -#ifndef _MSC_VER +#if !defined(_MSC_VER) || _MSC_VER >= 1900 const int MessageMsg0::kTypeFieldNumber; const int MessageMsg0::kEpidFieldNumber; const int MessageMsg0::kStatusFieldNumber; -#endif // !_MSC_VER +#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 MessageMsg0::MessageMsg0() - : ::google::protobuf::Message() { + : ::google::protobuf::Message(), _internal_metadata_(NULL) { SharedCtor(); // @@protoc_insertion_point(constructor:Messages.MessageMsg0) } @@ -610,7 +652,8 @@ void MessageMsg0::InitAsDefaultInstance() { } MessageMsg0::MessageMsg0(const MessageMsg0& from) - : ::google::protobuf::Message() { + : ::google::protobuf::Message(), + _internal_metadata_(NULL) { SharedCtor(); MergeFrom(from); // @@protoc_insertion_point(copy_constructor:Messages.MessageMsg0) @@ -651,33 +694,46 @@ const MessageMsg0& MessageMsg0::default_instance() { MessageMsg0* MessageMsg0::default_instance_ = NULL; -MessageMsg0* MessageMsg0::New() const { - return new MessageMsg0; +MessageMsg0* MessageMsg0::New(::google::protobuf::Arena* arena) const { + MessageMsg0* n = new MessageMsg0; + if (arena != NULL) { + arena->Own(n); + } + return n; } void MessageMsg0::Clear() { -#define OFFSET_OF_FIELD_(f) (reinterpret_cast( \ - &reinterpret_cast(16)->f) - \ - reinterpret_cast(16)) - -#define ZR_(first, last) do { \ - size_t f = OFFSET_OF_FIELD_(first); \ - size_t n = OFFSET_OF_FIELD_(last) - f + sizeof(last); \ - ::memset(&first, 0, n); \ - } while (0) +// @@protoc_insertion_point(message_clear_start:Messages.MessageMsg0) +#if defined(__clang__) +#define ZR_HELPER_(f) \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Winvalid-offsetof\"") \ + __builtin_offsetof(MessageMsg0, f) \ + _Pragma("clang diagnostic pop") +#else +#define ZR_HELPER_(f) reinterpret_cast(\ + &reinterpret_cast(16)->f) +#endif + +#define ZR_(first, last) do {\ + ::memset(&first, 0,\ + ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\ +} while (0) ZR_(type_, status_); -#undef OFFSET_OF_FIELD_ +#undef ZR_HELPER_ #undef ZR_ ::memset(_has_bits_, 0, sizeof(_has_bits_)); - mutable_unknown_fields()->Clear(); + if (_internal_metadata_.have_unknown_fields()) { + mutable_unknown_fields()->Clear(); + } } bool MessageMsg0::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure +#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; // @@protoc_insertion_point(parse_start:Messages.MessageMsg0) for (;;) { @@ -769,15 +825,15 @@ void MessageMsg0::SerializeWithCachedSizes( ::google::protobuf::internal::WireFormatLite::WriteUInt32(3, this->status(), output); } - if (!unknown_fields().empty()) { + if (_internal_metadata_.have_unknown_fields()) { ::google::protobuf::internal::WireFormat::SerializeUnknownFields( unknown_fields(), output); } // @@protoc_insertion_point(serialize_end:Messages.MessageMsg0) } -::google::protobuf::uint8* MessageMsg0::SerializeWithCachedSizesToArray( - ::google::protobuf::uint8* target) const { +::google::protobuf::uint8* MessageMsg0::InternalSerializeWithCachedSizesToArray( + bool deterministic, ::google::protobuf::uint8* target) const { // @@protoc_insertion_point(serialize_to_array_start:Messages.MessageMsg0) // required uint32 type = 1; if (has_type()) { @@ -794,7 +850,7 @@ ::google::protobuf::uint8* MessageMsg0::SerializeWithCachedSizesToArray( target = ::google::protobuf::internal::WireFormatLite::WriteUInt32ToArray(3, this->status(), target); } - if (!unknown_fields().empty()) { + if (_internal_metadata_.have_unknown_fields()) { target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( unknown_fields(), target); } @@ -802,33 +858,52 @@ ::google::protobuf::uint8* MessageMsg0::SerializeWithCachedSizesToArray( return target; } -int MessageMsg0::ByteSize() const { +int MessageMsg0::RequiredFieldsByteSizeFallback() const { +// @@protoc_insertion_point(required_fields_byte_size_fallback_start:Messages.MessageMsg0) int total_size = 0; - if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (has_type()) { // required uint32 type = 1; - if (has_type()) { - total_size += 1 + - ::google::protobuf::internal::WireFormatLite::UInt32Size( - this->type()); - } + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::UInt32Size( + this->type()); + } + if (has_epid()) { // required uint32 epid = 2; - if (has_epid()) { - total_size += 1 + - ::google::protobuf::internal::WireFormatLite::UInt32Size( - this->epid()); - } + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::UInt32Size( + this->epid()); + } - // optional uint32 status = 3; - if (has_status()) { - total_size += 1 + - ::google::protobuf::internal::WireFormatLite::UInt32Size( - this->status()); - } + return total_size; +} +int MessageMsg0::ByteSize() const { +// @@protoc_insertion_point(message_byte_size_start:Messages.MessageMsg0) + int total_size = 0; + if (((_has_bits_[0] & 0x00000003) ^ 0x00000003) == 0) { // All required fields are present. + // required uint32 type = 1; + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::UInt32Size( + this->type()); + + // required uint32 epid = 2; + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::UInt32Size( + this->epid()); + + } else { + total_size += RequiredFieldsByteSizeFallback(); + } + // optional uint32 status = 3; + if (has_status()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::UInt32Size( + this->status()); } - if (!unknown_fields().empty()) { + + if (_internal_metadata_.have_unknown_fields()) { total_size += ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( unknown_fields()); @@ -840,19 +915,27 @@ int MessageMsg0::ByteSize() const { } void MessageMsg0::MergeFrom(const ::google::protobuf::Message& from) { - GOOGLE_CHECK_NE(&from, this); - const MessageMsg0* source = - ::google::protobuf::internal::dynamic_cast_if_available( - &from); +// @@protoc_insertion_point(generalized_merge_from_start:Messages.MessageMsg0) + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } + const MessageMsg0* source = + ::google::protobuf::internal::DynamicCastToGenerated( + &from); if (source == NULL) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:Messages.MessageMsg0) ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:Messages.MessageMsg0) MergeFrom(*source); } } void MessageMsg0::MergeFrom(const MessageMsg0& from) { - GOOGLE_CHECK_NE(&from, this); +// @@protoc_insertion_point(class_specific_merge_from_start:Messages.MessageMsg0) + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { if (from.has_type()) { set_type(from.type()); @@ -864,16 +947,20 @@ void MessageMsg0::MergeFrom(const MessageMsg0& from) { set_status(from.status()); } } - mutable_unknown_fields()->MergeFrom(from.unknown_fields()); + if (from._internal_metadata_.have_unknown_fields()) { + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); + } } void MessageMsg0::CopyFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:Messages.MessageMsg0) if (&from == this) return; Clear(); MergeFrom(from); } void MessageMsg0::CopyFrom(const MessageMsg0& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:Messages.MessageMsg0) if (&from == this) return; Clear(); MergeFrom(from); @@ -886,14 +973,16 @@ bool MessageMsg0::IsInitialized() const { } void MessageMsg0::Swap(MessageMsg0* other) { - if (other != this) { - std::swap(type_, other->type_); - std::swap(epid_, other->epid_); - std::swap(status_, other->status_); - std::swap(_has_bits_[0], other->_has_bits_[0]); - _unknown_fields_.Swap(&other->_unknown_fields_); - std::swap(_cached_size_, other->_cached_size_); - } + if (other == this) return; + InternalSwap(other); +} +void MessageMsg0::InternalSwap(MessageMsg0* other) { + std::swap(type_, other->type_); + std::swap(epid_, other->epid_); + std::swap(status_, other->status_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _internal_metadata_.Swap(&other->_internal_metadata_); + std::swap(_cached_size_, other->_cached_size_); } ::google::protobuf::Metadata MessageMsg0::GetMetadata() const { @@ -904,18 +993,94 @@ ::google::protobuf::Metadata MessageMsg0::GetMetadata() const { return metadata; } +#if PROTOBUF_INLINE_NOT_IN_HEADERS +// MessageMsg0 + +// required uint32 type = 1; +bool MessageMsg0::has_type() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +void MessageMsg0::set_has_type() { + _has_bits_[0] |= 0x00000001u; +} +void MessageMsg0::clear_has_type() { + _has_bits_[0] &= ~0x00000001u; +} +void MessageMsg0::clear_type() { + type_ = 0u; + clear_has_type(); +} + ::google::protobuf::uint32 MessageMsg0::type() const { + // @@protoc_insertion_point(field_get:Messages.MessageMsg0.type) + return type_; +} + void MessageMsg0::set_type(::google::protobuf::uint32 value) { + set_has_type(); + type_ = value; + // @@protoc_insertion_point(field_set:Messages.MessageMsg0.type) +} + +// required uint32 epid = 2; +bool MessageMsg0::has_epid() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} +void MessageMsg0::set_has_epid() { + _has_bits_[0] |= 0x00000002u; +} +void MessageMsg0::clear_has_epid() { + _has_bits_[0] &= ~0x00000002u; +} +void MessageMsg0::clear_epid() { + epid_ = 0u; + clear_has_epid(); +} + ::google::protobuf::uint32 MessageMsg0::epid() const { + // @@protoc_insertion_point(field_get:Messages.MessageMsg0.epid) + return epid_; +} + void MessageMsg0::set_epid(::google::protobuf::uint32 value) { + set_has_epid(); + epid_ = value; + // @@protoc_insertion_point(field_set:Messages.MessageMsg0.epid) +} + +// optional uint32 status = 3; +bool MessageMsg0::has_status() const { + return (_has_bits_[0] & 0x00000004u) != 0; +} +void MessageMsg0::set_has_status() { + _has_bits_[0] |= 0x00000004u; +} +void MessageMsg0::clear_has_status() { + _has_bits_[0] &= ~0x00000004u; +} +void MessageMsg0::clear_status() { + status_ = 0u; + clear_has_status(); +} + ::google::protobuf::uint32 MessageMsg0::status() const { + // @@protoc_insertion_point(field_get:Messages.MessageMsg0.status) + return status_; +} + void MessageMsg0::set_status(::google::protobuf::uint32 value) { + set_has_status(); + status_ = value; + // @@protoc_insertion_point(field_set:Messages.MessageMsg0.status) +} + +#endif // PROTOBUF_INLINE_NOT_IN_HEADERS // =================================================================== -#ifndef _MSC_VER +#if !defined(_MSC_VER) || _MSC_VER >= 1900 const int MessageMSG1::kTypeFieldNumber; const int MessageMSG1::kGaXFieldNumber; const int MessageMSG1::kGaYFieldNumber; const int MessageMSG1::kGIDFieldNumber; -#endif // !_MSC_VER +#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 MessageMSG1::MessageMSG1() - : ::google::protobuf::Message() { + : ::google::protobuf::Message(), _internal_metadata_(NULL) { SharedCtor(); // @@protoc_insertion_point(constructor:Messages.MessageMSG1) } @@ -924,7 +1089,8 @@ void MessageMSG1::InitAsDefaultInstance() { } MessageMSG1::MessageMSG1(const MessageMSG1& from) - : ::google::protobuf::Message() { + : ::google::protobuf::Message(), + _internal_metadata_(NULL) { SharedCtor(); MergeFrom(from); // @@protoc_insertion_point(copy_constructor:Messages.MessageMSG1) @@ -963,22 +1129,29 @@ const MessageMSG1& MessageMSG1::default_instance() { MessageMSG1* MessageMSG1::default_instance_ = NULL; -MessageMSG1* MessageMSG1::New() const { - return new MessageMSG1; +MessageMSG1* MessageMSG1::New(::google::protobuf::Arena* arena) const { + MessageMSG1* n = new MessageMSG1; + if (arena != NULL) { + arena->Own(n); + } + return n; } void MessageMSG1::Clear() { +// @@protoc_insertion_point(message_clear_start:Messages.MessageMSG1) type_ = 0u; gax_.Clear(); gay_.Clear(); gid_.Clear(); ::memset(_has_bits_, 0, sizeof(_has_bits_)); - mutable_unknown_fields()->Clear(); + if (_internal_metadata_.have_unknown_fields()) { + mutable_unknown_fields()->Clear(); + } } bool MessageMSG1::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure +#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; // @@protoc_insertion_point(parse_start:Messages.MessageMSG1) for (;;) { @@ -1114,15 +1287,15 @@ void MessageMSG1::SerializeWithCachedSizes( this->gid(i), output); } - if (!unknown_fields().empty()) { + if (_internal_metadata_.have_unknown_fields()) { ::google::protobuf::internal::WireFormat::SerializeUnknownFields( unknown_fields(), output); } // @@protoc_insertion_point(serialize_end:Messages.MessageMSG1) } -::google::protobuf::uint8* MessageMSG1::SerializeWithCachedSizesToArray( - ::google::protobuf::uint8* target) const { +::google::protobuf::uint8* MessageMSG1::InternalSerializeWithCachedSizesToArray( + bool deterministic, ::google::protobuf::uint8* target) const { // @@protoc_insertion_point(serialize_to_array_start:Messages.MessageMSG1) // required uint32 type = 1; if (has_type()) { @@ -1171,7 +1344,7 @@ ::google::protobuf::uint8* MessageMSG1::SerializeWithCachedSizesToArray( WriteUInt32NoTagToArray(this->gid(i), target); } - if (!unknown_fields().empty()) { + if (_internal_metadata_.have_unknown_fields()) { target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( unknown_fields(), target); } @@ -1180,16 +1353,14 @@ ::google::protobuf::uint8* MessageMSG1::SerializeWithCachedSizesToArray( } int MessageMSG1::ByteSize() const { +// @@protoc_insertion_point(message_byte_size_start:Messages.MessageMSG1) int total_size = 0; - if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { - // required uint32 type = 1; - if (has_type()) { - total_size += 1 + - ::google::protobuf::internal::WireFormatLite::UInt32Size( - this->type()); - } - + // required uint32 type = 1; + if (has_type()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::UInt32Size( + this->type()); } // repeated uint32 GaX = 2 [packed = true]; { @@ -1242,7 +1413,7 @@ int MessageMSG1::ByteSize() const { total_size += data_size; } - if (!unknown_fields().empty()) { + if (_internal_metadata_.have_unknown_fields()) { total_size += ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( unknown_fields()); @@ -1254,19 +1425,27 @@ int MessageMSG1::ByteSize() const { } void MessageMSG1::MergeFrom(const ::google::protobuf::Message& from) { - GOOGLE_CHECK_NE(&from, this); - const MessageMSG1* source = - ::google::protobuf::internal::dynamic_cast_if_available( - &from); +// @@protoc_insertion_point(generalized_merge_from_start:Messages.MessageMSG1) + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } + const MessageMSG1* source = + ::google::protobuf::internal::DynamicCastToGenerated( + &from); if (source == NULL) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:Messages.MessageMSG1) ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:Messages.MessageMSG1) MergeFrom(*source); } } void MessageMSG1::MergeFrom(const MessageMSG1& from) { - GOOGLE_CHECK_NE(&from, this); +// @@protoc_insertion_point(class_specific_merge_from_start:Messages.MessageMSG1) + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } gax_.MergeFrom(from.gax_); gay_.MergeFrom(from.gay_); gid_.MergeFrom(from.gid_); @@ -1275,16 +1454,20 @@ void MessageMSG1::MergeFrom(const MessageMSG1& from) { set_type(from.type()); } } - mutable_unknown_fields()->MergeFrom(from.unknown_fields()); + if (from._internal_metadata_.have_unknown_fields()) { + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); + } } void MessageMSG1::CopyFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:Messages.MessageMSG1) if (&from == this) return; Clear(); MergeFrom(from); } void MessageMSG1::CopyFrom(const MessageMSG1& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:Messages.MessageMSG1) if (&from == this) return; Clear(); MergeFrom(from); @@ -1297,15 +1480,17 @@ bool MessageMSG1::IsInitialized() const { } void MessageMSG1::Swap(MessageMSG1* other) { - if (other != this) { - std::swap(type_, other->type_); - gax_.Swap(&other->gax_); - gay_.Swap(&other->gay_); - gid_.Swap(&other->gid_); - std::swap(_has_bits_[0], other->_has_bits_[0]); - _unknown_fields_.Swap(&other->_unknown_fields_); - std::swap(_cached_size_, other->_cached_size_); - } + if (other == this) return; + InternalSwap(other); +} +void MessageMSG1::InternalSwap(MessageMSG1* other) { + std::swap(type_, other->type_); + gax_.UnsafeArenaSwap(&other->gax_); + gay_.UnsafeArenaSwap(&other->gay_); + gid_.UnsafeArenaSwap(&other->gid_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _internal_metadata_.Swap(&other->_internal_metadata_); + std::swap(_cached_size_, other->_cached_size_); } ::google::protobuf::Metadata MessageMSG1::GetMetadata() const { @@ -1316,10 +1501,128 @@ ::google::protobuf::Metadata MessageMSG1::GetMetadata() const { return metadata; } +#if PROTOBUF_INLINE_NOT_IN_HEADERS +// MessageMSG1 + +// required uint32 type = 1; +bool MessageMSG1::has_type() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +void MessageMSG1::set_has_type() { + _has_bits_[0] |= 0x00000001u; +} +void MessageMSG1::clear_has_type() { + _has_bits_[0] &= ~0x00000001u; +} +void MessageMSG1::clear_type() { + type_ = 0u; + clear_has_type(); +} + ::google::protobuf::uint32 MessageMSG1::type() const { + // @@protoc_insertion_point(field_get:Messages.MessageMSG1.type) + return type_; +} + void MessageMSG1::set_type(::google::protobuf::uint32 value) { + set_has_type(); + type_ = value; + // @@protoc_insertion_point(field_set:Messages.MessageMSG1.type) +} + +// repeated uint32 GaX = 2 [packed = true]; +int MessageMSG1::gax_size() const { + return gax_.size(); +} +void MessageMSG1::clear_gax() { + gax_.Clear(); +} + ::google::protobuf::uint32 MessageMSG1::gax(int index) const { + // @@protoc_insertion_point(field_get:Messages.MessageMSG1.GaX) + return gax_.Get(index); +} + void MessageMSG1::set_gax(int index, ::google::protobuf::uint32 value) { + gax_.Set(index, value); + // @@protoc_insertion_point(field_set:Messages.MessageMSG1.GaX) +} + void MessageMSG1::add_gax(::google::protobuf::uint32 value) { + gax_.Add(value); + // @@protoc_insertion_point(field_add:Messages.MessageMSG1.GaX) +} + const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& +MessageMSG1::gax() const { + // @@protoc_insertion_point(field_list:Messages.MessageMSG1.GaX) + return gax_; +} + ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* +MessageMSG1::mutable_gax() { + // @@protoc_insertion_point(field_mutable_list:Messages.MessageMSG1.GaX) + return &gax_; +} + +// repeated uint32 GaY = 3 [packed = true]; +int MessageMSG1::gay_size() const { + return gay_.size(); +} +void MessageMSG1::clear_gay() { + gay_.Clear(); +} + ::google::protobuf::uint32 MessageMSG1::gay(int index) const { + // @@protoc_insertion_point(field_get:Messages.MessageMSG1.GaY) + return gay_.Get(index); +} + void MessageMSG1::set_gay(int index, ::google::protobuf::uint32 value) { + gay_.Set(index, value); + // @@protoc_insertion_point(field_set:Messages.MessageMSG1.GaY) +} + void MessageMSG1::add_gay(::google::protobuf::uint32 value) { + gay_.Add(value); + // @@protoc_insertion_point(field_add:Messages.MessageMSG1.GaY) +} + const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& +MessageMSG1::gay() const { + // @@protoc_insertion_point(field_list:Messages.MessageMSG1.GaY) + return gay_; +} + ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* +MessageMSG1::mutable_gay() { + // @@protoc_insertion_point(field_mutable_list:Messages.MessageMSG1.GaY) + return &gay_; +} + +// repeated uint32 GID = 4 [packed = true]; +int MessageMSG1::gid_size() const { + return gid_.size(); +} +void MessageMSG1::clear_gid() { + gid_.Clear(); +} + ::google::protobuf::uint32 MessageMSG1::gid(int index) const { + // @@protoc_insertion_point(field_get:Messages.MessageMSG1.GID) + return gid_.Get(index); +} + void MessageMSG1::set_gid(int index, ::google::protobuf::uint32 value) { + gid_.Set(index, value); + // @@protoc_insertion_point(field_set:Messages.MessageMSG1.GID) +} + void MessageMSG1::add_gid(::google::protobuf::uint32 value) { + gid_.Add(value); + // @@protoc_insertion_point(field_add:Messages.MessageMSG1.GID) +} + const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& +MessageMSG1::gid() const { + // @@protoc_insertion_point(field_list:Messages.MessageMSG1.GID) + return gid_; +} + ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* +MessageMSG1::mutable_gid() { + // @@protoc_insertion_point(field_mutable_list:Messages.MessageMSG1.GID) + return &gid_; +} + +#endif // PROTOBUF_INLINE_NOT_IN_HEADERS // =================================================================== -#ifndef _MSC_VER +#if !defined(_MSC_VER) || _MSC_VER >= 1900 const int MessageMSG2::kTypeFieldNumber; const int MessageMSG2::kSizeFieldNumber; const int MessageMSG2::kPublicKeyGxFieldNumber; @@ -1332,10 +1635,10 @@ const int MessageMSG2::kSignatureYFieldNumber; const int MessageMSG2::kSmacFieldNumber; const int MessageMSG2::kSizeSigrlFieldNumber; const int MessageMSG2::kSigrlFieldNumber; -#endif // !_MSC_VER +#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 MessageMSG2::MessageMSG2() - : ::google::protobuf::Message() { + : ::google::protobuf::Message(), _internal_metadata_(NULL) { SharedCtor(); // @@protoc_insertion_point(constructor:Messages.MessageMSG2) } @@ -1344,7 +1647,8 @@ void MessageMSG2::InitAsDefaultInstance() { } MessageMSG2::MessageMSG2(const MessageMSG2& from) - : ::google::protobuf::Message() { + : ::google::protobuf::Message(), + _internal_metadata_(NULL) { SharedCtor(); MergeFrom(from); // @@protoc_insertion_point(copy_constructor:Messages.MessageMSG2) @@ -1387,26 +1691,37 @@ const MessageMSG2& MessageMSG2::default_instance() { MessageMSG2* MessageMSG2::default_instance_ = NULL; -MessageMSG2* MessageMSG2::New() const { - return new MessageMSG2; +MessageMSG2* MessageMSG2::New(::google::protobuf::Arena* arena) const { + MessageMSG2* n = new MessageMSG2; + if (arena != NULL) { + arena->Own(n); + } + return n; } void MessageMSG2::Clear() { -#define OFFSET_OF_FIELD_(f) (reinterpret_cast( \ - &reinterpret_cast(16)->f) - \ - reinterpret_cast(16)) - -#define ZR_(first, last) do { \ - size_t f = OFFSET_OF_FIELD_(first); \ - size_t n = OFFSET_OF_FIELD_(last) - f + sizeof(last); \ - ::memset(&first, 0, n); \ - } while (0) +// @@protoc_insertion_point(message_clear_start:Messages.MessageMSG2) +#if defined(__clang__) +#define ZR_HELPER_(f) \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Winvalid-offsetof\"") \ + __builtin_offsetof(MessageMSG2, f) \ + _Pragma("clang diagnostic pop") +#else +#define ZR_HELPER_(f) reinterpret_cast(\ + &reinterpret_cast(16)->f) +#endif + +#define ZR_(first, last) do {\ + ::memset(&first, 0,\ + ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\ +} while (0) ZR_(type_, size_); ZR_(quote_type_, cmac_kdf_id_); size_sigrl_ = 0u; -#undef OFFSET_OF_FIELD_ +#undef ZR_HELPER_ #undef ZR_ public_key_gx_.Clear(); @@ -1417,12 +1732,14 @@ void MessageMSG2::Clear() { smac_.Clear(); sigrl_.Clear(); ::memset(_has_bits_, 0, sizeof(_has_bits_)); - mutable_unknown_fields()->Clear(); + if (_internal_metadata_.have_unknown_fields()) { + mutable_unknown_fields()->Clear(); + } } bool MessageMSG2::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure +#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; // @@protoc_insertion_point(parse_start:Messages.MessageMSG2) for (;;) { @@ -1750,15 +2067,15 @@ void MessageMSG2::SerializeWithCachedSizes( this->sigrl(i), output); } - if (!unknown_fields().empty()) { + if (_internal_metadata_.have_unknown_fields()) { ::google::protobuf::internal::WireFormat::SerializeUnknownFields( unknown_fields(), output); } // @@protoc_insertion_point(serialize_end:Messages.MessageMSG2) } -::google::protobuf::uint8* MessageMSG2::SerializeWithCachedSizesToArray( - ::google::protobuf::uint8* target) const { +::google::protobuf::uint8* MessageMSG2::InternalSerializeWithCachedSizesToArray( + bool deterministic, ::google::protobuf::uint8* target) const { // @@protoc_insertion_point(serialize_to_array_start:Messages.MessageMSG2) // required uint32 type = 1; if (has_type()) { @@ -1883,7 +2200,7 @@ ::google::protobuf::uint8* MessageMSG2::SerializeWithCachedSizesToArray( WriteUInt32NoTagToArray(this->sigrl(i), target); } - if (!unknown_fields().empty()) { + if (_internal_metadata_.have_unknown_fields()) { target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( unknown_fields(), target); } @@ -1892,16 +2209,16 @@ ::google::protobuf::uint8* MessageMSG2::SerializeWithCachedSizesToArray( } int MessageMSG2::ByteSize() const { +// @@protoc_insertion_point(message_byte_size_start:Messages.MessageMSG2) int total_size = 0; - if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { - // required uint32 type = 1; - if (has_type()) { - total_size += 1 + - ::google::protobuf::internal::WireFormatLite::UInt32Size( - this->type()); - } - + // required uint32 type = 1; + if (has_type()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::UInt32Size( + this->type()); + } + if (_has_bits_[1 / 32] & 82u) { // optional uint32 size = 2; if (has_size()) { total_size += 1 + @@ -1924,15 +2241,13 @@ int MessageMSG2::ByteSize() const { } } - if (_has_bits_[10 / 32] & (0xffu << (10 % 32))) { - // optional uint32 size_sigrl = 11; - if (has_size_sigrl()) { - total_size += 1 + - ::google::protobuf::internal::WireFormatLite::UInt32Size( - this->size_sigrl()); - } - + // optional uint32 size_sigrl = 11; + if (has_size_sigrl()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::UInt32Size( + this->size_sigrl()); } + // repeated uint32 public_key_gx = 3 [packed = true]; { int data_size = 0; @@ -2052,7 +2367,7 @@ int MessageMSG2::ByteSize() const { total_size += data_size; } - if (!unknown_fields().empty()) { + if (_internal_metadata_.have_unknown_fields()) { total_size += ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( unknown_fields()); @@ -2064,19 +2379,27 @@ int MessageMSG2::ByteSize() const { } void MessageMSG2::MergeFrom(const ::google::protobuf::Message& from) { - GOOGLE_CHECK_NE(&from, this); - const MessageMSG2* source = - ::google::protobuf::internal::dynamic_cast_if_available( - &from); +// @@protoc_insertion_point(generalized_merge_from_start:Messages.MessageMSG2) + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } + const MessageMSG2* source = + ::google::protobuf::internal::DynamicCastToGenerated( + &from); if (source == NULL) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:Messages.MessageMSG2) ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:Messages.MessageMSG2) MergeFrom(*source); } } void MessageMSG2::MergeFrom(const MessageMSG2& from) { - GOOGLE_CHECK_NE(&from, this); +// @@protoc_insertion_point(class_specific_merge_from_start:Messages.MessageMSG2) + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } public_key_gx_.MergeFrom(from.public_key_gx_); public_key_gy_.MergeFrom(from.public_key_gy_); spid_.MergeFrom(from.spid_); @@ -2103,16 +2426,20 @@ void MessageMSG2::MergeFrom(const MessageMSG2& from) { set_size_sigrl(from.size_sigrl()); } } - mutable_unknown_fields()->MergeFrom(from.unknown_fields()); + if (from._internal_metadata_.have_unknown_fields()) { + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); + } } void MessageMSG2::CopyFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:Messages.MessageMSG2) if (&from == this) return; Clear(); MergeFrom(from); } void MessageMSG2::CopyFrom(const MessageMSG2& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:Messages.MessageMSG2) if (&from == this) return; Clear(); MergeFrom(from); @@ -2125,23 +2452,25 @@ bool MessageMSG2::IsInitialized() const { } void MessageMSG2::Swap(MessageMSG2* other) { - if (other != this) { - std::swap(type_, other->type_); - std::swap(size_, other->size_); - public_key_gx_.Swap(&other->public_key_gx_); - public_key_gy_.Swap(&other->public_key_gy_); - std::swap(quote_type_, other->quote_type_); - spid_.Swap(&other->spid_); - std::swap(cmac_kdf_id_, other->cmac_kdf_id_); - signature_x_.Swap(&other->signature_x_); - signature_y_.Swap(&other->signature_y_); - smac_.Swap(&other->smac_); - std::swap(size_sigrl_, other->size_sigrl_); - sigrl_.Swap(&other->sigrl_); - std::swap(_has_bits_[0], other->_has_bits_[0]); - _unknown_fields_.Swap(&other->_unknown_fields_); - std::swap(_cached_size_, other->_cached_size_); - } + if (other == this) return; + InternalSwap(other); +} +void MessageMSG2::InternalSwap(MessageMSG2* other) { + std::swap(type_, other->type_); + std::swap(size_, other->size_); + public_key_gx_.UnsafeArenaSwap(&other->public_key_gx_); + public_key_gy_.UnsafeArenaSwap(&other->public_key_gy_); + std::swap(quote_type_, other->quote_type_); + spid_.UnsafeArenaSwap(&other->spid_); + std::swap(cmac_kdf_id_, other->cmac_kdf_id_); + signature_x_.UnsafeArenaSwap(&other->signature_x_); + signature_y_.UnsafeArenaSwap(&other->signature_y_); + smac_.UnsafeArenaSwap(&other->smac_); + std::swap(size_sigrl_, other->size_sigrl_); + sigrl_.UnsafeArenaSwap(&other->sigrl_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _internal_metadata_.Swap(&other->_internal_metadata_); + std::swap(_cached_size_, other->_cached_size_); } ::google::protobuf::Metadata MessageMSG2::GetMetadata() const { @@ -2152,87 +2481,433 @@ ::google::protobuf::Metadata MessageMSG2::GetMetadata() const { return metadata; } +#if PROTOBUF_INLINE_NOT_IN_HEADERS +// MessageMSG2 -// =================================================================== - -#ifndef _MSC_VER -const int MessageMSG3::kTypeFieldNumber; -const int MessageMSG3::kSizeFieldNumber; -const int MessageMSG3::kSgxMacFieldNumber; -const int MessageMSG3::kGaxMsg3FieldNumber; -const int MessageMSG3::kGayMsg3FieldNumber; -const int MessageMSG3::kSecPropertyFieldNumber; -const int MessageMSG3::kQuoteFieldNumber; -#endif // !_MSC_VER - -MessageMSG3::MessageMSG3() - : ::google::protobuf::Message() { - SharedCtor(); - // @@protoc_insertion_point(constructor:Messages.MessageMSG3) +// required uint32 type = 1; +bool MessageMSG2::has_type() const { + return (_has_bits_[0] & 0x00000001u) != 0; } - -void MessageMSG3::InitAsDefaultInstance() { +void MessageMSG2::set_has_type() { + _has_bits_[0] |= 0x00000001u; } - -MessageMSG3::MessageMSG3(const MessageMSG3& from) - : ::google::protobuf::Message() { - SharedCtor(); - MergeFrom(from); - // @@protoc_insertion_point(copy_constructor:Messages.MessageMSG3) +void MessageMSG2::clear_has_type() { + _has_bits_[0] &= ~0x00000001u; } - -void MessageMSG3::SharedCtor() { - _cached_size_ = 0; +void MessageMSG2::clear_type() { type_ = 0u; - size_ = 0u; - ::memset(_has_bits_, 0, sizeof(_has_bits_)); + clear_has_type(); } - -MessageMSG3::~MessageMSG3() { - // @@protoc_insertion_point(destructor:Messages.MessageMSG3) - SharedDtor(); + ::google::protobuf::uint32 MessageMSG2::type() const { + // @@protoc_insertion_point(field_get:Messages.MessageMSG2.type) + return type_; } - -void MessageMSG3::SharedDtor() { - if (this != default_instance_) { - } + void MessageMSG2::set_type(::google::protobuf::uint32 value) { + set_has_type(); + type_ = value; + // @@protoc_insertion_point(field_set:Messages.MessageMSG2.type) } -void MessageMSG3::SetCachedSize(int size) const { - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); +// optional uint32 size = 2; +bool MessageMSG2::has_size() const { + return (_has_bits_[0] & 0x00000002u) != 0; } -const ::google::protobuf::Descriptor* MessageMSG3::descriptor() { - protobuf_AssignDescriptorsOnce(); - return MessageMSG3_descriptor_; +void MessageMSG2::set_has_size() { + _has_bits_[0] |= 0x00000002u; } - -const MessageMSG3& MessageMSG3::default_instance() { - if (default_instance_ == NULL) protobuf_AddDesc_Messages_2eproto(); - return *default_instance_; +void MessageMSG2::clear_has_size() { + _has_bits_[0] &= ~0x00000002u; +} +void MessageMSG2::clear_size() { + size_ = 0u; + clear_has_size(); +} + ::google::protobuf::uint32 MessageMSG2::size() const { + // @@protoc_insertion_point(field_get:Messages.MessageMSG2.size) + return size_; +} + void MessageMSG2::set_size(::google::protobuf::uint32 value) { + set_has_size(); + size_ = value; + // @@protoc_insertion_point(field_set:Messages.MessageMSG2.size) } -MessageMSG3* MessageMSG3::default_instance_ = NULL; - -MessageMSG3* MessageMSG3::New() const { - return new MessageMSG3; +// repeated uint32 public_key_gx = 3 [packed = true]; +int MessageMSG2::public_key_gx_size() const { + return public_key_gx_.size(); +} +void MessageMSG2::clear_public_key_gx() { + public_key_gx_.Clear(); +} + ::google::protobuf::uint32 MessageMSG2::public_key_gx(int index) const { + // @@protoc_insertion_point(field_get:Messages.MessageMSG2.public_key_gx) + return public_key_gx_.Get(index); +} + void MessageMSG2::set_public_key_gx(int index, ::google::protobuf::uint32 value) { + public_key_gx_.Set(index, value); + // @@protoc_insertion_point(field_set:Messages.MessageMSG2.public_key_gx) +} + void MessageMSG2::add_public_key_gx(::google::protobuf::uint32 value) { + public_key_gx_.Add(value); + // @@protoc_insertion_point(field_add:Messages.MessageMSG2.public_key_gx) +} + const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& +MessageMSG2::public_key_gx() const { + // @@protoc_insertion_point(field_list:Messages.MessageMSG2.public_key_gx) + return public_key_gx_; +} + ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* +MessageMSG2::mutable_public_key_gx() { + // @@protoc_insertion_point(field_mutable_list:Messages.MessageMSG2.public_key_gx) + return &public_key_gx_; } -void MessageMSG3::Clear() { -#define OFFSET_OF_FIELD_(f) (reinterpret_cast( \ - &reinterpret_cast(16)->f) - \ - reinterpret_cast(16)) +// repeated uint32 public_key_gy = 4 [packed = true]; +int MessageMSG2::public_key_gy_size() const { + return public_key_gy_.size(); +} +void MessageMSG2::clear_public_key_gy() { + public_key_gy_.Clear(); +} + ::google::protobuf::uint32 MessageMSG2::public_key_gy(int index) const { + // @@protoc_insertion_point(field_get:Messages.MessageMSG2.public_key_gy) + return public_key_gy_.Get(index); +} + void MessageMSG2::set_public_key_gy(int index, ::google::protobuf::uint32 value) { + public_key_gy_.Set(index, value); + // @@protoc_insertion_point(field_set:Messages.MessageMSG2.public_key_gy) +} + void MessageMSG2::add_public_key_gy(::google::protobuf::uint32 value) { + public_key_gy_.Add(value); + // @@protoc_insertion_point(field_add:Messages.MessageMSG2.public_key_gy) +} + const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& +MessageMSG2::public_key_gy() const { + // @@protoc_insertion_point(field_list:Messages.MessageMSG2.public_key_gy) + return public_key_gy_; +} + ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* +MessageMSG2::mutable_public_key_gy() { + // @@protoc_insertion_point(field_mutable_list:Messages.MessageMSG2.public_key_gy) + return &public_key_gy_; +} -#define ZR_(first, last) do { \ - size_t f = OFFSET_OF_FIELD_(first); \ - size_t n = OFFSET_OF_FIELD_(last) - f + sizeof(last); \ - ::memset(&first, 0, n); \ - } while (0) +// optional uint32 quote_type = 5; +bool MessageMSG2::has_quote_type() const { + return (_has_bits_[0] & 0x00000010u) != 0; +} +void MessageMSG2::set_has_quote_type() { + _has_bits_[0] |= 0x00000010u; +} +void MessageMSG2::clear_has_quote_type() { + _has_bits_[0] &= ~0x00000010u; +} +void MessageMSG2::clear_quote_type() { + quote_type_ = 0u; + clear_has_quote_type(); +} + ::google::protobuf::uint32 MessageMSG2::quote_type() const { + // @@protoc_insertion_point(field_get:Messages.MessageMSG2.quote_type) + return quote_type_; +} + void MessageMSG2::set_quote_type(::google::protobuf::uint32 value) { + set_has_quote_type(); + quote_type_ = value; + // @@protoc_insertion_point(field_set:Messages.MessageMSG2.quote_type) +} + +// repeated uint32 spid = 6 [packed = true]; +int MessageMSG2::spid_size() const { + return spid_.size(); +} +void MessageMSG2::clear_spid() { + spid_.Clear(); +} + ::google::protobuf::uint32 MessageMSG2::spid(int index) const { + // @@protoc_insertion_point(field_get:Messages.MessageMSG2.spid) + return spid_.Get(index); +} + void MessageMSG2::set_spid(int index, ::google::protobuf::uint32 value) { + spid_.Set(index, value); + // @@protoc_insertion_point(field_set:Messages.MessageMSG2.spid) +} + void MessageMSG2::add_spid(::google::protobuf::uint32 value) { + spid_.Add(value); + // @@protoc_insertion_point(field_add:Messages.MessageMSG2.spid) +} + const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& +MessageMSG2::spid() const { + // @@protoc_insertion_point(field_list:Messages.MessageMSG2.spid) + return spid_; +} + ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* +MessageMSG2::mutable_spid() { + // @@protoc_insertion_point(field_mutable_list:Messages.MessageMSG2.spid) + return &spid_; +} + +// optional uint32 cmac_kdf_id = 7; +bool MessageMSG2::has_cmac_kdf_id() const { + return (_has_bits_[0] & 0x00000040u) != 0; +} +void MessageMSG2::set_has_cmac_kdf_id() { + _has_bits_[0] |= 0x00000040u; +} +void MessageMSG2::clear_has_cmac_kdf_id() { + _has_bits_[0] &= ~0x00000040u; +} +void MessageMSG2::clear_cmac_kdf_id() { + cmac_kdf_id_ = 0u; + clear_has_cmac_kdf_id(); +} + ::google::protobuf::uint32 MessageMSG2::cmac_kdf_id() const { + // @@protoc_insertion_point(field_get:Messages.MessageMSG2.cmac_kdf_id) + return cmac_kdf_id_; +} + void MessageMSG2::set_cmac_kdf_id(::google::protobuf::uint32 value) { + set_has_cmac_kdf_id(); + cmac_kdf_id_ = value; + // @@protoc_insertion_point(field_set:Messages.MessageMSG2.cmac_kdf_id) +} + +// repeated uint32 signature_x = 8 [packed = true]; +int MessageMSG2::signature_x_size() const { + return signature_x_.size(); +} +void MessageMSG2::clear_signature_x() { + signature_x_.Clear(); +} + ::google::protobuf::uint32 MessageMSG2::signature_x(int index) const { + // @@protoc_insertion_point(field_get:Messages.MessageMSG2.signature_x) + return signature_x_.Get(index); +} + void MessageMSG2::set_signature_x(int index, ::google::protobuf::uint32 value) { + signature_x_.Set(index, value); + // @@protoc_insertion_point(field_set:Messages.MessageMSG2.signature_x) +} + void MessageMSG2::add_signature_x(::google::protobuf::uint32 value) { + signature_x_.Add(value); + // @@protoc_insertion_point(field_add:Messages.MessageMSG2.signature_x) +} + const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& +MessageMSG2::signature_x() const { + // @@protoc_insertion_point(field_list:Messages.MessageMSG2.signature_x) + return signature_x_; +} + ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* +MessageMSG2::mutable_signature_x() { + // @@protoc_insertion_point(field_mutable_list:Messages.MessageMSG2.signature_x) + return &signature_x_; +} + +// repeated uint32 signature_y = 9 [packed = true]; +int MessageMSG2::signature_y_size() const { + return signature_y_.size(); +} +void MessageMSG2::clear_signature_y() { + signature_y_.Clear(); +} + ::google::protobuf::uint32 MessageMSG2::signature_y(int index) const { + // @@protoc_insertion_point(field_get:Messages.MessageMSG2.signature_y) + return signature_y_.Get(index); +} + void MessageMSG2::set_signature_y(int index, ::google::protobuf::uint32 value) { + signature_y_.Set(index, value); + // @@protoc_insertion_point(field_set:Messages.MessageMSG2.signature_y) +} + void MessageMSG2::add_signature_y(::google::protobuf::uint32 value) { + signature_y_.Add(value); + // @@protoc_insertion_point(field_add:Messages.MessageMSG2.signature_y) +} + const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& +MessageMSG2::signature_y() const { + // @@protoc_insertion_point(field_list:Messages.MessageMSG2.signature_y) + return signature_y_; +} + ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* +MessageMSG2::mutable_signature_y() { + // @@protoc_insertion_point(field_mutable_list:Messages.MessageMSG2.signature_y) + return &signature_y_; +} + +// repeated uint32 smac = 10 [packed = true]; +int MessageMSG2::smac_size() const { + return smac_.size(); +} +void MessageMSG2::clear_smac() { + smac_.Clear(); +} + ::google::protobuf::uint32 MessageMSG2::smac(int index) const { + // @@protoc_insertion_point(field_get:Messages.MessageMSG2.smac) + return smac_.Get(index); +} + void MessageMSG2::set_smac(int index, ::google::protobuf::uint32 value) { + smac_.Set(index, value); + // @@protoc_insertion_point(field_set:Messages.MessageMSG2.smac) +} + void MessageMSG2::add_smac(::google::protobuf::uint32 value) { + smac_.Add(value); + // @@protoc_insertion_point(field_add:Messages.MessageMSG2.smac) +} + const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& +MessageMSG2::smac() const { + // @@protoc_insertion_point(field_list:Messages.MessageMSG2.smac) + return smac_; +} + ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* +MessageMSG2::mutable_smac() { + // @@protoc_insertion_point(field_mutable_list:Messages.MessageMSG2.smac) + return &smac_; +} + +// optional uint32 size_sigrl = 11; +bool MessageMSG2::has_size_sigrl() const { + return (_has_bits_[0] & 0x00000400u) != 0; +} +void MessageMSG2::set_has_size_sigrl() { + _has_bits_[0] |= 0x00000400u; +} +void MessageMSG2::clear_has_size_sigrl() { + _has_bits_[0] &= ~0x00000400u; +} +void MessageMSG2::clear_size_sigrl() { + size_sigrl_ = 0u; + clear_has_size_sigrl(); +} + ::google::protobuf::uint32 MessageMSG2::size_sigrl() const { + // @@protoc_insertion_point(field_get:Messages.MessageMSG2.size_sigrl) + return size_sigrl_; +} + void MessageMSG2::set_size_sigrl(::google::protobuf::uint32 value) { + set_has_size_sigrl(); + size_sigrl_ = value; + // @@protoc_insertion_point(field_set:Messages.MessageMSG2.size_sigrl) +} + +// repeated uint32 sigrl = 12 [packed = true]; +int MessageMSG2::sigrl_size() const { + return sigrl_.size(); +} +void MessageMSG2::clear_sigrl() { + sigrl_.Clear(); +} + ::google::protobuf::uint32 MessageMSG2::sigrl(int index) const { + // @@protoc_insertion_point(field_get:Messages.MessageMSG2.sigrl) + return sigrl_.Get(index); +} + void MessageMSG2::set_sigrl(int index, ::google::protobuf::uint32 value) { + sigrl_.Set(index, value); + // @@protoc_insertion_point(field_set:Messages.MessageMSG2.sigrl) +} + void MessageMSG2::add_sigrl(::google::protobuf::uint32 value) { + sigrl_.Add(value); + // @@protoc_insertion_point(field_add:Messages.MessageMSG2.sigrl) +} + const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& +MessageMSG2::sigrl() const { + // @@protoc_insertion_point(field_list:Messages.MessageMSG2.sigrl) + return sigrl_; +} + ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* +MessageMSG2::mutable_sigrl() { + // @@protoc_insertion_point(field_mutable_list:Messages.MessageMSG2.sigrl) + return &sigrl_; +} + +#endif // PROTOBUF_INLINE_NOT_IN_HEADERS + +// =================================================================== + +#if !defined(_MSC_VER) || _MSC_VER >= 1900 +const int MessageMSG3::kTypeFieldNumber; +const int MessageMSG3::kSizeFieldNumber; +const int MessageMSG3::kSgxMacFieldNumber; +const int MessageMSG3::kGaxMsg3FieldNumber; +const int MessageMSG3::kGayMsg3FieldNumber; +const int MessageMSG3::kSecPropertyFieldNumber; +const int MessageMSG3::kQuoteFieldNumber; +#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 + +MessageMSG3::MessageMSG3() + : ::google::protobuf::Message(), _internal_metadata_(NULL) { + SharedCtor(); + // @@protoc_insertion_point(constructor:Messages.MessageMSG3) +} + +void MessageMSG3::InitAsDefaultInstance() { +} + +MessageMSG3::MessageMSG3(const MessageMSG3& from) + : ::google::protobuf::Message(), + _internal_metadata_(NULL) { + SharedCtor(); + MergeFrom(from); + // @@protoc_insertion_point(copy_constructor:Messages.MessageMSG3) +} + +void MessageMSG3::SharedCtor() { + _cached_size_ = 0; + type_ = 0u; + size_ = 0u; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +MessageMSG3::~MessageMSG3() { + // @@protoc_insertion_point(destructor:Messages.MessageMSG3) + SharedDtor(); +} + +void MessageMSG3::SharedDtor() { + if (this != default_instance_) { + } +} + +void MessageMSG3::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* MessageMSG3::descriptor() { + protobuf_AssignDescriptorsOnce(); + return MessageMSG3_descriptor_; +} + +const MessageMSG3& MessageMSG3::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_Messages_2eproto(); + return *default_instance_; +} + +MessageMSG3* MessageMSG3::default_instance_ = NULL; + +MessageMSG3* MessageMSG3::New(::google::protobuf::Arena* arena) const { + MessageMSG3* n = new MessageMSG3; + if (arena != NULL) { + arena->Own(n); + } + return n; +} + +void MessageMSG3::Clear() { +// @@protoc_insertion_point(message_clear_start:Messages.MessageMSG3) +#if defined(__clang__) +#define ZR_HELPER_(f) \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Winvalid-offsetof\"") \ + __builtin_offsetof(MessageMSG3, f) \ + _Pragma("clang diagnostic pop") +#else +#define ZR_HELPER_(f) reinterpret_cast(\ + &reinterpret_cast(16)->f) +#endif + +#define ZR_(first, last) do {\ + ::memset(&first, 0,\ + ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\ +} while (0) ZR_(type_, size_); -#undef OFFSET_OF_FIELD_ +#undef ZR_HELPER_ #undef ZR_ sgx_mac_.Clear(); @@ -2241,12 +2916,14 @@ void MessageMSG3::Clear() { sec_property_.Clear(); quote_.Clear(); ::memset(_has_bits_, 0, sizeof(_has_bits_)); - mutable_unknown_fields()->Clear(); + if (_internal_metadata_.have_unknown_fields()) { + mutable_unknown_fields()->Clear(); + } } bool MessageMSG3::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure +#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; // @@protoc_insertion_point(parse_start:Messages.MessageMSG3) for (;;) { @@ -2458,15 +3135,15 @@ void MessageMSG3::SerializeWithCachedSizes( this->quote(i), output); } - if (!unknown_fields().empty()) { + if (_internal_metadata_.have_unknown_fields()) { ::google::protobuf::internal::WireFormat::SerializeUnknownFields( unknown_fields(), output); } // @@protoc_insertion_point(serialize_end:Messages.MessageMSG3) } -::google::protobuf::uint8* MessageMSG3::SerializeWithCachedSizesToArray( - ::google::protobuf::uint8* target) const { +::google::protobuf::uint8* MessageMSG3::InternalSerializeWithCachedSizesToArray( + bool deterministic, ::google::protobuf::uint8* target) const { // @@protoc_insertion_point(serialize_to_array_start:Messages.MessageMSG3) // required uint32 type = 1; if (has_type()) { @@ -2548,7 +3225,7 @@ ::google::protobuf::uint8* MessageMSG3::SerializeWithCachedSizesToArray( WriteUInt32NoTagToArray(this->quote(i), target); } - if (!unknown_fields().empty()) { + if (_internal_metadata_.have_unknown_fields()) { target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( unknown_fields(), target); } @@ -2557,24 +3234,22 @@ ::google::protobuf::uint8* MessageMSG3::SerializeWithCachedSizesToArray( } int MessageMSG3::ByteSize() const { +// @@protoc_insertion_point(message_byte_size_start:Messages.MessageMSG3) int total_size = 0; - if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { - // required uint32 type = 1; - if (has_type()) { - total_size += 1 + - ::google::protobuf::internal::WireFormatLite::UInt32Size( - this->type()); - } - - // optional uint32 size = 2; - if (has_size()) { - total_size += 1 + - ::google::protobuf::internal::WireFormatLite::UInt32Size( - this->size()); - } - + // required uint32 type = 1; + if (has_type()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::UInt32Size( + this->type()); } + // optional uint32 size = 2; + if (has_size()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::UInt32Size( + this->size()); + } + // repeated uint32 sgx_mac = 3 [packed = true]; { int data_size = 0; @@ -2660,7 +3335,7 @@ int MessageMSG3::ByteSize() const { total_size += data_size; } - if (!unknown_fields().empty()) { + if (_internal_metadata_.have_unknown_fields()) { total_size += ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( unknown_fields()); @@ -2672,19 +3347,27 @@ int MessageMSG3::ByteSize() const { } void MessageMSG3::MergeFrom(const ::google::protobuf::Message& from) { - GOOGLE_CHECK_NE(&from, this); - const MessageMSG3* source = - ::google::protobuf::internal::dynamic_cast_if_available( - &from); +// @@protoc_insertion_point(generalized_merge_from_start:Messages.MessageMSG3) + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } + const MessageMSG3* source = + ::google::protobuf::internal::DynamicCastToGenerated( + &from); if (source == NULL) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:Messages.MessageMSG3) ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:Messages.MessageMSG3) MergeFrom(*source); } } void MessageMSG3::MergeFrom(const MessageMSG3& from) { - GOOGLE_CHECK_NE(&from, this); +// @@protoc_insertion_point(class_specific_merge_from_start:Messages.MessageMSG3) + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } sgx_mac_.MergeFrom(from.sgx_mac_); gax_msg3_.MergeFrom(from.gax_msg3_); gay_msg3_.MergeFrom(from.gay_msg3_); @@ -2698,16 +3381,20 @@ void MessageMSG3::MergeFrom(const MessageMSG3& from) { set_size(from.size()); } } - mutable_unknown_fields()->MergeFrom(from.unknown_fields()); + if (from._internal_metadata_.have_unknown_fields()) { + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); + } } void MessageMSG3::CopyFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:Messages.MessageMSG3) if (&from == this) return; Clear(); MergeFrom(from); } void MessageMSG3::CopyFrom(const MessageMSG3& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:Messages.MessageMSG3) if (&from == this) return; Clear(); MergeFrom(from); @@ -2720,18 +3407,20 @@ bool MessageMSG3::IsInitialized() const { } void MessageMSG3::Swap(MessageMSG3* other) { - if (other != this) { - std::swap(type_, other->type_); - std::swap(size_, other->size_); - sgx_mac_.Swap(&other->sgx_mac_); - gax_msg3_.Swap(&other->gax_msg3_); - gay_msg3_.Swap(&other->gay_msg3_); - sec_property_.Swap(&other->sec_property_); - quote_.Swap(&other->quote_); - std::swap(_has_bits_[0], other->_has_bits_[0]); - _unknown_fields_.Swap(&other->_unknown_fields_); - std::swap(_cached_size_, other->_cached_size_); - } + if (other == this) return; + InternalSwap(other); +} +void MessageMSG3::InternalSwap(MessageMSG3* other) { + std::swap(type_, other->type_); + std::swap(size_, other->size_); + sgx_mac_.UnsafeArenaSwap(&other->sgx_mac_); + gax_msg3_.UnsafeArenaSwap(&other->gax_msg3_); + gay_msg3_.UnsafeArenaSwap(&other->gay_msg3_); + sec_property_.UnsafeArenaSwap(&other->sec_property_); + quote_.UnsafeArenaSwap(&other->quote_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _internal_metadata_.Swap(&other->_internal_metadata_); + std::swap(_cached_size_, other->_cached_size_); } ::google::protobuf::Metadata MessageMSG3::GetMetadata() const { @@ -2742,10 +3431,212 @@ ::google::protobuf::Metadata MessageMSG3::GetMetadata() const { return metadata; } +#if PROTOBUF_INLINE_NOT_IN_HEADERS +// MessageMSG3 + +// required uint32 type = 1; +bool MessageMSG3::has_type() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +void MessageMSG3::set_has_type() { + _has_bits_[0] |= 0x00000001u; +} +void MessageMSG3::clear_has_type() { + _has_bits_[0] &= ~0x00000001u; +} +void MessageMSG3::clear_type() { + type_ = 0u; + clear_has_type(); +} + ::google::protobuf::uint32 MessageMSG3::type() const { + // @@protoc_insertion_point(field_get:Messages.MessageMSG3.type) + return type_; +} + void MessageMSG3::set_type(::google::protobuf::uint32 value) { + set_has_type(); + type_ = value; + // @@protoc_insertion_point(field_set:Messages.MessageMSG3.type) +} + +// optional uint32 size = 2; +bool MessageMSG3::has_size() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} +void MessageMSG3::set_has_size() { + _has_bits_[0] |= 0x00000002u; +} +void MessageMSG3::clear_has_size() { + _has_bits_[0] &= ~0x00000002u; +} +void MessageMSG3::clear_size() { + size_ = 0u; + clear_has_size(); +} + ::google::protobuf::uint32 MessageMSG3::size() const { + // @@protoc_insertion_point(field_get:Messages.MessageMSG3.size) + return size_; +} + void MessageMSG3::set_size(::google::protobuf::uint32 value) { + set_has_size(); + size_ = value; + // @@protoc_insertion_point(field_set:Messages.MessageMSG3.size) +} + +// repeated uint32 sgx_mac = 3 [packed = true]; +int MessageMSG3::sgx_mac_size() const { + return sgx_mac_.size(); +} +void MessageMSG3::clear_sgx_mac() { + sgx_mac_.Clear(); +} + ::google::protobuf::uint32 MessageMSG3::sgx_mac(int index) const { + // @@protoc_insertion_point(field_get:Messages.MessageMSG3.sgx_mac) + return sgx_mac_.Get(index); +} + void MessageMSG3::set_sgx_mac(int index, ::google::protobuf::uint32 value) { + sgx_mac_.Set(index, value); + // @@protoc_insertion_point(field_set:Messages.MessageMSG3.sgx_mac) +} + void MessageMSG3::add_sgx_mac(::google::protobuf::uint32 value) { + sgx_mac_.Add(value); + // @@protoc_insertion_point(field_add:Messages.MessageMSG3.sgx_mac) +} + const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& +MessageMSG3::sgx_mac() const { + // @@protoc_insertion_point(field_list:Messages.MessageMSG3.sgx_mac) + return sgx_mac_; +} + ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* +MessageMSG3::mutable_sgx_mac() { + // @@protoc_insertion_point(field_mutable_list:Messages.MessageMSG3.sgx_mac) + return &sgx_mac_; +} + +// repeated uint32 gax_msg3 = 4 [packed = true]; +int MessageMSG3::gax_msg3_size() const { + return gax_msg3_.size(); +} +void MessageMSG3::clear_gax_msg3() { + gax_msg3_.Clear(); +} + ::google::protobuf::uint32 MessageMSG3::gax_msg3(int index) const { + // @@protoc_insertion_point(field_get:Messages.MessageMSG3.gax_msg3) + return gax_msg3_.Get(index); +} + void MessageMSG3::set_gax_msg3(int index, ::google::protobuf::uint32 value) { + gax_msg3_.Set(index, value); + // @@protoc_insertion_point(field_set:Messages.MessageMSG3.gax_msg3) +} + void MessageMSG3::add_gax_msg3(::google::protobuf::uint32 value) { + gax_msg3_.Add(value); + // @@protoc_insertion_point(field_add:Messages.MessageMSG3.gax_msg3) +} + const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& +MessageMSG3::gax_msg3() const { + // @@protoc_insertion_point(field_list:Messages.MessageMSG3.gax_msg3) + return gax_msg3_; +} + ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* +MessageMSG3::mutable_gax_msg3() { + // @@protoc_insertion_point(field_mutable_list:Messages.MessageMSG3.gax_msg3) + return &gax_msg3_; +} + +// repeated uint32 gay_msg3 = 5 [packed = true]; +int MessageMSG3::gay_msg3_size() const { + return gay_msg3_.size(); +} +void MessageMSG3::clear_gay_msg3() { + gay_msg3_.Clear(); +} + ::google::protobuf::uint32 MessageMSG3::gay_msg3(int index) const { + // @@protoc_insertion_point(field_get:Messages.MessageMSG3.gay_msg3) + return gay_msg3_.Get(index); +} + void MessageMSG3::set_gay_msg3(int index, ::google::protobuf::uint32 value) { + gay_msg3_.Set(index, value); + // @@protoc_insertion_point(field_set:Messages.MessageMSG3.gay_msg3) +} + void MessageMSG3::add_gay_msg3(::google::protobuf::uint32 value) { + gay_msg3_.Add(value); + // @@protoc_insertion_point(field_add:Messages.MessageMSG3.gay_msg3) +} + const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& +MessageMSG3::gay_msg3() const { + // @@protoc_insertion_point(field_list:Messages.MessageMSG3.gay_msg3) + return gay_msg3_; +} + ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* +MessageMSG3::mutable_gay_msg3() { + // @@protoc_insertion_point(field_mutable_list:Messages.MessageMSG3.gay_msg3) + return &gay_msg3_; +} + +// repeated uint32 sec_property = 6 [packed = true]; +int MessageMSG3::sec_property_size() const { + return sec_property_.size(); +} +void MessageMSG3::clear_sec_property() { + sec_property_.Clear(); +} + ::google::protobuf::uint32 MessageMSG3::sec_property(int index) const { + // @@protoc_insertion_point(field_get:Messages.MessageMSG3.sec_property) + return sec_property_.Get(index); +} + void MessageMSG3::set_sec_property(int index, ::google::protobuf::uint32 value) { + sec_property_.Set(index, value); + // @@protoc_insertion_point(field_set:Messages.MessageMSG3.sec_property) +} + void MessageMSG3::add_sec_property(::google::protobuf::uint32 value) { + sec_property_.Add(value); + // @@protoc_insertion_point(field_add:Messages.MessageMSG3.sec_property) +} + const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& +MessageMSG3::sec_property() const { + // @@protoc_insertion_point(field_list:Messages.MessageMSG3.sec_property) + return sec_property_; +} + ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* +MessageMSG3::mutable_sec_property() { + // @@protoc_insertion_point(field_mutable_list:Messages.MessageMSG3.sec_property) + return &sec_property_; +} + +// repeated uint32 quote = 7 [packed = true]; +int MessageMSG3::quote_size() const { + return quote_.size(); +} +void MessageMSG3::clear_quote() { + quote_.Clear(); +} + ::google::protobuf::uint32 MessageMSG3::quote(int index) const { + // @@protoc_insertion_point(field_get:Messages.MessageMSG3.quote) + return quote_.Get(index); +} + void MessageMSG3::set_quote(int index, ::google::protobuf::uint32 value) { + quote_.Set(index, value); + // @@protoc_insertion_point(field_set:Messages.MessageMSG3.quote) +} + void MessageMSG3::add_quote(::google::protobuf::uint32 value) { + quote_.Add(value); + // @@protoc_insertion_point(field_add:Messages.MessageMSG3.quote) +} + const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& +MessageMSG3::quote() const { + // @@protoc_insertion_point(field_list:Messages.MessageMSG3.quote) + return quote_; +} + ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* +MessageMSG3::mutable_quote() { + // @@protoc_insertion_point(field_mutable_list:Messages.MessageMSG3.quote) + return "e_; +} + +#endif // PROTOBUF_INLINE_NOT_IN_HEADERS // =================================================================== -#ifndef _MSC_VER +#if !defined(_MSC_VER) || _MSC_VER >= 1900 const int AttestationMessage::kTypeFieldNumber; const int AttestationMessage::kSizeFieldNumber; const int AttestationMessage::kEpidGroupStatusFieldNumber; @@ -2762,10 +3653,10 @@ const int AttestationMessage::kResultSizeFieldNumber; const int AttestationMessage::kReservedFieldNumber; const int AttestationMessage::kPayloadTagFieldNumber; const int AttestationMessage::kPayloadFieldNumber; -#endif // !_MSC_VER +#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 AttestationMessage::AttestationMessage() - : ::google::protobuf::Message() { + : ::google::protobuf::Message(), _internal_metadata_(NULL) { SharedCtor(); // @@protoc_insertion_point(constructor:Messages.AttestationMessage) } @@ -2774,7 +3665,8 @@ void AttestationMessage::InitAsDefaultInstance() { } AttestationMessage::AttestationMessage(const AttestationMessage& from) - : ::google::protobuf::Message() { + : ::google::protobuf::Message(), + _internal_metadata_(NULL) { SharedCtor(); MergeFrom(from); // @@protoc_insertion_point(copy_constructor:Messages.AttestationMessage) @@ -2818,28 +3710,39 @@ const AttestationMessage& AttestationMessage::default_instance() { AttestationMessage* AttestationMessage::default_instance_ = NULL; -AttestationMessage* AttestationMessage::New() const { - return new AttestationMessage; +AttestationMessage* AttestationMessage::New(::google::protobuf::Arena* arena) const { + AttestationMessage* n = new AttestationMessage; + if (arena != NULL) { + arena->Own(n); + } + return n; } void AttestationMessage::Clear() { -#define OFFSET_OF_FIELD_(f) (reinterpret_cast( \ - &reinterpret_cast(16)->f) - \ - reinterpret_cast(16)) - -#define ZR_(first, last) do { \ - size_t f = OFFSET_OF_FIELD_(first); \ - size_t n = OFFSET_OF_FIELD_(last) - f + sizeof(last); \ - ::memset(&first, 0, n); \ - } while (0) - - if (_has_bits_[0 / 32] & 31) { +// @@protoc_insertion_point(message_clear_start:Messages.AttestationMessage) +#if defined(__clang__) +#define ZR_HELPER_(f) \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Winvalid-offsetof\"") \ + __builtin_offsetof(AttestationMessage, f) \ + _Pragma("clang diagnostic pop") +#else +#define ZR_HELPER_(f) reinterpret_cast(\ + &reinterpret_cast(16)->f) +#endif + +#define ZR_(first, last) do {\ + ::memset(&first, 0,\ + ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\ +} while (0) + + if (_has_bits_[0 / 32] & 31u) { ZR_(type_, tcb_evaluation_status_); pse_evaluation_status_ = 0u; } result_size_ = 0u; -#undef OFFSET_OF_FIELD_ +#undef ZR_HELPER_ #undef ZR_ latest_equivalent_tcb_psvn_.Clear(); @@ -2853,12 +3756,14 @@ void AttestationMessage::Clear() { payload_tag_.Clear(); payload_.Clear(); ::memset(_has_bits_, 0, sizeof(_has_bits_)); - mutable_unknown_fields()->Clear(); + if (_internal_metadata_.have_unknown_fields()) { + mutable_unknown_fields()->Clear(); + } } bool AttestationMessage::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure +#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; // @@protoc_insertion_point(parse_start:Messages.AttestationMessage) for (;;) { @@ -3290,15 +4195,15 @@ void AttestationMessage::SerializeWithCachedSizes( this->payload(i), output); } - if (!unknown_fields().empty()) { + if (_internal_metadata_.have_unknown_fields()) { ::google::protobuf::internal::WireFormat::SerializeUnknownFields( unknown_fields(), output); } // @@protoc_insertion_point(serialize_end:Messages.AttestationMessage) } -::google::protobuf::uint8* AttestationMessage::SerializeWithCachedSizesToArray( - ::google::protobuf::uint8* target) const { +::google::protobuf::uint8* AttestationMessage::InternalSerializeWithCachedSizesToArray( + bool deterministic, ::google::protobuf::uint8* target) const { // @@protoc_insertion_point(serialize_to_array_start:Messages.AttestationMessage) // required uint32 type = 1; if (has_type()) { @@ -3470,7 +4375,7 @@ ::google::protobuf::uint8* AttestationMessage::SerializeWithCachedSizesToArray( WriteUInt32NoTagToArray(this->payload(i), target); } - if (!unknown_fields().empty()) { + if (_internal_metadata_.have_unknown_fields()) { target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( unknown_fields(), target); } @@ -3478,24 +4383,45 @@ ::google::protobuf::uint8* AttestationMessage::SerializeWithCachedSizesToArray( return target; } +int AttestationMessage::RequiredFieldsByteSizeFallback() const { +// @@protoc_insertion_point(required_fields_byte_size_fallback_start:Messages.AttestationMessage) + int total_size = 0; + + if (has_type()) { + // required uint32 type = 1; + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::UInt32Size( + this->type()); + } + + if (has_size()) { + // required uint32 size = 2; + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::UInt32Size( + this->size()); + } + + return total_size; +} int AttestationMessage::ByteSize() const { +// @@protoc_insertion_point(message_byte_size_start:Messages.AttestationMessage) int total_size = 0; - if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (((_has_bits_[0] & 0x00000003) ^ 0x00000003) == 0) { // All required fields are present. // required uint32 type = 1; - if (has_type()) { - total_size += 1 + - ::google::protobuf::internal::WireFormatLite::UInt32Size( - this->type()); - } + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::UInt32Size( + this->type()); // required uint32 size = 2; - if (has_size()) { - total_size += 1 + - ::google::protobuf::internal::WireFormatLite::UInt32Size( - this->size()); - } + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::UInt32Size( + this->size()); + } else { + total_size += RequiredFieldsByteSizeFallback(); + } + if (_has_bits_[2 / 32] & 28u) { // optional uint32 epid_group_status = 3; if (has_epid_group_status()) { total_size += 1 + @@ -3518,15 +4444,13 @@ int AttestationMessage::ByteSize() const { } } - if (_has_bits_[12 / 32] & (0xffu << (12 % 32))) { - // optional uint32 result_size = 13; - if (has_result_size()) { - total_size += 1 + - ::google::protobuf::internal::WireFormatLite::UInt32Size( - this->result_size()); - } - + // optional uint32 result_size = 13; + if (has_result_size()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::UInt32Size( + this->result_size()); } + // repeated uint32 latest_equivalent_tcb_psvn = 6 [packed = true]; { int data_size = 0; @@ -3697,7 +4621,7 @@ int AttestationMessage::ByteSize() const { total_size += data_size; } - if (!unknown_fields().empty()) { + if (_internal_metadata_.have_unknown_fields()) { total_size += ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( unknown_fields()); @@ -3709,19 +4633,27 @@ int AttestationMessage::ByteSize() const { } void AttestationMessage::MergeFrom(const ::google::protobuf::Message& from) { - GOOGLE_CHECK_NE(&from, this); - const AttestationMessage* source = - ::google::protobuf::internal::dynamic_cast_if_available( - &from); +// @@protoc_insertion_point(generalized_merge_from_start:Messages.AttestationMessage) + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } + const AttestationMessage* source = + ::google::protobuf::internal::DynamicCastToGenerated( + &from); if (source == NULL) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:Messages.AttestationMessage) ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:Messages.AttestationMessage) MergeFrom(*source); } } void AttestationMessage::MergeFrom(const AttestationMessage& from) { - GOOGLE_CHECK_NE(&from, this); +// @@protoc_insertion_point(class_specific_merge_from_start:Messages.AttestationMessage) + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } latest_equivalent_tcb_psvn_.MergeFrom(from.latest_equivalent_tcb_psvn_); latest_pse_isvsvn_.MergeFrom(from.latest_pse_isvsvn_); latest_psda_svn_.MergeFrom(from.latest_psda_svn_); @@ -3754,16 +4686,20 @@ void AttestationMessage::MergeFrom(const AttestationMessage& from) { set_result_size(from.result_size()); } } - mutable_unknown_fields()->MergeFrom(from.unknown_fields()); + if (from._internal_metadata_.have_unknown_fields()) { + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); + } } void AttestationMessage::CopyFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:Messages.AttestationMessage) if (&from == this) return; Clear(); MergeFrom(from); } void AttestationMessage::CopyFrom(const AttestationMessage& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:Messages.AttestationMessage) if (&from == this) return; Clear(); MergeFrom(from); @@ -3776,27 +4712,29 @@ bool AttestationMessage::IsInitialized() const { } void AttestationMessage::Swap(AttestationMessage* other) { - if (other != this) { - std::swap(type_, other->type_); - std::swap(size_, other->size_); - std::swap(epid_group_status_, other->epid_group_status_); - std::swap(tcb_evaluation_status_, other->tcb_evaluation_status_); - std::swap(pse_evaluation_status_, other->pse_evaluation_status_); - latest_equivalent_tcb_psvn_.Swap(&other->latest_equivalent_tcb_psvn_); - latest_pse_isvsvn_.Swap(&other->latest_pse_isvsvn_); - latest_psda_svn_.Swap(&other->latest_psda_svn_); - performance_rekey_gid_.Swap(&other->performance_rekey_gid_); - ec_sign256_x_.Swap(&other->ec_sign256_x_); - ec_sign256_y_.Swap(&other->ec_sign256_y_); - mac_smk_.Swap(&other->mac_smk_); - std::swap(result_size_, other->result_size_); - reserved_.Swap(&other->reserved_); - payload_tag_.Swap(&other->payload_tag_); - payload_.Swap(&other->payload_); - std::swap(_has_bits_[0], other->_has_bits_[0]); - _unknown_fields_.Swap(&other->_unknown_fields_); - std::swap(_cached_size_, other->_cached_size_); - } + if (other == this) return; + InternalSwap(other); +} +void AttestationMessage::InternalSwap(AttestationMessage* other) { + std::swap(type_, other->type_); + std::swap(size_, other->size_); + std::swap(epid_group_status_, other->epid_group_status_); + std::swap(tcb_evaluation_status_, other->tcb_evaluation_status_); + std::swap(pse_evaluation_status_, other->pse_evaluation_status_); + latest_equivalent_tcb_psvn_.UnsafeArenaSwap(&other->latest_equivalent_tcb_psvn_); + latest_pse_isvsvn_.UnsafeArenaSwap(&other->latest_pse_isvsvn_); + latest_psda_svn_.UnsafeArenaSwap(&other->latest_psda_svn_); + performance_rekey_gid_.UnsafeArenaSwap(&other->performance_rekey_gid_); + ec_sign256_x_.UnsafeArenaSwap(&other->ec_sign256_x_); + ec_sign256_y_.UnsafeArenaSwap(&other->ec_sign256_y_); + mac_smk_.UnsafeArenaSwap(&other->mac_smk_); + std::swap(result_size_, other->result_size_); + reserved_.UnsafeArenaSwap(&other->reserved_); + payload_tag_.UnsafeArenaSwap(&other->payload_tag_); + payload_.UnsafeArenaSwap(&other->payload_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _internal_metadata_.Swap(&other->_internal_metadata_); + std::swap(_cached_size_, other->_cached_size_); } ::google::protobuf::Metadata AttestationMessage::GetMetadata() const { @@ -3807,735 +4745,454 @@ ::google::protobuf::Metadata AttestationMessage::GetMetadata() const { return metadata; } +#if PROTOBUF_INLINE_NOT_IN_HEADERS +// AttestationMessage -// =================================================================== - -#ifndef _MSC_VER -const int SecretMessage::kTypeFieldNumber; -const int SecretMessage::kSizeFieldNumber; -const int SecretMessage::kEncrypedPkeySizeFieldNumber; -const int SecretMessage::kEncrypedX509SizeFieldNumber; -const int SecretMessage::kEncryptedContentFieldNumber; -const int SecretMessage::kMacSmkFieldNumber; -const int SecretMessage::kEncryptedPkeyFieldNumber; -const int SecretMessage::kEncryptedPkeyMacSmkFieldNumber; -const int SecretMessage::kEncryptedX509FieldNumber; -const int SecretMessage::kEncryptedX509MacSmkFieldNumber; -#endif // !_MSC_VER - -SecretMessage::SecretMessage() - : ::google::protobuf::Message() { - SharedCtor(); - // @@protoc_insertion_point(constructor:Messages.SecretMessage) +// required uint32 type = 1; +bool AttestationMessage::has_type() const { + return (_has_bits_[0] & 0x00000001u) != 0; } - -void SecretMessage::InitAsDefaultInstance() { +void AttestationMessage::set_has_type() { + _has_bits_[0] |= 0x00000001u; } - -SecretMessage::SecretMessage(const SecretMessage& from) - : ::google::protobuf::Message() { - SharedCtor(); - MergeFrom(from); - // @@protoc_insertion_point(copy_constructor:Messages.SecretMessage) +void AttestationMessage::clear_has_type() { + _has_bits_[0] &= ~0x00000001u; } - -void SecretMessage::SharedCtor() { - _cached_size_ = 0; +void AttestationMessage::clear_type() { type_ = 0u; - size_ = 0u; - encryped_pkey_size_ = 0u; - encryped_x509_size_ = 0u; - ::memset(_has_bits_, 0, sizeof(_has_bits_)); + clear_has_type(); +} + ::google::protobuf::uint32 AttestationMessage::type() const { + // @@protoc_insertion_point(field_get:Messages.AttestationMessage.type) + return type_; +} + void AttestationMessage::set_type(::google::protobuf::uint32 value) { + set_has_type(); + type_ = value; + // @@protoc_insertion_point(field_set:Messages.AttestationMessage.type) } -SecretMessage::~SecretMessage() { - // @@protoc_insertion_point(destructor:Messages.SecretMessage) - SharedDtor(); +// required uint32 size = 2; +bool AttestationMessage::has_size() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} +void AttestationMessage::set_has_size() { + _has_bits_[0] |= 0x00000002u; +} +void AttestationMessage::clear_has_size() { + _has_bits_[0] &= ~0x00000002u; +} +void AttestationMessage::clear_size() { + size_ = 0u; + clear_has_size(); +} + ::google::protobuf::uint32 AttestationMessage::size() const { + // @@protoc_insertion_point(field_get:Messages.AttestationMessage.size) + return size_; +} + void AttestationMessage::set_size(::google::protobuf::uint32 value) { + set_has_size(); + size_ = value; + // @@protoc_insertion_point(field_set:Messages.AttestationMessage.size) } -void SecretMessage::SharedDtor() { - if (this != default_instance_) { - } +// optional uint32 epid_group_status = 3; +bool AttestationMessage::has_epid_group_status() const { + return (_has_bits_[0] & 0x00000004u) != 0; +} +void AttestationMessage::set_has_epid_group_status() { + _has_bits_[0] |= 0x00000004u; +} +void AttestationMessage::clear_has_epid_group_status() { + _has_bits_[0] &= ~0x00000004u; +} +void AttestationMessage::clear_epid_group_status() { + epid_group_status_ = 0u; + clear_has_epid_group_status(); +} + ::google::protobuf::uint32 AttestationMessage::epid_group_status() const { + // @@protoc_insertion_point(field_get:Messages.AttestationMessage.epid_group_status) + return epid_group_status_; +} + void AttestationMessage::set_epid_group_status(::google::protobuf::uint32 value) { + set_has_epid_group_status(); + epid_group_status_ = value; + // @@protoc_insertion_point(field_set:Messages.AttestationMessage.epid_group_status) } -void SecretMessage::SetCachedSize(int size) const { - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); +// optional uint32 tcb_evaluation_status = 4; +bool AttestationMessage::has_tcb_evaluation_status() const { + return (_has_bits_[0] & 0x00000008u) != 0; } -const ::google::protobuf::Descriptor* SecretMessage::descriptor() { - protobuf_AssignDescriptorsOnce(); - return SecretMessage_descriptor_; +void AttestationMessage::set_has_tcb_evaluation_status() { + _has_bits_[0] |= 0x00000008u; +} +void AttestationMessage::clear_has_tcb_evaluation_status() { + _has_bits_[0] &= ~0x00000008u; +} +void AttestationMessage::clear_tcb_evaluation_status() { + tcb_evaluation_status_ = 0u; + clear_has_tcb_evaluation_status(); +} + ::google::protobuf::uint32 AttestationMessage::tcb_evaluation_status() const { + // @@protoc_insertion_point(field_get:Messages.AttestationMessage.tcb_evaluation_status) + return tcb_evaluation_status_; +} + void AttestationMessage::set_tcb_evaluation_status(::google::protobuf::uint32 value) { + set_has_tcb_evaluation_status(); + tcb_evaluation_status_ = value; + // @@protoc_insertion_point(field_set:Messages.AttestationMessage.tcb_evaluation_status) } -const SecretMessage& SecretMessage::default_instance() { - if (default_instance_ == NULL) protobuf_AddDesc_Messages_2eproto(); - return *default_instance_; +// optional uint32 pse_evaluation_status = 5; +bool AttestationMessage::has_pse_evaluation_status() const { + return (_has_bits_[0] & 0x00000010u) != 0; +} +void AttestationMessage::set_has_pse_evaluation_status() { + _has_bits_[0] |= 0x00000010u; +} +void AttestationMessage::clear_has_pse_evaluation_status() { + _has_bits_[0] &= ~0x00000010u; +} +void AttestationMessage::clear_pse_evaluation_status() { + pse_evaluation_status_ = 0u; + clear_has_pse_evaluation_status(); +} + ::google::protobuf::uint32 AttestationMessage::pse_evaluation_status() const { + // @@protoc_insertion_point(field_get:Messages.AttestationMessage.pse_evaluation_status) + return pse_evaluation_status_; +} + void AttestationMessage::set_pse_evaluation_status(::google::protobuf::uint32 value) { + set_has_pse_evaluation_status(); + pse_evaluation_status_ = value; + // @@protoc_insertion_point(field_set:Messages.AttestationMessage.pse_evaluation_status) } -SecretMessage* SecretMessage::default_instance_ = NULL; +// repeated uint32 latest_equivalent_tcb_psvn = 6 [packed = true]; +int AttestationMessage::latest_equivalent_tcb_psvn_size() const { + return latest_equivalent_tcb_psvn_.size(); +} +void AttestationMessage::clear_latest_equivalent_tcb_psvn() { + latest_equivalent_tcb_psvn_.Clear(); +} + ::google::protobuf::uint32 AttestationMessage::latest_equivalent_tcb_psvn(int index) const { + // @@protoc_insertion_point(field_get:Messages.AttestationMessage.latest_equivalent_tcb_psvn) + return latest_equivalent_tcb_psvn_.Get(index); +} + void AttestationMessage::set_latest_equivalent_tcb_psvn(int index, ::google::protobuf::uint32 value) { + latest_equivalent_tcb_psvn_.Set(index, value); + // @@protoc_insertion_point(field_set:Messages.AttestationMessage.latest_equivalent_tcb_psvn) +} + void AttestationMessage::add_latest_equivalent_tcb_psvn(::google::protobuf::uint32 value) { + latest_equivalent_tcb_psvn_.Add(value); + // @@protoc_insertion_point(field_add:Messages.AttestationMessage.latest_equivalent_tcb_psvn) +} + const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& +AttestationMessage::latest_equivalent_tcb_psvn() const { + // @@protoc_insertion_point(field_list:Messages.AttestationMessage.latest_equivalent_tcb_psvn) + return latest_equivalent_tcb_psvn_; +} + ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* +AttestationMessage::mutable_latest_equivalent_tcb_psvn() { + // @@protoc_insertion_point(field_mutable_list:Messages.AttestationMessage.latest_equivalent_tcb_psvn) + return &latest_equivalent_tcb_psvn_; +} -SecretMessage* SecretMessage::New() const { - return new SecretMessage; +// repeated uint32 latest_pse_isvsvn = 7 [packed = true]; +int AttestationMessage::latest_pse_isvsvn_size() const { + return latest_pse_isvsvn_.size(); +} +void AttestationMessage::clear_latest_pse_isvsvn() { + latest_pse_isvsvn_.Clear(); +} + ::google::protobuf::uint32 AttestationMessage::latest_pse_isvsvn(int index) const { + // @@protoc_insertion_point(field_get:Messages.AttestationMessage.latest_pse_isvsvn) + return latest_pse_isvsvn_.Get(index); +} + void AttestationMessage::set_latest_pse_isvsvn(int index, ::google::protobuf::uint32 value) { + latest_pse_isvsvn_.Set(index, value); + // @@protoc_insertion_point(field_set:Messages.AttestationMessage.latest_pse_isvsvn) +} + void AttestationMessage::add_latest_pse_isvsvn(::google::protobuf::uint32 value) { + latest_pse_isvsvn_.Add(value); + // @@protoc_insertion_point(field_add:Messages.AttestationMessage.latest_pse_isvsvn) +} + const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& +AttestationMessage::latest_pse_isvsvn() const { + // @@protoc_insertion_point(field_list:Messages.AttestationMessage.latest_pse_isvsvn) + return latest_pse_isvsvn_; +} + ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* +AttestationMessage::mutable_latest_pse_isvsvn() { + // @@protoc_insertion_point(field_mutable_list:Messages.AttestationMessage.latest_pse_isvsvn) + return &latest_pse_isvsvn_; } -void SecretMessage::Clear() { -#define OFFSET_OF_FIELD_(f) (reinterpret_cast( \ - &reinterpret_cast(16)->f) - \ - reinterpret_cast(16)) +// repeated uint32 latest_psda_svn = 8 [packed = true]; +int AttestationMessage::latest_psda_svn_size() const { + return latest_psda_svn_.size(); +} +void AttestationMessage::clear_latest_psda_svn() { + latest_psda_svn_.Clear(); +} + ::google::protobuf::uint32 AttestationMessage::latest_psda_svn(int index) const { + // @@protoc_insertion_point(field_get:Messages.AttestationMessage.latest_psda_svn) + return latest_psda_svn_.Get(index); +} + void AttestationMessage::set_latest_psda_svn(int index, ::google::protobuf::uint32 value) { + latest_psda_svn_.Set(index, value); + // @@protoc_insertion_point(field_set:Messages.AttestationMessage.latest_psda_svn) +} + void AttestationMessage::add_latest_psda_svn(::google::protobuf::uint32 value) { + latest_psda_svn_.Add(value); + // @@protoc_insertion_point(field_add:Messages.AttestationMessage.latest_psda_svn) +} + const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& +AttestationMessage::latest_psda_svn() const { + // @@protoc_insertion_point(field_list:Messages.AttestationMessage.latest_psda_svn) + return latest_psda_svn_; +} + ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* +AttestationMessage::mutable_latest_psda_svn() { + // @@protoc_insertion_point(field_mutable_list:Messages.AttestationMessage.latest_psda_svn) + return &latest_psda_svn_; +} -#define ZR_(first, last) do { \ - size_t f = OFFSET_OF_FIELD_(first); \ - size_t n = OFFSET_OF_FIELD_(last) - f + sizeof(last); \ - ::memset(&first, 0, n); \ - } while (0) +// repeated uint32 performance_rekey_gid = 9 [packed = true]; +int AttestationMessage::performance_rekey_gid_size() const { + return performance_rekey_gid_.size(); +} +void AttestationMessage::clear_performance_rekey_gid() { + performance_rekey_gid_.Clear(); +} + ::google::protobuf::uint32 AttestationMessage::performance_rekey_gid(int index) const { + // @@protoc_insertion_point(field_get:Messages.AttestationMessage.performance_rekey_gid) + return performance_rekey_gid_.Get(index); +} + void AttestationMessage::set_performance_rekey_gid(int index, ::google::protobuf::uint32 value) { + performance_rekey_gid_.Set(index, value); + // @@protoc_insertion_point(field_set:Messages.AttestationMessage.performance_rekey_gid) +} + void AttestationMessage::add_performance_rekey_gid(::google::protobuf::uint32 value) { + performance_rekey_gid_.Add(value); + // @@protoc_insertion_point(field_add:Messages.AttestationMessage.performance_rekey_gid) +} + const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& +AttestationMessage::performance_rekey_gid() const { + // @@protoc_insertion_point(field_list:Messages.AttestationMessage.performance_rekey_gid) + return performance_rekey_gid_; +} + ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* +AttestationMessage::mutable_performance_rekey_gid() { + // @@protoc_insertion_point(field_mutable_list:Messages.AttestationMessage.performance_rekey_gid) + return &performance_rekey_gid_; +} - ZR_(type_, encryped_x509_size_); +// repeated uint32 ec_sign256_x = 10 [packed = true]; +int AttestationMessage::ec_sign256_x_size() const { + return ec_sign256_x_.size(); +} +void AttestationMessage::clear_ec_sign256_x() { + ec_sign256_x_.Clear(); +} + ::google::protobuf::uint32 AttestationMessage::ec_sign256_x(int index) const { + // @@protoc_insertion_point(field_get:Messages.AttestationMessage.ec_sign256_x) + return ec_sign256_x_.Get(index); +} + void AttestationMessage::set_ec_sign256_x(int index, ::google::protobuf::uint32 value) { + ec_sign256_x_.Set(index, value); + // @@protoc_insertion_point(field_set:Messages.AttestationMessage.ec_sign256_x) +} + void AttestationMessage::add_ec_sign256_x(::google::protobuf::uint32 value) { + ec_sign256_x_.Add(value); + // @@protoc_insertion_point(field_add:Messages.AttestationMessage.ec_sign256_x) +} + const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& +AttestationMessage::ec_sign256_x() const { + // @@protoc_insertion_point(field_list:Messages.AttestationMessage.ec_sign256_x) + return ec_sign256_x_; +} + ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* +AttestationMessage::mutable_ec_sign256_x() { + // @@protoc_insertion_point(field_mutable_list:Messages.AttestationMessage.ec_sign256_x) + return &ec_sign256_x_; +} -#undef OFFSET_OF_FIELD_ -#undef ZR_ +// repeated uint32 ec_sign256_y = 11 [packed = true]; +int AttestationMessage::ec_sign256_y_size() const { + return ec_sign256_y_.size(); +} +void AttestationMessage::clear_ec_sign256_y() { + ec_sign256_y_.Clear(); +} + ::google::protobuf::uint32 AttestationMessage::ec_sign256_y(int index) const { + // @@protoc_insertion_point(field_get:Messages.AttestationMessage.ec_sign256_y) + return ec_sign256_y_.Get(index); +} + void AttestationMessage::set_ec_sign256_y(int index, ::google::protobuf::uint32 value) { + ec_sign256_y_.Set(index, value); + // @@protoc_insertion_point(field_set:Messages.AttestationMessage.ec_sign256_y) +} + void AttestationMessage::add_ec_sign256_y(::google::protobuf::uint32 value) { + ec_sign256_y_.Add(value); + // @@protoc_insertion_point(field_add:Messages.AttestationMessage.ec_sign256_y) +} + const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& +AttestationMessage::ec_sign256_y() const { + // @@protoc_insertion_point(field_list:Messages.AttestationMessage.ec_sign256_y) + return ec_sign256_y_; +} + ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* +AttestationMessage::mutable_ec_sign256_y() { + // @@protoc_insertion_point(field_mutable_list:Messages.AttestationMessage.ec_sign256_y) + return &ec_sign256_y_; +} - encrypted_content_.Clear(); +// repeated uint32 mac_smk = 12 [packed = true]; +int AttestationMessage::mac_smk_size() const { + return mac_smk_.size(); +} +void AttestationMessage::clear_mac_smk() { mac_smk_.Clear(); - encrypted_pkey_.Clear(); - encrypted_pkey_mac_smk_.Clear(); - encrypted_x509_.Clear(); - encrypted_x509_mac_smk_.Clear(); - ::memset(_has_bits_, 0, sizeof(_has_bits_)); - mutable_unknown_fields()->Clear(); +} + ::google::protobuf::uint32 AttestationMessage::mac_smk(int index) const { + // @@protoc_insertion_point(field_get:Messages.AttestationMessage.mac_smk) + return mac_smk_.Get(index); +} + void AttestationMessage::set_mac_smk(int index, ::google::protobuf::uint32 value) { + mac_smk_.Set(index, value); + // @@protoc_insertion_point(field_set:Messages.AttestationMessage.mac_smk) +} + void AttestationMessage::add_mac_smk(::google::protobuf::uint32 value) { + mac_smk_.Add(value); + // @@protoc_insertion_point(field_add:Messages.AttestationMessage.mac_smk) +} + const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& +AttestationMessage::mac_smk() const { + // @@protoc_insertion_point(field_list:Messages.AttestationMessage.mac_smk) + return mac_smk_; +} + ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* +AttestationMessage::mutable_mac_smk() { + // @@protoc_insertion_point(field_mutable_list:Messages.AttestationMessage.mac_smk) + return &mac_smk_; } -bool SecretMessage::MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure - ::google::protobuf::uint32 tag; - // @@protoc_insertion_point(parse_start:Messages.SecretMessage) - for (;;) { - ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127); - tag = p.first; - if (!p.second) goto handle_unusual; - switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { - // required uint32 type = 1; - case 1: { - if (tag == 8) { - DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< - ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>( - input, &type_))); - set_has_type(); - } else { - goto handle_unusual; - } - if (input->ExpectTag(16)) goto parse_size; - break; - } - - // required uint32 size = 2; - case 2: { - if (tag == 16) { - parse_size: - DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< - ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>( - input, &size_))); - set_has_size(); - } else { - goto handle_unusual; - } - if (input->ExpectTag(24)) goto parse_encryped_pkey_size; - break; - } - - // optional uint32 encryped_pkey_size = 3; - case 3: { - if (tag == 24) { - parse_encryped_pkey_size: - DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< - ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>( - input, &encryped_pkey_size_))); - set_has_encryped_pkey_size(); - } else { - goto handle_unusual; - } - if (input->ExpectTag(32)) goto parse_encryped_x509_size; - break; - } - - // optional uint32 encryped_x509_size = 4; - case 4: { - if (tag == 32) { - parse_encryped_x509_size: - DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< - ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>( - input, &encryped_x509_size_))); - set_has_encryped_x509_size(); - } else { - goto handle_unusual; - } - if (input->ExpectTag(42)) goto parse_encrypted_content; - break; - } - - // repeated uint32 encrypted_content = 5 [packed = true]; - case 5: { - if (tag == 42) { - parse_encrypted_content: - DO_((::google::protobuf::internal::WireFormatLite::ReadPackedPrimitive< - ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>( - input, this->mutable_encrypted_content()))); - } else if (tag == 40) { - DO_((::google::protobuf::internal::WireFormatLite::ReadRepeatedPrimitiveNoInline< - ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>( - 1, 42, input, this->mutable_encrypted_content()))); - } else { - goto handle_unusual; - } - if (input->ExpectTag(50)) goto parse_mac_smk; - break; - } - - // repeated uint32 mac_smk = 6 [packed = true]; - case 6: { - if (tag == 50) { - parse_mac_smk: - DO_((::google::protobuf::internal::WireFormatLite::ReadPackedPrimitive< - ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>( - input, this->mutable_mac_smk()))); - } else if (tag == 48) { - DO_((::google::protobuf::internal::WireFormatLite::ReadRepeatedPrimitiveNoInline< - ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>( - 1, 50, input, this->mutable_mac_smk()))); - } else { - goto handle_unusual; - } - if (input->ExpectTag(58)) goto parse_encrypted_pkey; - break; - } - - // repeated uint32 encrypted_pkey = 7 [packed = true]; - case 7: { - if (tag == 58) { - parse_encrypted_pkey: - DO_((::google::protobuf::internal::WireFormatLite::ReadPackedPrimitive< - ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>( - input, this->mutable_encrypted_pkey()))); - } else if (tag == 56) { - DO_((::google::protobuf::internal::WireFormatLite::ReadRepeatedPrimitiveNoInline< - ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>( - 1, 58, input, this->mutable_encrypted_pkey()))); - } else { - goto handle_unusual; - } - if (input->ExpectTag(66)) goto parse_encrypted_pkey_mac_smk; - break; - } - - // repeated uint32 encrypted_pkey_mac_smk = 8 [packed = true]; - case 8: { - if (tag == 66) { - parse_encrypted_pkey_mac_smk: - DO_((::google::protobuf::internal::WireFormatLite::ReadPackedPrimitive< - ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>( - input, this->mutable_encrypted_pkey_mac_smk()))); - } else if (tag == 64) { - DO_((::google::protobuf::internal::WireFormatLite::ReadRepeatedPrimitiveNoInline< - ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>( - 1, 66, input, this->mutable_encrypted_pkey_mac_smk()))); - } else { - goto handle_unusual; - } - if (input->ExpectTag(74)) goto parse_encrypted_x509; - break; - } +// optional uint32 result_size = 13; +bool AttestationMessage::has_result_size() const { + return (_has_bits_[0] & 0x00001000u) != 0; +} +void AttestationMessage::set_has_result_size() { + _has_bits_[0] |= 0x00001000u; +} +void AttestationMessage::clear_has_result_size() { + _has_bits_[0] &= ~0x00001000u; +} +void AttestationMessage::clear_result_size() { + result_size_ = 0u; + clear_has_result_size(); +} + ::google::protobuf::uint32 AttestationMessage::result_size() const { + // @@protoc_insertion_point(field_get:Messages.AttestationMessage.result_size) + return result_size_; +} + void AttestationMessage::set_result_size(::google::protobuf::uint32 value) { + set_has_result_size(); + result_size_ = value; + // @@protoc_insertion_point(field_set:Messages.AttestationMessage.result_size) +} - // repeated uint32 encrypted_x509 = 9 [packed = true]; - case 9: { - if (tag == 74) { - parse_encrypted_x509: - DO_((::google::protobuf::internal::WireFormatLite::ReadPackedPrimitive< - ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>( - input, this->mutable_encrypted_x509()))); - } else if (tag == 72) { - DO_((::google::protobuf::internal::WireFormatLite::ReadRepeatedPrimitiveNoInline< - ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>( - 1, 74, input, this->mutable_encrypted_x509()))); - } else { - goto handle_unusual; - } - if (input->ExpectTag(82)) goto parse_encrypted_x509_mac_smk; - break; - } +// repeated uint32 reserved = 14 [packed = true]; +int AttestationMessage::reserved_size() const { + return reserved_.size(); +} +void AttestationMessage::clear_reserved() { + reserved_.Clear(); +} + ::google::protobuf::uint32 AttestationMessage::reserved(int index) const { + // @@protoc_insertion_point(field_get:Messages.AttestationMessage.reserved) + return reserved_.Get(index); +} + void AttestationMessage::set_reserved(int index, ::google::protobuf::uint32 value) { + reserved_.Set(index, value); + // @@protoc_insertion_point(field_set:Messages.AttestationMessage.reserved) +} + void AttestationMessage::add_reserved(::google::protobuf::uint32 value) { + reserved_.Add(value); + // @@protoc_insertion_point(field_add:Messages.AttestationMessage.reserved) +} + const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& +AttestationMessage::reserved() const { + // @@protoc_insertion_point(field_list:Messages.AttestationMessage.reserved) + return reserved_; +} + ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* +AttestationMessage::mutable_reserved() { + // @@protoc_insertion_point(field_mutable_list:Messages.AttestationMessage.reserved) + return &reserved_; +} - // repeated uint32 encrypted_x509_mac_smk = 10 [packed = true]; - case 10: { - if (tag == 82) { - parse_encrypted_x509_mac_smk: - DO_((::google::protobuf::internal::WireFormatLite::ReadPackedPrimitive< - ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>( - input, this->mutable_encrypted_x509_mac_smk()))); - } else if (tag == 80) { - DO_((::google::protobuf::internal::WireFormatLite::ReadRepeatedPrimitiveNoInline< - ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>( - 1, 82, input, this->mutable_encrypted_x509_mac_smk()))); - } else { - goto handle_unusual; - } - if (input->ExpectAtEnd()) goto success; - break; - } +// repeated uint32 payload_tag = 15 [packed = true]; +int AttestationMessage::payload_tag_size() const { + return payload_tag_.size(); +} +void AttestationMessage::clear_payload_tag() { + payload_tag_.Clear(); +} + ::google::protobuf::uint32 AttestationMessage::payload_tag(int index) const { + // @@protoc_insertion_point(field_get:Messages.AttestationMessage.payload_tag) + return payload_tag_.Get(index); +} + void AttestationMessage::set_payload_tag(int index, ::google::protobuf::uint32 value) { + payload_tag_.Set(index, value); + // @@protoc_insertion_point(field_set:Messages.AttestationMessage.payload_tag) +} + void AttestationMessage::add_payload_tag(::google::protobuf::uint32 value) { + payload_tag_.Add(value); + // @@protoc_insertion_point(field_add:Messages.AttestationMessage.payload_tag) +} + const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& +AttestationMessage::payload_tag() const { + // @@protoc_insertion_point(field_list:Messages.AttestationMessage.payload_tag) + return payload_tag_; +} + ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* +AttestationMessage::mutable_payload_tag() { + // @@protoc_insertion_point(field_mutable_list:Messages.AttestationMessage.payload_tag) + return &payload_tag_; +} - default: { - handle_unusual: - if (tag == 0 || - ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { - goto success; - } - DO_(::google::protobuf::internal::WireFormat::SkipField( - input, tag, mutable_unknown_fields())); - break; - } - } - } -success: - // @@protoc_insertion_point(parse_success:Messages.SecretMessage) - return true; -failure: - // @@protoc_insertion_point(parse_failure:Messages.SecretMessage) - return false; -#undef DO_ -} - -void SecretMessage::SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const { - // @@protoc_insertion_point(serialize_start:Messages.SecretMessage) - // required uint32 type = 1; - if (has_type()) { - ::google::protobuf::internal::WireFormatLite::WriteUInt32(1, this->type(), output); - } - - // required uint32 size = 2; - if (has_size()) { - ::google::protobuf::internal::WireFormatLite::WriteUInt32(2, this->size(), output); - } - - // optional uint32 encryped_pkey_size = 3; - if (has_encryped_pkey_size()) { - ::google::protobuf::internal::WireFormatLite::WriteUInt32(3, this->encryped_pkey_size(), output); - } - - // optional uint32 encryped_x509_size = 4; - if (has_encryped_x509_size()) { - ::google::protobuf::internal::WireFormatLite::WriteUInt32(4, this->encryped_x509_size(), output); - } - - // repeated uint32 encrypted_content = 5 [packed = true]; - if (this->encrypted_content_size() > 0) { - ::google::protobuf::internal::WireFormatLite::WriteTag(5, ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED, output); - output->WriteVarint32(_encrypted_content_cached_byte_size_); - } - for (int i = 0; i < this->encrypted_content_size(); i++) { - ::google::protobuf::internal::WireFormatLite::WriteUInt32NoTag( - this->encrypted_content(i), output); - } - - // repeated uint32 mac_smk = 6 [packed = true]; - if (this->mac_smk_size() > 0) { - ::google::protobuf::internal::WireFormatLite::WriteTag(6, ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED, output); - output->WriteVarint32(_mac_smk_cached_byte_size_); - } - for (int i = 0; i < this->mac_smk_size(); i++) { - ::google::protobuf::internal::WireFormatLite::WriteUInt32NoTag( - this->mac_smk(i), output); - } - - // repeated uint32 encrypted_pkey = 7 [packed = true]; - if (this->encrypted_pkey_size() > 0) { - ::google::protobuf::internal::WireFormatLite::WriteTag(7, ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED, output); - output->WriteVarint32(_encrypted_pkey_cached_byte_size_); - } - for (int i = 0; i < this->encrypted_pkey_size(); i++) { - ::google::protobuf::internal::WireFormatLite::WriteUInt32NoTag( - this->encrypted_pkey(i), output); - } - - // repeated uint32 encrypted_pkey_mac_smk = 8 [packed = true]; - if (this->encrypted_pkey_mac_smk_size() > 0) { - ::google::protobuf::internal::WireFormatLite::WriteTag(8, ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED, output); - output->WriteVarint32(_encrypted_pkey_mac_smk_cached_byte_size_); - } - for (int i = 0; i < this->encrypted_pkey_mac_smk_size(); i++) { - ::google::protobuf::internal::WireFormatLite::WriteUInt32NoTag( - this->encrypted_pkey_mac_smk(i), output); - } - - // repeated uint32 encrypted_x509 = 9 [packed = true]; - if (this->encrypted_x509_size() > 0) { - ::google::protobuf::internal::WireFormatLite::WriteTag(9, ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED, output); - output->WriteVarint32(_encrypted_x509_cached_byte_size_); - } - for (int i = 0; i < this->encrypted_x509_size(); i++) { - ::google::protobuf::internal::WireFormatLite::WriteUInt32NoTag( - this->encrypted_x509(i), output); - } - - // repeated uint32 encrypted_x509_mac_smk = 10 [packed = true]; - if (this->encrypted_x509_mac_smk_size() > 0) { - ::google::protobuf::internal::WireFormatLite::WriteTag(10, ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED, output); - output->WriteVarint32(_encrypted_x509_mac_smk_cached_byte_size_); - } - for (int i = 0; i < this->encrypted_x509_mac_smk_size(); i++) { - ::google::protobuf::internal::WireFormatLite::WriteUInt32NoTag( - this->encrypted_x509_mac_smk(i), output); - } - - if (!unknown_fields().empty()) { - ::google::protobuf::internal::WireFormat::SerializeUnknownFields( - unknown_fields(), output); - } - // @@protoc_insertion_point(serialize_end:Messages.SecretMessage) +// repeated uint32 payload = 16 [packed = true]; +int AttestationMessage::payload_size() const { + return payload_.size(); } - -::google::protobuf::uint8* SecretMessage::SerializeWithCachedSizesToArray( - ::google::protobuf::uint8* target) const { - // @@protoc_insertion_point(serialize_to_array_start:Messages.SecretMessage) - // required uint32 type = 1; - if (has_type()) { - target = ::google::protobuf::internal::WireFormatLite::WriteUInt32ToArray(1, this->type(), target); - } - - // required uint32 size = 2; - if (has_size()) { - target = ::google::protobuf::internal::WireFormatLite::WriteUInt32ToArray(2, this->size(), target); - } - - // optional uint32 encryped_pkey_size = 3; - if (has_encryped_pkey_size()) { - target = ::google::protobuf::internal::WireFormatLite::WriteUInt32ToArray(3, this->encryped_pkey_size(), target); - } - - // optional uint32 encryped_x509_size = 4; - if (has_encryped_x509_size()) { - target = ::google::protobuf::internal::WireFormatLite::WriteUInt32ToArray(4, this->encryped_x509_size(), target); - } - - // repeated uint32 encrypted_content = 5 [packed = true]; - if (this->encrypted_content_size() > 0) { - target = ::google::protobuf::internal::WireFormatLite::WriteTagToArray( - 5, - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED, - target); - target = ::google::protobuf::io::CodedOutputStream::WriteVarint32ToArray( - _encrypted_content_cached_byte_size_, target); - } - for (int i = 0; i < this->encrypted_content_size(); i++) { - target = ::google::protobuf::internal::WireFormatLite:: - WriteUInt32NoTagToArray(this->encrypted_content(i), target); - } - - // repeated uint32 mac_smk = 6 [packed = true]; - if (this->mac_smk_size() > 0) { - target = ::google::protobuf::internal::WireFormatLite::WriteTagToArray( - 6, - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED, - target); - target = ::google::protobuf::io::CodedOutputStream::WriteVarint32ToArray( - _mac_smk_cached_byte_size_, target); - } - for (int i = 0; i < this->mac_smk_size(); i++) { - target = ::google::protobuf::internal::WireFormatLite:: - WriteUInt32NoTagToArray(this->mac_smk(i), target); - } - - // repeated uint32 encrypted_pkey = 7 [packed = true]; - if (this->encrypted_pkey_size() > 0) { - target = ::google::protobuf::internal::WireFormatLite::WriteTagToArray( - 7, - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED, - target); - target = ::google::protobuf::io::CodedOutputStream::WriteVarint32ToArray( - _encrypted_pkey_cached_byte_size_, target); - } - for (int i = 0; i < this->encrypted_pkey_size(); i++) { - target = ::google::protobuf::internal::WireFormatLite:: - WriteUInt32NoTagToArray(this->encrypted_pkey(i), target); - } - - // repeated uint32 encrypted_pkey_mac_smk = 8 [packed = true]; - if (this->encrypted_pkey_mac_smk_size() > 0) { - target = ::google::protobuf::internal::WireFormatLite::WriteTagToArray( - 8, - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED, - target); - target = ::google::protobuf::io::CodedOutputStream::WriteVarint32ToArray( - _encrypted_pkey_mac_smk_cached_byte_size_, target); - } - for (int i = 0; i < this->encrypted_pkey_mac_smk_size(); i++) { - target = ::google::protobuf::internal::WireFormatLite:: - WriteUInt32NoTagToArray(this->encrypted_pkey_mac_smk(i), target); - } - - // repeated uint32 encrypted_x509 = 9 [packed = true]; - if (this->encrypted_x509_size() > 0) { - target = ::google::protobuf::internal::WireFormatLite::WriteTagToArray( - 9, - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED, - target); - target = ::google::protobuf::io::CodedOutputStream::WriteVarint32ToArray( - _encrypted_x509_cached_byte_size_, target); - } - for (int i = 0; i < this->encrypted_x509_size(); i++) { - target = ::google::protobuf::internal::WireFormatLite:: - WriteUInt32NoTagToArray(this->encrypted_x509(i), target); - } - - // repeated uint32 encrypted_x509_mac_smk = 10 [packed = true]; - if (this->encrypted_x509_mac_smk_size() > 0) { - target = ::google::protobuf::internal::WireFormatLite::WriteTagToArray( - 10, - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED, - target); - target = ::google::protobuf::io::CodedOutputStream::WriteVarint32ToArray( - _encrypted_x509_mac_smk_cached_byte_size_, target); - } - for (int i = 0; i < this->encrypted_x509_mac_smk_size(); i++) { - target = ::google::protobuf::internal::WireFormatLite:: - WriteUInt32NoTagToArray(this->encrypted_x509_mac_smk(i), target); - } - - if (!unknown_fields().empty()) { - target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( - unknown_fields(), target); - } - // @@protoc_insertion_point(serialize_to_array_end:Messages.SecretMessage) - return target; -} - -int SecretMessage::ByteSize() const { - int total_size = 0; - - if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { - // required uint32 type = 1; - if (has_type()) { - total_size += 1 + - ::google::protobuf::internal::WireFormatLite::UInt32Size( - this->type()); - } - - // required uint32 size = 2; - if (has_size()) { - total_size += 1 + - ::google::protobuf::internal::WireFormatLite::UInt32Size( - this->size()); - } - - // optional uint32 encryped_pkey_size = 3; - if (has_encryped_pkey_size()) { - total_size += 1 + - ::google::protobuf::internal::WireFormatLite::UInt32Size( - this->encryped_pkey_size()); - } - - // optional uint32 encryped_x509_size = 4; - if (has_encryped_x509_size()) { - total_size += 1 + - ::google::protobuf::internal::WireFormatLite::UInt32Size( - this->encryped_x509_size()); - } - - } - // repeated uint32 encrypted_content = 5 [packed = true]; - { - int data_size = 0; - for (int i = 0; i < this->encrypted_content_size(); i++) { - data_size += ::google::protobuf::internal::WireFormatLite:: - UInt32Size(this->encrypted_content(i)); - } - if (data_size > 0) { - total_size += 1 + - ::google::protobuf::internal::WireFormatLite::Int32Size(data_size); - } - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _encrypted_content_cached_byte_size_ = data_size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); - total_size += data_size; - } - - // repeated uint32 mac_smk = 6 [packed = true]; - { - int data_size = 0; - for (int i = 0; i < this->mac_smk_size(); i++) { - data_size += ::google::protobuf::internal::WireFormatLite:: - UInt32Size(this->mac_smk(i)); - } - if (data_size > 0) { - total_size += 1 + - ::google::protobuf::internal::WireFormatLite::Int32Size(data_size); - } - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _mac_smk_cached_byte_size_ = data_size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); - total_size += data_size; - } - - // repeated uint32 encrypted_pkey = 7 [packed = true]; - { - int data_size = 0; - for (int i = 0; i < this->encrypted_pkey_size(); i++) { - data_size += ::google::protobuf::internal::WireFormatLite:: - UInt32Size(this->encrypted_pkey(i)); - } - if (data_size > 0) { - total_size += 1 + - ::google::protobuf::internal::WireFormatLite::Int32Size(data_size); - } - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _encrypted_pkey_cached_byte_size_ = data_size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); - total_size += data_size; - } - - // repeated uint32 encrypted_pkey_mac_smk = 8 [packed = true]; - { - int data_size = 0; - for (int i = 0; i < this->encrypted_pkey_mac_smk_size(); i++) { - data_size += ::google::protobuf::internal::WireFormatLite:: - UInt32Size(this->encrypted_pkey_mac_smk(i)); - } - if (data_size > 0) { - total_size += 1 + - ::google::protobuf::internal::WireFormatLite::Int32Size(data_size); - } - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _encrypted_pkey_mac_smk_cached_byte_size_ = data_size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); - total_size += data_size; - } - - // repeated uint32 encrypted_x509 = 9 [packed = true]; - { - int data_size = 0; - for (int i = 0; i < this->encrypted_x509_size(); i++) { - data_size += ::google::protobuf::internal::WireFormatLite:: - UInt32Size(this->encrypted_x509(i)); - } - if (data_size > 0) { - total_size += 1 + - ::google::protobuf::internal::WireFormatLite::Int32Size(data_size); - } - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _encrypted_x509_cached_byte_size_ = data_size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); - total_size += data_size; - } - - // repeated uint32 encrypted_x509_mac_smk = 10 [packed = true]; - { - int data_size = 0; - for (int i = 0; i < this->encrypted_x509_mac_smk_size(); i++) { - data_size += ::google::protobuf::internal::WireFormatLite:: - UInt32Size(this->encrypted_x509_mac_smk(i)); - } - if (data_size > 0) { - total_size += 1 + - ::google::protobuf::internal::WireFormatLite::Int32Size(data_size); - } - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _encrypted_x509_mac_smk_cached_byte_size_ = data_size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); - total_size += data_size; - } - - if (!unknown_fields().empty()) { - total_size += - ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( - unknown_fields()); - } - GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); - _cached_size_ = total_size; - GOOGLE_SAFE_CONCURRENT_WRITES_END(); - return total_size; -} - -void SecretMessage::MergeFrom(const ::google::protobuf::Message& from) { - GOOGLE_CHECK_NE(&from, this); - const SecretMessage* source = - ::google::protobuf::internal::dynamic_cast_if_available( - &from); - if (source == NULL) { - ::google::protobuf::internal::ReflectionOps::Merge(from, this); - } else { - MergeFrom(*source); - } -} - -void SecretMessage::MergeFrom(const SecretMessage& from) { - GOOGLE_CHECK_NE(&from, this); - encrypted_content_.MergeFrom(from.encrypted_content_); - mac_smk_.MergeFrom(from.mac_smk_); - encrypted_pkey_.MergeFrom(from.encrypted_pkey_); - encrypted_pkey_mac_smk_.MergeFrom(from.encrypted_pkey_mac_smk_); - encrypted_x509_.MergeFrom(from.encrypted_x509_); - encrypted_x509_mac_smk_.MergeFrom(from.encrypted_x509_mac_smk_); - if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { - if (from.has_type()) { - set_type(from.type()); - } - if (from.has_size()) { - set_size(from.size()); - } - if (from.has_encryped_pkey_size()) { - set_encryped_pkey_size(from.encryped_pkey_size()); - } - if (from.has_encryped_x509_size()) { - set_encryped_x509_size(from.encryped_x509_size()); - } - } - mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +void AttestationMessage::clear_payload() { + payload_.Clear(); } - -void SecretMessage::CopyFrom(const ::google::protobuf::Message& from) { - if (&from == this) return; - Clear(); - MergeFrom(from); + ::google::protobuf::uint32 AttestationMessage::payload(int index) const { + // @@protoc_insertion_point(field_get:Messages.AttestationMessage.payload) + return payload_.Get(index); } - -void SecretMessage::CopyFrom(const SecretMessage& from) { - if (&from == this) return; - Clear(); - MergeFrom(from); + void AttestationMessage::set_payload(int index, ::google::protobuf::uint32 value) { + payload_.Set(index, value); + // @@protoc_insertion_point(field_set:Messages.AttestationMessage.payload) } - -bool SecretMessage::IsInitialized() const { - if ((_has_bits_[0] & 0x00000003) != 0x00000003) return false; - - return true; + void AttestationMessage::add_payload(::google::protobuf::uint32 value) { + payload_.Add(value); + // @@protoc_insertion_point(field_add:Messages.AttestationMessage.payload) } - -void SecretMessage::Swap(SecretMessage* other) { - if (other != this) { - std::swap(type_, other->type_); - std::swap(size_, other->size_); - std::swap(encryped_pkey_size_, other->encryped_pkey_size_); - std::swap(encryped_x509_size_, other->encryped_x509_size_); - encrypted_content_.Swap(&other->encrypted_content_); - mac_smk_.Swap(&other->mac_smk_); - encrypted_pkey_.Swap(&other->encrypted_pkey_); - encrypted_pkey_mac_smk_.Swap(&other->encrypted_pkey_mac_smk_); - encrypted_x509_.Swap(&other->encrypted_x509_); - encrypted_x509_mac_smk_.Swap(&other->encrypted_x509_mac_smk_); - std::swap(_has_bits_[0], other->_has_bits_[0]); - _unknown_fields_.Swap(&other->_unknown_fields_); - std::swap(_cached_size_, other->_cached_size_); - } + const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& +AttestationMessage::payload() const { + // @@protoc_insertion_point(field_list:Messages.AttestationMessage.payload) + return payload_; } - -::google::protobuf::Metadata SecretMessage::GetMetadata() const { - protobuf_AssignDescriptorsOnce(); - ::google::protobuf::Metadata metadata; - metadata.descriptor = SecretMessage_descriptor_; - metadata.reflection = SecretMessage_reflection_; - return metadata; + ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* +AttestationMessage::mutable_payload() { + // @@protoc_insertion_point(field_mutable_list:Messages.AttestationMessage.payload) + return &payload_; } +#endif // PROTOBUF_INLINE_NOT_IN_HEADERS // @@protoc_insertion_point(namespace_scope) diff --git a/samplecode/remoteattestation/GoogleMessages/Messages.pb.h b/samplecode/remoteattestation/GoogleMessages/Messages.pb.h index 8c2e78fba..3acdf981d 100644 --- a/samplecode/remoteattestation/GoogleMessages/Messages.pb.h +++ b/samplecode/remoteattestation/GoogleMessages/Messages.pb.h @@ -8,18 +8,21 @@ #include -#if GOOGLE_PROTOBUF_VERSION < 2006000 +#if GOOGLE_PROTOBUF_VERSION < 3000000 #error This file was generated by a newer version of protoc which is #error incompatible with your Protocol Buffer headers. Please update #error your headers. #endif -#if 2006001 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION +#if 3000000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION #error This file was generated by an older version of protoc which is #error incompatible with your Protocol Buffer headers. Please #error regenerate this file with a newer version of protoc. #endif +#include +#include #include +#include #include #include #include @@ -29,21 +32,20 @@ namespace Messages { // Internal implementation detail -- do not call these. -void protobuf_AddDesc_Messages_2eproto(); +void protobuf_AddDesc_Messages_2eproto(); void protobuf_AssignDesc_Messages_2eproto(); void protobuf_ShutdownFile_Messages_2eproto(); +class AttestationMessage; class InitialMessage; -class MessageMsg0; class MessageMSG1; class MessageMSG2; class MessageMSG3; -class AttestationMessage; -class SecretMessage; +class MessageMsg0; // =================================================================== -class InitialMessage : public ::google::protobuf::Message { +class InitialMessage : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:Messages.InitialMessage) */ { public: InitialMessage(); virtual ~InitialMessage(); @@ -56,11 +58,11 @@ class InitialMessage : public ::google::protobuf::Message { } inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { - return _unknown_fields_; + return _internal_metadata_.unknown_fields(); } inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { - return &_unknown_fields_; + return _internal_metadata_.mutable_unknown_fields(); } static const ::google::protobuf::Descriptor* descriptor(); @@ -70,7 +72,9 @@ class InitialMessage : public ::google::protobuf::Message { // implements Message ---------------------------------------------- - InitialMessage* New() const; + inline InitialMessage* New() const { return New(NULL); } + + InitialMessage* New(::google::protobuf::Arena* arena) const; void CopyFrom(const ::google::protobuf::Message& from); void MergeFrom(const ::google::protobuf::Message& from); void CopyFrom(const InitialMessage& from); @@ -83,13 +87,26 @@ class InitialMessage : public ::google::protobuf::Message { ::google::protobuf::io::CodedInputStream* input); void SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const; - ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray( + bool deterministic, ::google::protobuf::uint8* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const { + return InternalSerializeWithCachedSizesToArray(false, output); + } int GetCachedSize() const { return _cached_size_; } private: void SharedCtor(); void SharedDtor(); void SetCachedSize(int size) const; + void InternalSwap(InitialMessage* other); + private: + inline ::google::protobuf::Arena* GetArenaNoVirtual() const { + return _internal_metadata_.arena(); + } + inline void* MaybeArenaPtr() const { + return _internal_metadata_.raw_arena_ptr(); + } public: + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -97,18 +114,18 @@ class InitialMessage : public ::google::protobuf::Message { // accessors ------------------------------------------------------- // required uint32 type = 1; - inline bool has_type() const; - inline void clear_type(); + bool has_type() const; + void clear_type(); static const int kTypeFieldNumber = 1; - inline ::google::protobuf::uint32 type() const; - inline void set_type(::google::protobuf::uint32 value); + ::google::protobuf::uint32 type() const; + void set_type(::google::protobuf::uint32 value); // optional uint32 size = 2; - inline bool has_size() const; - inline void clear_size(); + bool has_size() const; + void clear_size(); static const int kSizeFieldNumber = 2; - inline ::google::protobuf::uint32 size() const; - inline void set_size(::google::protobuf::uint32 value); + ::google::protobuf::uint32 size() const; + void set_size(::google::protobuf::uint32 value); // @@protoc_insertion_point(class_scope:Messages.InitialMessage) private: @@ -117,8 +134,7 @@ class InitialMessage : public ::google::protobuf::Message { inline void set_has_size(); inline void clear_has_size(); - ::google::protobuf::UnknownFieldSet _unknown_fields_; - + ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; ::google::protobuf::uint32 _has_bits_[1]; mutable int _cached_size_; ::google::protobuf::uint32 type_; @@ -132,7 +148,7 @@ class InitialMessage : public ::google::protobuf::Message { }; // ------------------------------------------------------------------- -class MessageMsg0 : public ::google::protobuf::Message { +class MessageMsg0 : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:Messages.MessageMsg0) */ { public: MessageMsg0(); virtual ~MessageMsg0(); @@ -145,11 +161,11 @@ class MessageMsg0 : public ::google::protobuf::Message { } inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { - return _unknown_fields_; + return _internal_metadata_.unknown_fields(); } inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { - return &_unknown_fields_; + return _internal_metadata_.mutable_unknown_fields(); } static const ::google::protobuf::Descriptor* descriptor(); @@ -159,7 +175,9 @@ class MessageMsg0 : public ::google::protobuf::Message { // implements Message ---------------------------------------------- - MessageMsg0* New() const; + inline MessageMsg0* New() const { return New(NULL); } + + MessageMsg0* New(::google::protobuf::Arena* arena) const; void CopyFrom(const ::google::protobuf::Message& from); void MergeFrom(const ::google::protobuf::Message& from); void CopyFrom(const MessageMsg0& from); @@ -172,13 +190,26 @@ class MessageMsg0 : public ::google::protobuf::Message { ::google::protobuf::io::CodedInputStream* input); void SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const; - ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray( + bool deterministic, ::google::protobuf::uint8* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const { + return InternalSerializeWithCachedSizesToArray(false, output); + } int GetCachedSize() const { return _cached_size_; } private: void SharedCtor(); void SharedDtor(); void SetCachedSize(int size) const; + void InternalSwap(MessageMsg0* other); + private: + inline ::google::protobuf::Arena* GetArenaNoVirtual() const { + return _internal_metadata_.arena(); + } + inline void* MaybeArenaPtr() const { + return _internal_metadata_.raw_arena_ptr(); + } public: + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -186,25 +217,25 @@ class MessageMsg0 : public ::google::protobuf::Message { // accessors ------------------------------------------------------- // required uint32 type = 1; - inline bool has_type() const; - inline void clear_type(); + bool has_type() const; + void clear_type(); static const int kTypeFieldNumber = 1; - inline ::google::protobuf::uint32 type() const; - inline void set_type(::google::protobuf::uint32 value); + ::google::protobuf::uint32 type() const; + void set_type(::google::protobuf::uint32 value); // required uint32 epid = 2; - inline bool has_epid() const; - inline void clear_epid(); + bool has_epid() const; + void clear_epid(); static const int kEpidFieldNumber = 2; - inline ::google::protobuf::uint32 epid() const; - inline void set_epid(::google::protobuf::uint32 value); + ::google::protobuf::uint32 epid() const; + void set_epid(::google::protobuf::uint32 value); // optional uint32 status = 3; - inline bool has_status() const; - inline void clear_status(); + bool has_status() const; + void clear_status(); static const int kStatusFieldNumber = 3; - inline ::google::protobuf::uint32 status() const; - inline void set_status(::google::protobuf::uint32 value); + ::google::protobuf::uint32 status() const; + void set_status(::google::protobuf::uint32 value); // @@protoc_insertion_point(class_scope:Messages.MessageMsg0) private: @@ -215,8 +246,10 @@ class MessageMsg0 : public ::google::protobuf::Message { inline void set_has_status(); inline void clear_has_status(); - ::google::protobuf::UnknownFieldSet _unknown_fields_; + // helper for ByteSize() + int RequiredFieldsByteSizeFallback() const; + ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; ::google::protobuf::uint32 _has_bits_[1]; mutable int _cached_size_; ::google::protobuf::uint32 type_; @@ -231,7 +264,7 @@ class MessageMsg0 : public ::google::protobuf::Message { }; // ------------------------------------------------------------------- -class MessageMSG1 : public ::google::protobuf::Message { +class MessageMSG1 : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:Messages.MessageMSG1) */ { public: MessageMSG1(); virtual ~MessageMSG1(); @@ -244,11 +277,11 @@ class MessageMSG1 : public ::google::protobuf::Message { } inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { - return _unknown_fields_; + return _internal_metadata_.unknown_fields(); } inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { - return &_unknown_fields_; + return _internal_metadata_.mutable_unknown_fields(); } static const ::google::protobuf::Descriptor* descriptor(); @@ -258,7 +291,9 @@ class MessageMSG1 : public ::google::protobuf::Message { // implements Message ---------------------------------------------- - MessageMSG1* New() const; + inline MessageMSG1* New() const { return New(NULL); } + + MessageMSG1* New(::google::protobuf::Arena* arena) const; void CopyFrom(const ::google::protobuf::Message& from); void MergeFrom(const ::google::protobuf::Message& from); void CopyFrom(const MessageMSG1& from); @@ -271,13 +306,26 @@ class MessageMSG1 : public ::google::protobuf::Message { ::google::protobuf::io::CodedInputStream* input); void SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const; - ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray( + bool deterministic, ::google::protobuf::uint8* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const { + return InternalSerializeWithCachedSizesToArray(false, output); + } int GetCachedSize() const { return _cached_size_; } private: void SharedCtor(); void SharedDtor(); void SetCachedSize(int size) const; + void InternalSwap(MessageMSG1* other); + private: + inline ::google::protobuf::Arena* GetArenaNoVirtual() const { + return _internal_metadata_.arena(); + } + inline void* MaybeArenaPtr() const { + return _internal_metadata_.raw_arena_ptr(); + } public: + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -285,46 +333,46 @@ class MessageMSG1 : public ::google::protobuf::Message { // accessors ------------------------------------------------------- // required uint32 type = 1; - inline bool has_type() const; - inline void clear_type(); + bool has_type() const; + void clear_type(); static const int kTypeFieldNumber = 1; - inline ::google::protobuf::uint32 type() const; - inline void set_type(::google::protobuf::uint32 value); + ::google::protobuf::uint32 type() const; + void set_type(::google::protobuf::uint32 value); // repeated uint32 GaX = 2 [packed = true]; - inline int gax_size() const; - inline void clear_gax(); + int gax_size() const; + void clear_gax(); static const int kGaXFieldNumber = 2; - inline ::google::protobuf::uint32 gax(int index) const; - inline void set_gax(int index, ::google::protobuf::uint32 value); - inline void add_gax(::google::protobuf::uint32 value); - inline const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& + ::google::protobuf::uint32 gax(int index) const; + void set_gax(int index, ::google::protobuf::uint32 value); + void add_gax(::google::protobuf::uint32 value); + const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& gax() const; - inline ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* + ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* mutable_gax(); // repeated uint32 GaY = 3 [packed = true]; - inline int gay_size() const; - inline void clear_gay(); + int gay_size() const; + void clear_gay(); static const int kGaYFieldNumber = 3; - inline ::google::protobuf::uint32 gay(int index) const; - inline void set_gay(int index, ::google::protobuf::uint32 value); - inline void add_gay(::google::protobuf::uint32 value); - inline const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& + ::google::protobuf::uint32 gay(int index) const; + void set_gay(int index, ::google::protobuf::uint32 value); + void add_gay(::google::protobuf::uint32 value); + const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& gay() const; - inline ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* + ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* mutable_gay(); // repeated uint32 GID = 4 [packed = true]; - inline int gid_size() const; - inline void clear_gid(); + int gid_size() const; + void clear_gid(); static const int kGIDFieldNumber = 4; - inline ::google::protobuf::uint32 gid(int index) const; - inline void set_gid(int index, ::google::protobuf::uint32 value); - inline void add_gid(::google::protobuf::uint32 value); - inline const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& + ::google::protobuf::uint32 gid(int index) const; + void set_gid(int index, ::google::protobuf::uint32 value); + void add_gid(::google::protobuf::uint32 value); + const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& gid() const; - inline ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* + ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* mutable_gid(); // @@protoc_insertion_point(class_scope:Messages.MessageMSG1) @@ -332,8 +380,7 @@ class MessageMSG1 : public ::google::protobuf::Message { inline void set_has_type(); inline void clear_has_type(); - ::google::protobuf::UnknownFieldSet _unknown_fields_; - + ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; ::google::protobuf::uint32 _has_bits_[1]; mutable int _cached_size_; ::google::protobuf::RepeatedField< ::google::protobuf::uint32 > gax_; @@ -352,7 +399,7 @@ class MessageMSG1 : public ::google::protobuf::Message { }; // ------------------------------------------------------------------- -class MessageMSG2 : public ::google::protobuf::Message { +class MessageMSG2 : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:Messages.MessageMSG2) */ { public: MessageMSG2(); virtual ~MessageMSG2(); @@ -365,11 +412,11 @@ class MessageMSG2 : public ::google::protobuf::Message { } inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { - return _unknown_fields_; + return _internal_metadata_.unknown_fields(); } inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { - return &_unknown_fields_; + return _internal_metadata_.mutable_unknown_fields(); } static const ::google::protobuf::Descriptor* descriptor(); @@ -379,7 +426,9 @@ class MessageMSG2 : public ::google::protobuf::Message { // implements Message ---------------------------------------------- - MessageMSG2* New() const; + inline MessageMSG2* New() const { return New(NULL); } + + MessageMSG2* New(::google::protobuf::Arena* arena) const; void CopyFrom(const ::google::protobuf::Message& from); void MergeFrom(const ::google::protobuf::Message& from); void CopyFrom(const MessageMSG2& from); @@ -392,13 +441,26 @@ class MessageMSG2 : public ::google::protobuf::Message { ::google::protobuf::io::CodedInputStream* input); void SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const; - ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray( + bool deterministic, ::google::protobuf::uint8* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const { + return InternalSerializeWithCachedSizesToArray(false, output); + } int GetCachedSize() const { return _cached_size_; } private: void SharedCtor(); void SharedDtor(); void SetCachedSize(int size) const; + void InternalSwap(MessageMSG2* other); + private: + inline ::google::protobuf::Arena* GetArenaNoVirtual() const { + return _internal_metadata_.arena(); + } + inline void* MaybeArenaPtr() const { + return _internal_metadata_.raw_arena_ptr(); + } public: + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -406,122 +468,122 @@ class MessageMSG2 : public ::google::protobuf::Message { // accessors ------------------------------------------------------- // required uint32 type = 1; - inline bool has_type() const; - inline void clear_type(); + bool has_type() const; + void clear_type(); static const int kTypeFieldNumber = 1; - inline ::google::protobuf::uint32 type() const; - inline void set_type(::google::protobuf::uint32 value); + ::google::protobuf::uint32 type() const; + void set_type(::google::protobuf::uint32 value); // optional uint32 size = 2; - inline bool has_size() const; - inline void clear_size(); + bool has_size() const; + void clear_size(); static const int kSizeFieldNumber = 2; - inline ::google::protobuf::uint32 size() const; - inline void set_size(::google::protobuf::uint32 value); + ::google::protobuf::uint32 size() const; + void set_size(::google::protobuf::uint32 value); // repeated uint32 public_key_gx = 3 [packed = true]; - inline int public_key_gx_size() const; - inline void clear_public_key_gx(); + int public_key_gx_size() const; + void clear_public_key_gx(); static const int kPublicKeyGxFieldNumber = 3; - inline ::google::protobuf::uint32 public_key_gx(int index) const; - inline void set_public_key_gx(int index, ::google::protobuf::uint32 value); - inline void add_public_key_gx(::google::protobuf::uint32 value); - inline const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& + ::google::protobuf::uint32 public_key_gx(int index) const; + void set_public_key_gx(int index, ::google::protobuf::uint32 value); + void add_public_key_gx(::google::protobuf::uint32 value); + const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& public_key_gx() const; - inline ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* + ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* mutable_public_key_gx(); // repeated uint32 public_key_gy = 4 [packed = true]; - inline int public_key_gy_size() const; - inline void clear_public_key_gy(); + int public_key_gy_size() const; + void clear_public_key_gy(); static const int kPublicKeyGyFieldNumber = 4; - inline ::google::protobuf::uint32 public_key_gy(int index) const; - inline void set_public_key_gy(int index, ::google::protobuf::uint32 value); - inline void add_public_key_gy(::google::protobuf::uint32 value); - inline const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& + ::google::protobuf::uint32 public_key_gy(int index) const; + void set_public_key_gy(int index, ::google::protobuf::uint32 value); + void add_public_key_gy(::google::protobuf::uint32 value); + const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& public_key_gy() const; - inline ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* + ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* mutable_public_key_gy(); // optional uint32 quote_type = 5; - inline bool has_quote_type() const; - inline void clear_quote_type(); + bool has_quote_type() const; + void clear_quote_type(); static const int kQuoteTypeFieldNumber = 5; - inline ::google::protobuf::uint32 quote_type() const; - inline void set_quote_type(::google::protobuf::uint32 value); + ::google::protobuf::uint32 quote_type() const; + void set_quote_type(::google::protobuf::uint32 value); // repeated uint32 spid = 6 [packed = true]; - inline int spid_size() const; - inline void clear_spid(); + int spid_size() const; + void clear_spid(); static const int kSpidFieldNumber = 6; - inline ::google::protobuf::uint32 spid(int index) const; - inline void set_spid(int index, ::google::protobuf::uint32 value); - inline void add_spid(::google::protobuf::uint32 value); - inline const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& + ::google::protobuf::uint32 spid(int index) const; + void set_spid(int index, ::google::protobuf::uint32 value); + void add_spid(::google::protobuf::uint32 value); + const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& spid() const; - inline ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* + ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* mutable_spid(); // optional uint32 cmac_kdf_id = 7; - inline bool has_cmac_kdf_id() const; - inline void clear_cmac_kdf_id(); + bool has_cmac_kdf_id() const; + void clear_cmac_kdf_id(); static const int kCmacKdfIdFieldNumber = 7; - inline ::google::protobuf::uint32 cmac_kdf_id() const; - inline void set_cmac_kdf_id(::google::protobuf::uint32 value); + ::google::protobuf::uint32 cmac_kdf_id() const; + void set_cmac_kdf_id(::google::protobuf::uint32 value); // repeated uint32 signature_x = 8 [packed = true]; - inline int signature_x_size() const; - inline void clear_signature_x(); + int signature_x_size() const; + void clear_signature_x(); static const int kSignatureXFieldNumber = 8; - inline ::google::protobuf::uint32 signature_x(int index) const; - inline void set_signature_x(int index, ::google::protobuf::uint32 value); - inline void add_signature_x(::google::protobuf::uint32 value); - inline const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& + ::google::protobuf::uint32 signature_x(int index) const; + void set_signature_x(int index, ::google::protobuf::uint32 value); + void add_signature_x(::google::protobuf::uint32 value); + const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& signature_x() const; - inline ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* + ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* mutable_signature_x(); // repeated uint32 signature_y = 9 [packed = true]; - inline int signature_y_size() const; - inline void clear_signature_y(); + int signature_y_size() const; + void clear_signature_y(); static const int kSignatureYFieldNumber = 9; - inline ::google::protobuf::uint32 signature_y(int index) const; - inline void set_signature_y(int index, ::google::protobuf::uint32 value); - inline void add_signature_y(::google::protobuf::uint32 value); - inline const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& + ::google::protobuf::uint32 signature_y(int index) const; + void set_signature_y(int index, ::google::protobuf::uint32 value); + void add_signature_y(::google::protobuf::uint32 value); + const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& signature_y() const; - inline ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* + ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* mutable_signature_y(); // repeated uint32 smac = 10 [packed = true]; - inline int smac_size() const; - inline void clear_smac(); + int smac_size() const; + void clear_smac(); static const int kSmacFieldNumber = 10; - inline ::google::protobuf::uint32 smac(int index) const; - inline void set_smac(int index, ::google::protobuf::uint32 value); - inline void add_smac(::google::protobuf::uint32 value); - inline const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& + ::google::protobuf::uint32 smac(int index) const; + void set_smac(int index, ::google::protobuf::uint32 value); + void add_smac(::google::protobuf::uint32 value); + const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& smac() const; - inline ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* + ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* mutable_smac(); // optional uint32 size_sigrl = 11; - inline bool has_size_sigrl() const; - inline void clear_size_sigrl(); + bool has_size_sigrl() const; + void clear_size_sigrl(); static const int kSizeSigrlFieldNumber = 11; - inline ::google::protobuf::uint32 size_sigrl() const; - inline void set_size_sigrl(::google::protobuf::uint32 value); + ::google::protobuf::uint32 size_sigrl() const; + void set_size_sigrl(::google::protobuf::uint32 value); // repeated uint32 sigrl = 12 [packed = true]; - inline int sigrl_size() const; - inline void clear_sigrl(); + int sigrl_size() const; + void clear_sigrl(); static const int kSigrlFieldNumber = 12; - inline ::google::protobuf::uint32 sigrl(int index) const; - inline void set_sigrl(int index, ::google::protobuf::uint32 value); - inline void add_sigrl(::google::protobuf::uint32 value); - inline const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& + ::google::protobuf::uint32 sigrl(int index) const; + void set_sigrl(int index, ::google::protobuf::uint32 value); + void add_sigrl(::google::protobuf::uint32 value); + const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& sigrl() const; - inline ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* + ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* mutable_sigrl(); // @@protoc_insertion_point(class_scope:Messages.MessageMSG2) @@ -537,8 +599,7 @@ class MessageMSG2 : public ::google::protobuf::Message { inline void set_has_size_sigrl(); inline void clear_has_size_sigrl(); - ::google::protobuf::UnknownFieldSet _unknown_fields_; - + ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; ::google::protobuf::uint32 _has_bits_[1]; mutable int _cached_size_; ::google::protobuf::uint32 type_; @@ -569,7 +630,7 @@ class MessageMSG2 : public ::google::protobuf::Message { }; // ------------------------------------------------------------------- -class MessageMSG3 : public ::google::protobuf::Message { +class MessageMSG3 : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:Messages.MessageMSG3) */ { public: MessageMSG3(); virtual ~MessageMSG3(); @@ -582,11 +643,11 @@ class MessageMSG3 : public ::google::protobuf::Message { } inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { - return _unknown_fields_; + return _internal_metadata_.unknown_fields(); } inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { - return &_unknown_fields_; + return _internal_metadata_.mutable_unknown_fields(); } static const ::google::protobuf::Descriptor* descriptor(); @@ -596,7 +657,9 @@ class MessageMSG3 : public ::google::protobuf::Message { // implements Message ---------------------------------------------- - MessageMSG3* New() const; + inline MessageMSG3* New() const { return New(NULL); } + + MessageMSG3* New(::google::protobuf::Arena* arena) const; void CopyFrom(const ::google::protobuf::Message& from); void MergeFrom(const ::google::protobuf::Message& from); void CopyFrom(const MessageMSG3& from); @@ -609,13 +672,26 @@ class MessageMSG3 : public ::google::protobuf::Message { ::google::protobuf::io::CodedInputStream* input); void SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const; - ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray( + bool deterministic, ::google::protobuf::uint8* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const { + return InternalSerializeWithCachedSizesToArray(false, output); + } int GetCachedSize() const { return _cached_size_; } private: void SharedCtor(); void SharedDtor(); void SetCachedSize(int size) const; + void InternalSwap(MessageMSG3* other); + private: + inline ::google::protobuf::Arena* GetArenaNoVirtual() const { + return _internal_metadata_.arena(); + } + inline void* MaybeArenaPtr() const { + return _internal_metadata_.raw_arena_ptr(); + } public: + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -623,77 +699,77 @@ class MessageMSG3 : public ::google::protobuf::Message { // accessors ------------------------------------------------------- // required uint32 type = 1; - inline bool has_type() const; - inline void clear_type(); + bool has_type() const; + void clear_type(); static const int kTypeFieldNumber = 1; - inline ::google::protobuf::uint32 type() const; - inline void set_type(::google::protobuf::uint32 value); + ::google::protobuf::uint32 type() const; + void set_type(::google::protobuf::uint32 value); // optional uint32 size = 2; - inline bool has_size() const; - inline void clear_size(); + bool has_size() const; + void clear_size(); static const int kSizeFieldNumber = 2; - inline ::google::protobuf::uint32 size() const; - inline void set_size(::google::protobuf::uint32 value); + ::google::protobuf::uint32 size() const; + void set_size(::google::protobuf::uint32 value); // repeated uint32 sgx_mac = 3 [packed = true]; - inline int sgx_mac_size() const; - inline void clear_sgx_mac(); + int sgx_mac_size() const; + void clear_sgx_mac(); static const int kSgxMacFieldNumber = 3; - inline ::google::protobuf::uint32 sgx_mac(int index) const; - inline void set_sgx_mac(int index, ::google::protobuf::uint32 value); - inline void add_sgx_mac(::google::protobuf::uint32 value); - inline const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& + ::google::protobuf::uint32 sgx_mac(int index) const; + void set_sgx_mac(int index, ::google::protobuf::uint32 value); + void add_sgx_mac(::google::protobuf::uint32 value); + const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& sgx_mac() const; - inline ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* + ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* mutable_sgx_mac(); // repeated uint32 gax_msg3 = 4 [packed = true]; - inline int gax_msg3_size() const; - inline void clear_gax_msg3(); + int gax_msg3_size() const; + void clear_gax_msg3(); static const int kGaxMsg3FieldNumber = 4; - inline ::google::protobuf::uint32 gax_msg3(int index) const; - inline void set_gax_msg3(int index, ::google::protobuf::uint32 value); - inline void add_gax_msg3(::google::protobuf::uint32 value); - inline const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& + ::google::protobuf::uint32 gax_msg3(int index) const; + void set_gax_msg3(int index, ::google::protobuf::uint32 value); + void add_gax_msg3(::google::protobuf::uint32 value); + const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& gax_msg3() const; - inline ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* + ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* mutable_gax_msg3(); // repeated uint32 gay_msg3 = 5 [packed = true]; - inline int gay_msg3_size() const; - inline void clear_gay_msg3(); + int gay_msg3_size() const; + void clear_gay_msg3(); static const int kGayMsg3FieldNumber = 5; - inline ::google::protobuf::uint32 gay_msg3(int index) const; - inline void set_gay_msg3(int index, ::google::protobuf::uint32 value); - inline void add_gay_msg3(::google::protobuf::uint32 value); - inline const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& + ::google::protobuf::uint32 gay_msg3(int index) const; + void set_gay_msg3(int index, ::google::protobuf::uint32 value); + void add_gay_msg3(::google::protobuf::uint32 value); + const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& gay_msg3() const; - inline ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* + ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* mutable_gay_msg3(); // repeated uint32 sec_property = 6 [packed = true]; - inline int sec_property_size() const; - inline void clear_sec_property(); + int sec_property_size() const; + void clear_sec_property(); static const int kSecPropertyFieldNumber = 6; - inline ::google::protobuf::uint32 sec_property(int index) const; - inline void set_sec_property(int index, ::google::protobuf::uint32 value); - inline void add_sec_property(::google::protobuf::uint32 value); - inline const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& + ::google::protobuf::uint32 sec_property(int index) const; + void set_sec_property(int index, ::google::protobuf::uint32 value); + void add_sec_property(::google::protobuf::uint32 value); + const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& sec_property() const; - inline ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* + ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* mutable_sec_property(); // repeated uint32 quote = 7 [packed = true]; - inline int quote_size() const; - inline void clear_quote(); + int quote_size() const; + void clear_quote(); static const int kQuoteFieldNumber = 7; - inline ::google::protobuf::uint32 quote(int index) const; - inline void set_quote(int index, ::google::protobuf::uint32 value); - inline void add_quote(::google::protobuf::uint32 value); - inline const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& + ::google::protobuf::uint32 quote(int index) const; + void set_quote(int index, ::google::protobuf::uint32 value); + void add_quote(::google::protobuf::uint32 value); + const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& quote() const; - inline ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* + ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* mutable_quote(); // @@protoc_insertion_point(class_scope:Messages.MessageMSG3) @@ -703,8 +779,7 @@ class MessageMSG3 : public ::google::protobuf::Message { inline void set_has_size(); inline void clear_has_size(); - ::google::protobuf::UnknownFieldSet _unknown_fields_; - + ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; ::google::protobuf::uint32 _has_bits_[1]; mutable int _cached_size_; ::google::protobuf::uint32 type_; @@ -728,7 +803,7 @@ class MessageMSG3 : public ::google::protobuf::Message { }; // ------------------------------------------------------------------- -class AttestationMessage : public ::google::protobuf::Message { +class AttestationMessage : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:Messages.AttestationMessage) */ { public: AttestationMessage(); virtual ~AttestationMessage(); @@ -741,11 +816,11 @@ class AttestationMessage : public ::google::protobuf::Message { } inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { - return _unknown_fields_; + return _internal_metadata_.unknown_fields(); } inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { - return &_unknown_fields_; + return _internal_metadata_.mutable_unknown_fields(); } static const ::google::protobuf::Descriptor* descriptor(); @@ -755,7 +830,9 @@ class AttestationMessage : public ::google::protobuf::Message { // implements Message ---------------------------------------------- - AttestationMessage* New() const; + inline AttestationMessage* New() const { return New(NULL); } + + AttestationMessage* New(::google::protobuf::Arena* arena) const; void CopyFrom(const ::google::protobuf::Message& from); void MergeFrom(const ::google::protobuf::Message& from); void CopyFrom(const AttestationMessage& from); @@ -768,13 +845,26 @@ class AttestationMessage : public ::google::protobuf::Message { ::google::protobuf::io::CodedInputStream* input); void SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const; - ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray( + bool deterministic, ::google::protobuf::uint8* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const { + return InternalSerializeWithCachedSizesToArray(false, output); + } int GetCachedSize() const { return _cached_size_; } private: void SharedCtor(); void SharedDtor(); void SetCachedSize(int size) const; + void InternalSwap(AttestationMessage* other); + private: + inline ::google::protobuf::Arena* GetArenaNoVirtual() const { + return _internal_metadata_.arena(); + } + inline void* MaybeArenaPtr() const { + return _internal_metadata_.raw_arena_ptr(); + } public: + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -782,165 +872,165 @@ class AttestationMessage : public ::google::protobuf::Message { // accessors ------------------------------------------------------- // required uint32 type = 1; - inline bool has_type() const; - inline void clear_type(); + bool has_type() const; + void clear_type(); static const int kTypeFieldNumber = 1; - inline ::google::protobuf::uint32 type() const; - inline void set_type(::google::protobuf::uint32 value); + ::google::protobuf::uint32 type() const; + void set_type(::google::protobuf::uint32 value); // required uint32 size = 2; - inline bool has_size() const; - inline void clear_size(); + bool has_size() const; + void clear_size(); static const int kSizeFieldNumber = 2; - inline ::google::protobuf::uint32 size() const; - inline void set_size(::google::protobuf::uint32 value); + ::google::protobuf::uint32 size() const; + void set_size(::google::protobuf::uint32 value); // optional uint32 epid_group_status = 3; - inline bool has_epid_group_status() const; - inline void clear_epid_group_status(); + bool has_epid_group_status() const; + void clear_epid_group_status(); static const int kEpidGroupStatusFieldNumber = 3; - inline ::google::protobuf::uint32 epid_group_status() const; - inline void set_epid_group_status(::google::protobuf::uint32 value); + ::google::protobuf::uint32 epid_group_status() const; + void set_epid_group_status(::google::protobuf::uint32 value); // optional uint32 tcb_evaluation_status = 4; - inline bool has_tcb_evaluation_status() const; - inline void clear_tcb_evaluation_status(); + bool has_tcb_evaluation_status() const; + void clear_tcb_evaluation_status(); static const int kTcbEvaluationStatusFieldNumber = 4; - inline ::google::protobuf::uint32 tcb_evaluation_status() const; - inline void set_tcb_evaluation_status(::google::protobuf::uint32 value); + ::google::protobuf::uint32 tcb_evaluation_status() const; + void set_tcb_evaluation_status(::google::protobuf::uint32 value); // optional uint32 pse_evaluation_status = 5; - inline bool has_pse_evaluation_status() const; - inline void clear_pse_evaluation_status(); + bool has_pse_evaluation_status() const; + void clear_pse_evaluation_status(); static const int kPseEvaluationStatusFieldNumber = 5; - inline ::google::protobuf::uint32 pse_evaluation_status() const; - inline void set_pse_evaluation_status(::google::protobuf::uint32 value); + ::google::protobuf::uint32 pse_evaluation_status() const; + void set_pse_evaluation_status(::google::protobuf::uint32 value); // repeated uint32 latest_equivalent_tcb_psvn = 6 [packed = true]; - inline int latest_equivalent_tcb_psvn_size() const; - inline void clear_latest_equivalent_tcb_psvn(); + int latest_equivalent_tcb_psvn_size() const; + void clear_latest_equivalent_tcb_psvn(); static const int kLatestEquivalentTcbPsvnFieldNumber = 6; - inline ::google::protobuf::uint32 latest_equivalent_tcb_psvn(int index) const; - inline void set_latest_equivalent_tcb_psvn(int index, ::google::protobuf::uint32 value); - inline void add_latest_equivalent_tcb_psvn(::google::protobuf::uint32 value); - inline const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& + ::google::protobuf::uint32 latest_equivalent_tcb_psvn(int index) const; + void set_latest_equivalent_tcb_psvn(int index, ::google::protobuf::uint32 value); + void add_latest_equivalent_tcb_psvn(::google::protobuf::uint32 value); + const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& latest_equivalent_tcb_psvn() const; - inline ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* + ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* mutable_latest_equivalent_tcb_psvn(); // repeated uint32 latest_pse_isvsvn = 7 [packed = true]; - inline int latest_pse_isvsvn_size() const; - inline void clear_latest_pse_isvsvn(); + int latest_pse_isvsvn_size() const; + void clear_latest_pse_isvsvn(); static const int kLatestPseIsvsvnFieldNumber = 7; - inline ::google::protobuf::uint32 latest_pse_isvsvn(int index) const; - inline void set_latest_pse_isvsvn(int index, ::google::protobuf::uint32 value); - inline void add_latest_pse_isvsvn(::google::protobuf::uint32 value); - inline const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& + ::google::protobuf::uint32 latest_pse_isvsvn(int index) const; + void set_latest_pse_isvsvn(int index, ::google::protobuf::uint32 value); + void add_latest_pse_isvsvn(::google::protobuf::uint32 value); + const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& latest_pse_isvsvn() const; - inline ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* + ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* mutable_latest_pse_isvsvn(); // repeated uint32 latest_psda_svn = 8 [packed = true]; - inline int latest_psda_svn_size() const; - inline void clear_latest_psda_svn(); + int latest_psda_svn_size() const; + void clear_latest_psda_svn(); static const int kLatestPsdaSvnFieldNumber = 8; - inline ::google::protobuf::uint32 latest_psda_svn(int index) const; - inline void set_latest_psda_svn(int index, ::google::protobuf::uint32 value); - inline void add_latest_psda_svn(::google::protobuf::uint32 value); - inline const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& + ::google::protobuf::uint32 latest_psda_svn(int index) const; + void set_latest_psda_svn(int index, ::google::protobuf::uint32 value); + void add_latest_psda_svn(::google::protobuf::uint32 value); + const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& latest_psda_svn() const; - inline ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* + ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* mutable_latest_psda_svn(); // repeated uint32 performance_rekey_gid = 9 [packed = true]; - inline int performance_rekey_gid_size() const; - inline void clear_performance_rekey_gid(); + int performance_rekey_gid_size() const; + void clear_performance_rekey_gid(); static const int kPerformanceRekeyGidFieldNumber = 9; - inline ::google::protobuf::uint32 performance_rekey_gid(int index) const; - inline void set_performance_rekey_gid(int index, ::google::protobuf::uint32 value); - inline void add_performance_rekey_gid(::google::protobuf::uint32 value); - inline const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& + ::google::protobuf::uint32 performance_rekey_gid(int index) const; + void set_performance_rekey_gid(int index, ::google::protobuf::uint32 value); + void add_performance_rekey_gid(::google::protobuf::uint32 value); + const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& performance_rekey_gid() const; - inline ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* + ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* mutable_performance_rekey_gid(); // repeated uint32 ec_sign256_x = 10 [packed = true]; - inline int ec_sign256_x_size() const; - inline void clear_ec_sign256_x(); + int ec_sign256_x_size() const; + void clear_ec_sign256_x(); static const int kEcSign256XFieldNumber = 10; - inline ::google::protobuf::uint32 ec_sign256_x(int index) const; - inline void set_ec_sign256_x(int index, ::google::protobuf::uint32 value); - inline void add_ec_sign256_x(::google::protobuf::uint32 value); - inline const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& + ::google::protobuf::uint32 ec_sign256_x(int index) const; + void set_ec_sign256_x(int index, ::google::protobuf::uint32 value); + void add_ec_sign256_x(::google::protobuf::uint32 value); + const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& ec_sign256_x() const; - inline ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* + ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* mutable_ec_sign256_x(); // repeated uint32 ec_sign256_y = 11 [packed = true]; - inline int ec_sign256_y_size() const; - inline void clear_ec_sign256_y(); + int ec_sign256_y_size() const; + void clear_ec_sign256_y(); static const int kEcSign256YFieldNumber = 11; - inline ::google::protobuf::uint32 ec_sign256_y(int index) const; - inline void set_ec_sign256_y(int index, ::google::protobuf::uint32 value); - inline void add_ec_sign256_y(::google::protobuf::uint32 value); - inline const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& + ::google::protobuf::uint32 ec_sign256_y(int index) const; + void set_ec_sign256_y(int index, ::google::protobuf::uint32 value); + void add_ec_sign256_y(::google::protobuf::uint32 value); + const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& ec_sign256_y() const; - inline ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* + ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* mutable_ec_sign256_y(); // repeated uint32 mac_smk = 12 [packed = true]; - inline int mac_smk_size() const; - inline void clear_mac_smk(); + int mac_smk_size() const; + void clear_mac_smk(); static const int kMacSmkFieldNumber = 12; - inline ::google::protobuf::uint32 mac_smk(int index) const; - inline void set_mac_smk(int index, ::google::protobuf::uint32 value); - inline void add_mac_smk(::google::protobuf::uint32 value); - inline const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& + ::google::protobuf::uint32 mac_smk(int index) const; + void set_mac_smk(int index, ::google::protobuf::uint32 value); + void add_mac_smk(::google::protobuf::uint32 value); + const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& mac_smk() const; - inline ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* + ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* mutable_mac_smk(); // optional uint32 result_size = 13; - inline bool has_result_size() const; - inline void clear_result_size(); + bool has_result_size() const; + void clear_result_size(); static const int kResultSizeFieldNumber = 13; - inline ::google::protobuf::uint32 result_size() const; - inline void set_result_size(::google::protobuf::uint32 value); + ::google::protobuf::uint32 result_size() const; + void set_result_size(::google::protobuf::uint32 value); // repeated uint32 reserved = 14 [packed = true]; - inline int reserved_size() const; - inline void clear_reserved(); + int reserved_size() const; + void clear_reserved(); static const int kReservedFieldNumber = 14; - inline ::google::protobuf::uint32 reserved(int index) const; - inline void set_reserved(int index, ::google::protobuf::uint32 value); - inline void add_reserved(::google::protobuf::uint32 value); - inline const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& + ::google::protobuf::uint32 reserved(int index) const; + void set_reserved(int index, ::google::protobuf::uint32 value); + void add_reserved(::google::protobuf::uint32 value); + const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& reserved() const; - inline ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* + ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* mutable_reserved(); // repeated uint32 payload_tag = 15 [packed = true]; - inline int payload_tag_size() const; - inline void clear_payload_tag(); + int payload_tag_size() const; + void clear_payload_tag(); static const int kPayloadTagFieldNumber = 15; - inline ::google::protobuf::uint32 payload_tag(int index) const; - inline void set_payload_tag(int index, ::google::protobuf::uint32 value); - inline void add_payload_tag(::google::protobuf::uint32 value); - inline const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& + ::google::protobuf::uint32 payload_tag(int index) const; + void set_payload_tag(int index, ::google::protobuf::uint32 value); + void add_payload_tag(::google::protobuf::uint32 value); + const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& payload_tag() const; - inline ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* + ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* mutable_payload_tag(); // repeated uint32 payload = 16 [packed = true]; - inline int payload_size() const; - inline void clear_payload(); + int payload_size() const; + void clear_payload(); static const int kPayloadFieldNumber = 16; - inline ::google::protobuf::uint32 payload(int index) const; - inline void set_payload(int index, ::google::protobuf::uint32 value); - inline void add_payload(::google::protobuf::uint32 value); - inline const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& + ::google::protobuf::uint32 payload(int index) const; + void set_payload(int index, ::google::protobuf::uint32 value); + void add_payload(::google::protobuf::uint32 value); + const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& payload() const; - inline ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* + ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* mutable_payload(); // @@protoc_insertion_point(class_scope:Messages.AttestationMessage) @@ -958,8 +1048,10 @@ class AttestationMessage : public ::google::protobuf::Message { inline void set_has_result_size(); inline void clear_has_result_size(); - ::google::protobuf::UnknownFieldSet _unknown_fields_; + // helper for ByteSize() + int RequiredFieldsByteSizeFallback() const; + ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; ::google::protobuf::uint32 _has_bits_[1]; mutable int _cached_size_; ::google::protobuf::uint32 type_; @@ -995,204 +1087,12 @@ class AttestationMessage : public ::google::protobuf::Message { void InitAsDefaultInstance(); static AttestationMessage* default_instance_; }; -// ------------------------------------------------------------------- - -class SecretMessage : public ::google::protobuf::Message { - public: - SecretMessage(); - virtual ~SecretMessage(); - - SecretMessage(const SecretMessage& from); - - inline SecretMessage& operator=(const SecretMessage& from) { - CopyFrom(from); - return *this; - } - - inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { - return _unknown_fields_; - } - - inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { - return &_unknown_fields_; - } - - static const ::google::protobuf::Descriptor* descriptor(); - static const SecretMessage& default_instance(); - - void Swap(SecretMessage* other); - - // implements Message ---------------------------------------------- - - SecretMessage* New() const; - void CopyFrom(const ::google::protobuf::Message& from); - void MergeFrom(const ::google::protobuf::Message& from); - void CopyFrom(const SecretMessage& from); - void MergeFrom(const SecretMessage& from); - void Clear(); - bool IsInitialized() const; - - int ByteSize() const; - bool MergePartialFromCodedStream( - ::google::protobuf::io::CodedInputStream* input); - void SerializeWithCachedSizes( - ::google::protobuf::io::CodedOutputStream* output) const; - ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; - int GetCachedSize() const { return _cached_size_; } - private: - void SharedCtor(); - void SharedDtor(); - void SetCachedSize(int size) const; - public: - ::google::protobuf::Metadata GetMetadata() const; - - // nested types ---------------------------------------------------- - - // accessors ------------------------------------------------------- - - // required uint32 type = 1; - inline bool has_type() const; - inline void clear_type(); - static const int kTypeFieldNumber = 1; - inline ::google::protobuf::uint32 type() const; - inline void set_type(::google::protobuf::uint32 value); - - // required uint32 size = 2; - inline bool has_size() const; - inline void clear_size(); - static const int kSizeFieldNumber = 2; - inline ::google::protobuf::uint32 size() const; - inline void set_size(::google::protobuf::uint32 value); - - // optional uint32 encryped_pkey_size = 3; - inline bool has_encryped_pkey_size() const; - inline void clear_encryped_pkey_size(); - static const int kEncrypedPkeySizeFieldNumber = 3; - inline ::google::protobuf::uint32 encryped_pkey_size() const; - inline void set_encryped_pkey_size(::google::protobuf::uint32 value); - - // optional uint32 encryped_x509_size = 4; - inline bool has_encryped_x509_size() const; - inline void clear_encryped_x509_size(); - static const int kEncrypedX509SizeFieldNumber = 4; - inline ::google::protobuf::uint32 encryped_x509_size() const; - inline void set_encryped_x509_size(::google::protobuf::uint32 value); - - // repeated uint32 encrypted_content = 5 [packed = true]; - inline int encrypted_content_size() const; - inline void clear_encrypted_content(); - static const int kEncryptedContentFieldNumber = 5; - inline ::google::protobuf::uint32 encrypted_content(int index) const; - inline void set_encrypted_content(int index, ::google::protobuf::uint32 value); - inline void add_encrypted_content(::google::protobuf::uint32 value); - inline const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& - encrypted_content() const; - inline ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* - mutable_encrypted_content(); - - // repeated uint32 mac_smk = 6 [packed = true]; - inline int mac_smk_size() const; - inline void clear_mac_smk(); - static const int kMacSmkFieldNumber = 6; - inline ::google::protobuf::uint32 mac_smk(int index) const; - inline void set_mac_smk(int index, ::google::protobuf::uint32 value); - inline void add_mac_smk(::google::protobuf::uint32 value); - inline const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& - mac_smk() const; - inline ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* - mutable_mac_smk(); - - // repeated uint32 encrypted_pkey = 7 [packed = true]; - inline int encrypted_pkey_size() const; - inline void clear_encrypted_pkey(); - static const int kEncryptedPkeyFieldNumber = 7; - inline ::google::protobuf::uint32 encrypted_pkey(int index) const; - inline void set_encrypted_pkey(int index, ::google::protobuf::uint32 value); - inline void add_encrypted_pkey(::google::protobuf::uint32 value); - inline const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& - encrypted_pkey() const; - inline ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* - mutable_encrypted_pkey(); - - // repeated uint32 encrypted_pkey_mac_smk = 8 [packed = true]; - inline int encrypted_pkey_mac_smk_size() const; - inline void clear_encrypted_pkey_mac_smk(); - static const int kEncryptedPkeyMacSmkFieldNumber = 8; - inline ::google::protobuf::uint32 encrypted_pkey_mac_smk(int index) const; - inline void set_encrypted_pkey_mac_smk(int index, ::google::protobuf::uint32 value); - inline void add_encrypted_pkey_mac_smk(::google::protobuf::uint32 value); - inline const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& - encrypted_pkey_mac_smk() const; - inline ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* - mutable_encrypted_pkey_mac_smk(); - - // repeated uint32 encrypted_x509 = 9 [packed = true]; - inline int encrypted_x509_size() const; - inline void clear_encrypted_x509(); - static const int kEncryptedX509FieldNumber = 9; - inline ::google::protobuf::uint32 encrypted_x509(int index) const; - inline void set_encrypted_x509(int index, ::google::protobuf::uint32 value); - inline void add_encrypted_x509(::google::protobuf::uint32 value); - inline const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& - encrypted_x509() const; - inline ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* - mutable_encrypted_x509(); - - // repeated uint32 encrypted_x509_mac_smk = 10 [packed = true]; - inline int encrypted_x509_mac_smk_size() const; - inline void clear_encrypted_x509_mac_smk(); - static const int kEncryptedX509MacSmkFieldNumber = 10; - inline ::google::protobuf::uint32 encrypted_x509_mac_smk(int index) const; - inline void set_encrypted_x509_mac_smk(int index, ::google::protobuf::uint32 value); - inline void add_encrypted_x509_mac_smk(::google::protobuf::uint32 value); - inline const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& - encrypted_x509_mac_smk() const; - inline ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* - mutable_encrypted_x509_mac_smk(); - - // @@protoc_insertion_point(class_scope:Messages.SecretMessage) - private: - inline void set_has_type(); - inline void clear_has_type(); - inline void set_has_size(); - inline void clear_has_size(); - inline void set_has_encryped_pkey_size(); - inline void clear_has_encryped_pkey_size(); - inline void set_has_encryped_x509_size(); - inline void clear_has_encryped_x509_size(); - - ::google::protobuf::UnknownFieldSet _unknown_fields_; - - ::google::protobuf::uint32 _has_bits_[1]; - mutable int _cached_size_; - ::google::protobuf::uint32 type_; - ::google::protobuf::uint32 size_; - ::google::protobuf::uint32 encryped_pkey_size_; - ::google::protobuf::uint32 encryped_x509_size_; - ::google::protobuf::RepeatedField< ::google::protobuf::uint32 > encrypted_content_; - mutable int _encrypted_content_cached_byte_size_; - ::google::protobuf::RepeatedField< ::google::protobuf::uint32 > mac_smk_; - mutable int _mac_smk_cached_byte_size_; - ::google::protobuf::RepeatedField< ::google::protobuf::uint32 > encrypted_pkey_; - mutable int _encrypted_pkey_cached_byte_size_; - ::google::protobuf::RepeatedField< ::google::protobuf::uint32 > encrypted_pkey_mac_smk_; - mutable int _encrypted_pkey_mac_smk_cached_byte_size_; - ::google::protobuf::RepeatedField< ::google::protobuf::uint32 > encrypted_x509_; - mutable int _encrypted_x509_cached_byte_size_; - ::google::protobuf::RepeatedField< ::google::protobuf::uint32 > encrypted_x509_mac_smk_; - mutable int _encrypted_x509_mac_smk_cached_byte_size_; - friend void protobuf_AddDesc_Messages_2eproto(); - friend void protobuf_AssignDesc_Messages_2eproto(); - friend void protobuf_ShutdownFile_Messages_2eproto(); - - void InitAsDefaultInstance(); - static SecretMessage* default_instance_; -}; // =================================================================== // =================================================================== +#if !PROTOBUF_INLINE_NOT_IN_HEADERS // InitialMessage // required uint32 type = 1; @@ -2421,300 +2321,22 @@ AttestationMessage::mutable_payload() { return &payload_; } +#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS // ------------------------------------------------------------------- -// SecretMessage - -// required uint32 type = 1; -inline bool SecretMessage::has_type() const { - return (_has_bits_[0] & 0x00000001u) != 0; -} -inline void SecretMessage::set_has_type() { - _has_bits_[0] |= 0x00000001u; -} -inline void SecretMessage::clear_has_type() { - _has_bits_[0] &= ~0x00000001u; -} -inline void SecretMessage::clear_type() { - type_ = 0u; - clear_has_type(); -} -inline ::google::protobuf::uint32 SecretMessage::type() const { - // @@protoc_insertion_point(field_get:Messages.SecretMessage.type) - return type_; -} -inline void SecretMessage::set_type(::google::protobuf::uint32 value) { - set_has_type(); - type_ = value; - // @@protoc_insertion_point(field_set:Messages.SecretMessage.type) -} - -// required uint32 size = 2; -inline bool SecretMessage::has_size() const { - return (_has_bits_[0] & 0x00000002u) != 0; -} -inline void SecretMessage::set_has_size() { - _has_bits_[0] |= 0x00000002u; -} -inline void SecretMessage::clear_has_size() { - _has_bits_[0] &= ~0x00000002u; -} -inline void SecretMessage::clear_size() { - size_ = 0u; - clear_has_size(); -} -inline ::google::protobuf::uint32 SecretMessage::size() const { - // @@protoc_insertion_point(field_get:Messages.SecretMessage.size) - return size_; -} -inline void SecretMessage::set_size(::google::protobuf::uint32 value) { - set_has_size(); - size_ = value; - // @@protoc_insertion_point(field_set:Messages.SecretMessage.size) -} - -// optional uint32 encryped_pkey_size = 3; -inline bool SecretMessage::has_encryped_pkey_size() const { - return (_has_bits_[0] & 0x00000004u) != 0; -} -inline void SecretMessage::set_has_encryped_pkey_size() { - _has_bits_[0] |= 0x00000004u; -} -inline void SecretMessage::clear_has_encryped_pkey_size() { - _has_bits_[0] &= ~0x00000004u; -} -inline void SecretMessage::clear_encryped_pkey_size() { - encryped_pkey_size_ = 0u; - clear_has_encryped_pkey_size(); -} -inline ::google::protobuf::uint32 SecretMessage::encryped_pkey_size() const { - // @@protoc_insertion_point(field_get:Messages.SecretMessage.encryped_pkey_size) - return encryped_pkey_size_; -} -inline void SecretMessage::set_encryped_pkey_size(::google::protobuf::uint32 value) { - set_has_encryped_pkey_size(); - encryped_pkey_size_ = value; - // @@protoc_insertion_point(field_set:Messages.SecretMessage.encryped_pkey_size) -} - -// optional uint32 encryped_x509_size = 4; -inline bool SecretMessage::has_encryped_x509_size() const { - return (_has_bits_[0] & 0x00000008u) != 0; -} -inline void SecretMessage::set_has_encryped_x509_size() { - _has_bits_[0] |= 0x00000008u; -} -inline void SecretMessage::clear_has_encryped_x509_size() { - _has_bits_[0] &= ~0x00000008u; -} -inline void SecretMessage::clear_encryped_x509_size() { - encryped_x509_size_ = 0u; - clear_has_encryped_x509_size(); -} -inline ::google::protobuf::uint32 SecretMessage::encryped_x509_size() const { - // @@protoc_insertion_point(field_get:Messages.SecretMessage.encryped_x509_size) - return encryped_x509_size_; -} -inline void SecretMessage::set_encryped_x509_size(::google::protobuf::uint32 value) { - set_has_encryped_x509_size(); - encryped_x509_size_ = value; - // @@protoc_insertion_point(field_set:Messages.SecretMessage.encryped_x509_size) -} - -// repeated uint32 encrypted_content = 5 [packed = true]; -inline int SecretMessage::encrypted_content_size() const { - return encrypted_content_.size(); -} -inline void SecretMessage::clear_encrypted_content() { - encrypted_content_.Clear(); -} -inline ::google::protobuf::uint32 SecretMessage::encrypted_content(int index) const { - // @@protoc_insertion_point(field_get:Messages.SecretMessage.encrypted_content) - return encrypted_content_.Get(index); -} -inline void SecretMessage::set_encrypted_content(int index, ::google::protobuf::uint32 value) { - encrypted_content_.Set(index, value); - // @@protoc_insertion_point(field_set:Messages.SecretMessage.encrypted_content) -} -inline void SecretMessage::add_encrypted_content(::google::protobuf::uint32 value) { - encrypted_content_.Add(value); - // @@protoc_insertion_point(field_add:Messages.SecretMessage.encrypted_content) -} -inline const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& -SecretMessage::encrypted_content() const { - // @@protoc_insertion_point(field_list:Messages.SecretMessage.encrypted_content) - return encrypted_content_; -} -inline ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* -SecretMessage::mutable_encrypted_content() { - // @@protoc_insertion_point(field_mutable_list:Messages.SecretMessage.encrypted_content) - return &encrypted_content_; -} - -// repeated uint32 mac_smk = 6 [packed = true]; -inline int SecretMessage::mac_smk_size() const { - return mac_smk_.size(); -} -inline void SecretMessage::clear_mac_smk() { - mac_smk_.Clear(); -} -inline ::google::protobuf::uint32 SecretMessage::mac_smk(int index) const { - // @@protoc_insertion_point(field_get:Messages.SecretMessage.mac_smk) - return mac_smk_.Get(index); -} -inline void SecretMessage::set_mac_smk(int index, ::google::protobuf::uint32 value) { - mac_smk_.Set(index, value); - // @@protoc_insertion_point(field_set:Messages.SecretMessage.mac_smk) -} -inline void SecretMessage::add_mac_smk(::google::protobuf::uint32 value) { - mac_smk_.Add(value); - // @@protoc_insertion_point(field_add:Messages.SecretMessage.mac_smk) -} -inline const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& -SecretMessage::mac_smk() const { - // @@protoc_insertion_point(field_list:Messages.SecretMessage.mac_smk) - return mac_smk_; -} -inline ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* -SecretMessage::mutable_mac_smk() { - // @@protoc_insertion_point(field_mutable_list:Messages.SecretMessage.mac_smk) - return &mac_smk_; -} - -// repeated uint32 encrypted_pkey = 7 [packed = true]; -inline int SecretMessage::encrypted_pkey_size() const { - return encrypted_pkey_.size(); -} -inline void SecretMessage::clear_encrypted_pkey() { - encrypted_pkey_.Clear(); -} -inline ::google::protobuf::uint32 SecretMessage::encrypted_pkey(int index) const { - // @@protoc_insertion_point(field_get:Messages.SecretMessage.encrypted_pkey) - return encrypted_pkey_.Get(index); -} -inline void SecretMessage::set_encrypted_pkey(int index, ::google::protobuf::uint32 value) { - encrypted_pkey_.Set(index, value); - // @@protoc_insertion_point(field_set:Messages.SecretMessage.encrypted_pkey) -} -inline void SecretMessage::add_encrypted_pkey(::google::protobuf::uint32 value) { - encrypted_pkey_.Add(value); - // @@protoc_insertion_point(field_add:Messages.SecretMessage.encrypted_pkey) -} -inline const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& -SecretMessage::encrypted_pkey() const { - // @@protoc_insertion_point(field_list:Messages.SecretMessage.encrypted_pkey) - return encrypted_pkey_; -} -inline ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* -SecretMessage::mutable_encrypted_pkey() { - // @@protoc_insertion_point(field_mutable_list:Messages.SecretMessage.encrypted_pkey) - return &encrypted_pkey_; -} +// ------------------------------------------------------------------- -// repeated uint32 encrypted_pkey_mac_smk = 8 [packed = true]; -inline int SecretMessage::encrypted_pkey_mac_smk_size() const { - return encrypted_pkey_mac_smk_.size(); -} -inline void SecretMessage::clear_encrypted_pkey_mac_smk() { - encrypted_pkey_mac_smk_.Clear(); -} -inline ::google::protobuf::uint32 SecretMessage::encrypted_pkey_mac_smk(int index) const { - // @@protoc_insertion_point(field_get:Messages.SecretMessage.encrypted_pkey_mac_smk) - return encrypted_pkey_mac_smk_.Get(index); -} -inline void SecretMessage::set_encrypted_pkey_mac_smk(int index, ::google::protobuf::uint32 value) { - encrypted_pkey_mac_smk_.Set(index, value); - // @@protoc_insertion_point(field_set:Messages.SecretMessage.encrypted_pkey_mac_smk) -} -inline void SecretMessage::add_encrypted_pkey_mac_smk(::google::protobuf::uint32 value) { - encrypted_pkey_mac_smk_.Add(value); - // @@protoc_insertion_point(field_add:Messages.SecretMessage.encrypted_pkey_mac_smk) -} -inline const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& -SecretMessage::encrypted_pkey_mac_smk() const { - // @@protoc_insertion_point(field_list:Messages.SecretMessage.encrypted_pkey_mac_smk) - return encrypted_pkey_mac_smk_; -} -inline ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* -SecretMessage::mutable_encrypted_pkey_mac_smk() { - // @@protoc_insertion_point(field_mutable_list:Messages.SecretMessage.encrypted_pkey_mac_smk) - return &encrypted_pkey_mac_smk_; -} +// ------------------------------------------------------------------- -// repeated uint32 encrypted_x509 = 9 [packed = true]; -inline int SecretMessage::encrypted_x509_size() const { - return encrypted_x509_.size(); -} -inline void SecretMessage::clear_encrypted_x509() { - encrypted_x509_.Clear(); -} -inline ::google::protobuf::uint32 SecretMessage::encrypted_x509(int index) const { - // @@protoc_insertion_point(field_get:Messages.SecretMessage.encrypted_x509) - return encrypted_x509_.Get(index); -} -inline void SecretMessage::set_encrypted_x509(int index, ::google::protobuf::uint32 value) { - encrypted_x509_.Set(index, value); - // @@protoc_insertion_point(field_set:Messages.SecretMessage.encrypted_x509) -} -inline void SecretMessage::add_encrypted_x509(::google::protobuf::uint32 value) { - encrypted_x509_.Add(value); - // @@protoc_insertion_point(field_add:Messages.SecretMessage.encrypted_x509) -} -inline const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& -SecretMessage::encrypted_x509() const { - // @@protoc_insertion_point(field_list:Messages.SecretMessage.encrypted_x509) - return encrypted_x509_; -} -inline ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* -SecretMessage::mutable_encrypted_x509() { - // @@protoc_insertion_point(field_mutable_list:Messages.SecretMessage.encrypted_x509) - return &encrypted_x509_; -} +// ------------------------------------------------------------------- -// repeated uint32 encrypted_x509_mac_smk = 10 [packed = true]; -inline int SecretMessage::encrypted_x509_mac_smk_size() const { - return encrypted_x509_mac_smk_.size(); -} -inline void SecretMessage::clear_encrypted_x509_mac_smk() { - encrypted_x509_mac_smk_.Clear(); -} -inline ::google::protobuf::uint32 SecretMessage::encrypted_x509_mac_smk(int index) const { - // @@protoc_insertion_point(field_get:Messages.SecretMessage.encrypted_x509_mac_smk) - return encrypted_x509_mac_smk_.Get(index); -} -inline void SecretMessage::set_encrypted_x509_mac_smk(int index, ::google::protobuf::uint32 value) { - encrypted_x509_mac_smk_.Set(index, value); - // @@protoc_insertion_point(field_set:Messages.SecretMessage.encrypted_x509_mac_smk) -} -inline void SecretMessage::add_encrypted_x509_mac_smk(::google::protobuf::uint32 value) { - encrypted_x509_mac_smk_.Add(value); - // @@protoc_insertion_point(field_add:Messages.SecretMessage.encrypted_x509_mac_smk) -} -inline const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >& -SecretMessage::encrypted_x509_mac_smk() const { - // @@protoc_insertion_point(field_list:Messages.SecretMessage.encrypted_x509_mac_smk) - return encrypted_x509_mac_smk_; -} -inline ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >* -SecretMessage::mutable_encrypted_x509_mac_smk() { - // @@protoc_insertion_point(field_mutable_list:Messages.SecretMessage.encrypted_x509_mac_smk) - return &encrypted_x509_mac_smk_; -} +// ------------------------------------------------------------------- // @@protoc_insertion_point(namespace_scope) } // namespace Messages -#ifndef SWIG -namespace google { -namespace protobuf { - - -} // namespace google -} // namespace protobuf -#endif // SWIG - // @@protoc_insertion_point(global_scope) #endif // PROTOBUF_Messages_2eproto__INCLUDED diff --git a/samplecode/remoteattestation/GoogleMessages/Messages.proto b/samplecode/remoteattestation/GoogleMessages/Messages.proto index c828cfd6a..73675aed0 100644 --- a/samplecode/remoteattestation/GoogleMessages/Messages.proto +++ b/samplecode/remoteattestation/GoogleMessages/Messages.proto @@ -1,3 +1,4 @@ +syntax = "proto2"; package Messages; message InitialMessage { diff --git a/samplecode/remoteattestation/MessageHandler/MessageHandler.cpp b/samplecode/remoteattestation/MessageHandler/MessageHandler.cpp index 4881348f8..9c80f2abd 100644 --- a/samplecode/remoteattestation/MessageHandler/MessageHandler.cpp +++ b/samplecode/remoteattestation/MessageHandler/MessageHandler.cpp @@ -33,6 +33,7 @@ int MessageHandler::init() { this->nm->connectCallbackHandler([this](string v, int type) { return this->incomingHandler(v, type); }); + return 1; } @@ -396,7 +397,7 @@ string MessageHandler::handleVerification() { string MessageHandler::createInitMsg(int type, string msg) { - Messages::SecretMessage init_msg; + Messages::InitialMessage init_msg; init_msg.set_type(type); init_msg.set_size(msg.size()); diff --git a/samplecode/remoteattestation/ServiceProvider/isv_app/VerificationManager.cpp b/samplecode/remoteattestation/ServiceProvider/isv_app/VerificationManager.cpp index 5d7520913..029ac4488 100644 --- a/samplecode/remoteattestation/ServiceProvider/isv_app/VerificationManager.cpp +++ b/samplecode/remoteattestation/ServiceProvider/isv_app/VerificationManager.cpp @@ -55,6 +55,7 @@ int VerificationManager::init() { this->nm->connectCallbackHandler([this](string v, int type) { return this->incomingHandler(v, type); }); + return 1; } @@ -178,10 +179,10 @@ vector VerificationManager::incomingHandler(string v, int type) { } break; case RA_APP_ATT_OK: { - Messages::SecretMessage sec_msg; - ret = sec_msg.ParseFromString(v); + Messages::InitialMessage msg; + ret = msg.ParseFromString(v); if (ret) { - if (sec_msg.type() == RA_APP_ATT_OK) { + if (msg.type() == RA_APP_ATT_OK) { this->handleAppAttOk(); } } diff --git a/samplecode/remoteattestation/ServiceProvider/service_provider/ServiceProvider.h b/samplecode/remoteattestation/ServiceProvider/service_provider/ServiceProvider.h index 1228020bd..dd369bec1 100644 --- a/samplecode/remoteattestation/ServiceProvider/service_provider/ServiceProvider.h +++ b/samplecode/remoteattestation/ServiceProvider/service_provider/ServiceProvider.h @@ -78,7 +78,6 @@ class ServiceProvider { int sp_ra_proc_msg1_req(Messages::MessageMSG1 msg1, Messages::MessageMSG2 *msg2); int sp_ra_proc_msg3_req(Messages::MessageMSG3 msg, Messages::AttestationMessage *att_msg); sgx_ra_msg3_t* assembleMSG3(Messages::MessageMSG3 msg); - int sp_ra_proc_app_att_hmac(Messages::SecretMessage *new_msg, string hmac_key, string hmac_key_filename); private: WebService *ws = NULL; diff --git a/samplecode/sealeddata/enclave/Cargo.toml b/samplecode/sealeddata/enclave/Cargo.toml index 8bfce6b30..64a6e5605 100644 --- a/samplecode/sealeddata/enclave/Cargo.toml +++ b/samplecode/sealeddata/enclave/Cargo.toml @@ -22,6 +22,7 @@ serde_derive = { git = "https://github.com/mesalock-linux/serde-sgx" } serde_cbor = { git = "https://github.com/mesalock-linux/cbor-sgx" } [patch.'https://github.com/apache/teaclave-sgx-sdk.git'] +sgx_align_struct_attribute = { path = "../../../sgx_align_struct_attribute" } sgx_alloc = { path = "../../../sgx_alloc" } sgx_backtrace = { path = "../../../sgx_backtrace" } sgx_backtrace_sys = { path = "../../../sgx_backtrace_sys" } @@ -30,6 +31,7 @@ sgx_cov = { path = "../../../sgx_cov" } sgx_crypto_helper = { path = "../../../sgx_crypto_helper" } sgx_demangle = { path = "../../../sgx_demangle" } sgx_libc = { path = "../../../sgx_libc" } +sgx_no_tstd = { path = "../../../sgx_no_tstd" } sgx_rand = { path = "../../../sgx_rand" } sgx_rand_derive = { path = "../../../sgx_rand_derive" } sgx_serialize = { path = "../../../sgx_serialize" } diff --git a/samplecode/sealeddata/enclave/Xargo.toml b/samplecode/sealeddata/enclave/Xargo.toml index 31fb7d4a6..cd02285d5 100644 --- a/samplecode/sealeddata/enclave/Xargo.toml +++ b/samplecode/sealeddata/enclave/Xargo.toml @@ -88,6 +88,7 @@ stage = 7 [dependencies.sgx_cov] path = "../../../sgx_cov" stage = 7 + [dependencies.sgx_signal] path = "../../../sgx_signal" stage = 7 diff --git a/samplecode/sealeddata/enclave/x86_64-unknown-linux-sgx.json b/samplecode/sealeddata/enclave/x86_64-unknown-linux-sgx.json index 69b38be21..53f104e25 100644 --- a/samplecode/sealeddata/enclave/x86_64-unknown-linux-sgx.json +++ b/samplecode/sealeddata/enclave/x86_64-unknown-linux-sgx.json @@ -1,13 +1,13 @@ { "arch": "x86_64", "cpu": "x86-64", + "crt-static-respected": true, "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128", "dynamic-linking": true, "env": "sgx", - "exe-allocation-crate": "alloc_system", "executables": true, - "has-elf-tls": true, "has-rpath": true, + "has-thread-local": true, "linker-flavor": "gcc", "linker-is-gnu": true, "llvm-target": "x86_64-unknown-linux-gnu", @@ -30,6 +30,13 @@ 1 ] }, + "supported-sanitizers": [ + "address", + "cfi", + "leak", + "memory", + "thread" + ], "target-c-int-width": "32", "target-endian": "little", "target-family": "unix", diff --git a/samplecode/secretsharing/enclave/Cargo.toml b/samplecode/secretsharing/enclave/Cargo.toml index ad5014090..c5f950425 100644 --- a/samplecode/secretsharing/enclave/Cargo.toml +++ b/samplecode/secretsharing/enclave/Cargo.toml @@ -18,6 +18,7 @@ sgx_tstd = { path = "../../../sgx_tstd" } threshold-secret-sharing = { git = "https://github.com/mesalock-linux/rust-threshold-secret-sharing-sgx" } [patch.'https://github.com/apache/teaclave-sgx-sdk.git'] +sgx_align_struct_attribute = { path = "../../../sgx_align_struct_attribute" } sgx_alloc = { path = "../../../sgx_alloc" } sgx_backtrace = { path = "../../../sgx_backtrace" } sgx_backtrace_sys = { path = "../../../sgx_backtrace_sys" } @@ -26,6 +27,7 @@ sgx_cov = { path = "../../../sgx_cov" } sgx_crypto_helper = { path = "../../../sgx_crypto_helper" } sgx_demangle = { path = "../../../sgx_demangle" } sgx_libc = { path = "../../../sgx_libc" } +sgx_no_tstd = { path = "../../../sgx_no_tstd" } sgx_rand = { path = "../../../sgx_rand" } sgx_rand_derive = { path = "../../../sgx_rand_derive" } sgx_serialize = { path = "../../../sgx_serialize" } diff --git a/samplecode/secretsharing/enclave/Xargo.toml b/samplecode/secretsharing/enclave/Xargo.toml index 31fb7d4a6..cd02285d5 100644 --- a/samplecode/secretsharing/enclave/Xargo.toml +++ b/samplecode/secretsharing/enclave/Xargo.toml @@ -88,6 +88,7 @@ stage = 7 [dependencies.sgx_cov] path = "../../../sgx_cov" stage = 7 + [dependencies.sgx_signal] path = "../../../sgx_signal" stage = 7 diff --git a/samplecode/secretsharing/enclave/x86_64-unknown-linux-sgx.json b/samplecode/secretsharing/enclave/x86_64-unknown-linux-sgx.json index 69b38be21..53f104e25 100644 --- a/samplecode/secretsharing/enclave/x86_64-unknown-linux-sgx.json +++ b/samplecode/secretsharing/enclave/x86_64-unknown-linux-sgx.json @@ -1,13 +1,13 @@ { "arch": "x86_64", "cpu": "x86-64", + "crt-static-respected": true, "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128", "dynamic-linking": true, "env": "sgx", - "exe-allocation-crate": "alloc_system", "executables": true, - "has-elf-tls": true, "has-rpath": true, + "has-thread-local": true, "linker-flavor": "gcc", "linker-is-gnu": true, "llvm-target": "x86_64-unknown-linux-gnu", @@ -30,6 +30,13 @@ 1 ] }, + "supported-sanitizers": [ + "address", + "cfi", + "leak", + "memory", + "thread" + ], "target-c-int-width": "32", "target-endian": "little", "target-family": "unix", diff --git a/samplecode/serialize/enclave/Cargo.toml b/samplecode/serialize/enclave/Cargo.toml index 8496a58fc..00b57a287 100644 --- a/samplecode/serialize/enclave/Cargo.toml +++ b/samplecode/serialize/enclave/Cargo.toml @@ -15,6 +15,7 @@ sgx_serialize = { git = "https://github.com/apache/teaclave-sgx-sdk.git" } sgx_serialize_derive = { git = "https://github.com/apache/teaclave-sgx-sdk.git" } [patch.'https://github.com/apache/teaclave-sgx-sdk.git'] +sgx_align_struct_attribute = { path = "../../../sgx_align_struct_attribute" } sgx_alloc = { path = "../../../sgx_alloc" } sgx_backtrace = { path = "../../../sgx_backtrace" } sgx_backtrace_sys = { path = "../../../sgx_backtrace_sys" } @@ -23,6 +24,7 @@ sgx_cov = { path = "../../../sgx_cov" } sgx_crypto_helper = { path = "../../../sgx_crypto_helper" } sgx_demangle = { path = "../../../sgx_demangle" } sgx_libc = { path = "../../../sgx_libc" } +sgx_no_tstd = { path = "../../../sgx_no_tstd" } sgx_rand = { path = "../../../sgx_rand" } sgx_rand_derive = { path = "../../../sgx_rand_derive" } sgx_serialize = { path = "../../../sgx_serialize" } diff --git a/samplecode/serialize/enclave/Xargo.toml b/samplecode/serialize/enclave/Xargo.toml index 31fb7d4a6..cd02285d5 100644 --- a/samplecode/serialize/enclave/Xargo.toml +++ b/samplecode/serialize/enclave/Xargo.toml @@ -88,6 +88,7 @@ stage = 7 [dependencies.sgx_cov] path = "../../../sgx_cov" stage = 7 + [dependencies.sgx_signal] path = "../../../sgx_signal" stage = 7 diff --git a/samplecode/serialize/enclave/x86_64-unknown-linux-sgx.json b/samplecode/serialize/enclave/x86_64-unknown-linux-sgx.json index 69b38be21..53f104e25 100644 --- a/samplecode/serialize/enclave/x86_64-unknown-linux-sgx.json +++ b/samplecode/serialize/enclave/x86_64-unknown-linux-sgx.json @@ -1,13 +1,13 @@ { "arch": "x86_64", "cpu": "x86-64", + "crt-static-respected": true, "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128", "dynamic-linking": true, "env": "sgx", - "exe-allocation-crate": "alloc_system", "executables": true, - "has-elf-tls": true, "has-rpath": true, + "has-thread-local": true, "linker-flavor": "gcc", "linker-is-gnu": true, "llvm-target": "x86_64-unknown-linux-gnu", @@ -30,6 +30,13 @@ 1 ] }, + "supported-sanitizers": [ + "address", + "cfi", + "leak", + "memory", + "thread" + ], "target-c-int-width": "32", "target-endian": "little", "target-family": "unix", diff --git a/samplecode/sgx-cov/enclave/Cargo.toml b/samplecode/sgx-cov/enclave/Cargo.toml index 9cd5c3716..6653d1a14 100644 --- a/samplecode/sgx-cov/enclave/Cargo.toml +++ b/samplecode/sgx-cov/enclave/Cargo.toml @@ -22,7 +22,9 @@ sgx_types = { git = "https://github.com/apache/teaclave-sgx-sdk.git" } sgx_tstd = { git = "https://github.com/apache/teaclave-sgx-sdk.git" } sgx_trts = { git = "https://github.com/apache/teaclave-sgx-sdk.git" } sgx_cov = { git = "https://github.com/apache/teaclave-sgx-sdk.git", optional = true } + [patch.'https://github.com/apache/teaclave-sgx-sdk.git'] +sgx_align_struct_attribute = { path = "../../../sgx_align_struct_attribute" } sgx_alloc = { path = "../../../sgx_alloc" } sgx_backtrace = { path = "../../../sgx_backtrace" } sgx_backtrace_sys = { path = "../../../sgx_backtrace_sys" } @@ -31,6 +33,7 @@ sgx_cov = { path = "../../../sgx_cov" } sgx_crypto_helper = { path = "../../../sgx_crypto_helper" } sgx_demangle = { path = "../../../sgx_demangle" } sgx_libc = { path = "../../../sgx_libc" } +sgx_no_tstd = { path = "../../../sgx_no_tstd" } sgx_rand = { path = "../../../sgx_rand" } sgx_rand_derive = { path = "../../../sgx_rand_derive" } sgx_serialize = { path = "../../../sgx_serialize" } diff --git a/samplecode/sgx-cov/enclave/x86_64-unknown-linux-sgx.json b/samplecode/sgx-cov/enclave/x86_64-unknown-linux-sgx.json index 69b38be21..53f104e25 100644 --- a/samplecode/sgx-cov/enclave/x86_64-unknown-linux-sgx.json +++ b/samplecode/sgx-cov/enclave/x86_64-unknown-linux-sgx.json @@ -1,13 +1,13 @@ { "arch": "x86_64", "cpu": "x86-64", + "crt-static-respected": true, "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128", "dynamic-linking": true, "env": "sgx", - "exe-allocation-crate": "alloc_system", "executables": true, - "has-elf-tls": true, "has-rpath": true, + "has-thread-local": true, "linker-flavor": "gcc", "linker-is-gnu": true, "llvm-target": "x86_64-unknown-linux-gnu", @@ -30,6 +30,13 @@ 1 ] }, + "supported-sanitizers": [ + "address", + "cfi", + "leak", + "memory", + "thread" + ], "target-c-int-width": "32", "target-endian": "little", "target-family": "unix", diff --git a/samplecode/static-data-distribution/app/Cargo.toml b/samplecode/static-data-distribution/app/Cargo.toml index 3ceb7a93f..e250741b6 100644 --- a/samplecode/static-data-distribution/app/Cargo.toml +++ b/samplecode/static-data-distribution/app/Cargo.toml @@ -11,30 +11,7 @@ sgx_crypto_helper = { git = "https://github.com/apache/teaclave-sgx-sdk.git" } serde_json = "1.0" [patch.'https://github.com/apache/teaclave-sgx-sdk.git'] -sgx_alloc = { path = "../../../sgx_alloc" } -sgx_backtrace = { path = "../../../sgx_backtrace" } -sgx_backtrace_sys = { path = "../../../sgx_backtrace_sys" } -sgx_build_helper = { path = "../../../sgx_build_helper" } -sgx_cov = { path = "../../../sgx_cov" } sgx_crypto_helper = { path = "../../../sgx_crypto_helper" } -sgx_demangle = { path = "../../../sgx_demangle" } -sgx_libc = { path = "../../../sgx_libc" } -sgx_rand = { path = "../../../sgx_rand" } -sgx_rand_derive = { path = "../../../sgx_rand_derive" } -sgx_serialize = { path = "../../../sgx_serialize" } -sgx_serialize_derive = { path = "../../../sgx_serialize_derive" } -sgx_serialize_derive_internals = { path = "../../../sgx_serialize_derive_internals" } -sgx_tcrypto = { path = "../../../sgx_tcrypto" } -sgx_tcrypto_helper = { path = "../../../sgx_tcrypto_helper" } -sgx_tdh = { path = "../../../sgx_tdh" } -sgx_tkey_exchange = { path = "../../../sgx_tkey_exchange" } -sgx_tprotected_fs = { path = "../../../sgx_tprotected_fs" } -sgx_trts = { path = "../../../sgx_trts" } -sgx_tse = { path = "../../../sgx_tse" } -sgx_tseal = { path = "../../../sgx_tseal" } -sgx_tstd = { path = "../../../sgx_tstd" } -sgx_tunittest = { path = "../../../sgx_tunittest" } sgx_types = { path = "../../../sgx_types" } sgx_ucrypto = { path = "../../../sgx_ucrypto" } -sgx_unwind = { path = "../../../sgx_unwind" } sgx_urts = { path = "../../../sgx_urts" } diff --git a/samplecode/static-data-distribution/enclave/Cargo.toml b/samplecode/static-data-distribution/enclave/Cargo.toml index 64117b6c7..fdaf73d14 100644 --- a/samplecode/static-data-distribution/enclave/Cargo.toml +++ b/samplecode/static-data-distribution/enclave/Cargo.toml @@ -19,13 +19,16 @@ sgx_crypto_helper = { package = "sgx_tcrypto_helper", git = "https://github.com/ serde_json = { git = "https://github.com/mesalock-linux/serde-json-sgx" } [patch.'https://github.com/apache/teaclave-sgx-sdk.git'] +sgx_align_struct_attribute = { path = "../../../sgx_align_struct_attribute" } sgx_alloc = { path = "../../../sgx_alloc" } sgx_backtrace = { path = "../../../sgx_backtrace" } sgx_backtrace_sys = { path = "../../../sgx_backtrace_sys" } sgx_build_helper = { path = "../../../sgx_build_helper" } sgx_cov = { path = "../../../sgx_cov" } +sgx_crypto_helper = { path = "../../../sgx_crypto_helper" } sgx_demangle = { path = "../../../sgx_demangle" } sgx_libc = { path = "../../../sgx_libc" } +sgx_no_tstd = { path = "../../../sgx_no_tstd" } sgx_rand = { path = "../../../sgx_rand" } sgx_rand_derive = { path = "../../../sgx_rand_derive" } sgx_serialize = { path = "../../../sgx_serialize" } diff --git a/samplecode/static-data-distribution/enclave/Xargo.toml b/samplecode/static-data-distribution/enclave/Xargo.toml index 31fb7d4a6..cd02285d5 100644 --- a/samplecode/static-data-distribution/enclave/Xargo.toml +++ b/samplecode/static-data-distribution/enclave/Xargo.toml @@ -88,6 +88,7 @@ stage = 7 [dependencies.sgx_cov] path = "../../../sgx_cov" stage = 7 + [dependencies.sgx_signal] path = "../../../sgx_signal" stage = 7 diff --git a/samplecode/static-data-distribution/enclave/x86_64-unknown-linux-sgx.json b/samplecode/static-data-distribution/enclave/x86_64-unknown-linux-sgx.json index 69b38be21..53f104e25 100644 --- a/samplecode/static-data-distribution/enclave/x86_64-unknown-linux-sgx.json +++ b/samplecode/static-data-distribution/enclave/x86_64-unknown-linux-sgx.json @@ -1,13 +1,13 @@ { "arch": "x86_64", "cpu": "x86-64", + "crt-static-respected": true, "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128", "dynamic-linking": true, "env": "sgx", - "exe-allocation-crate": "alloc_system", "executables": true, - "has-elf-tls": true, "has-rpath": true, + "has-thread-local": true, "linker-flavor": "gcc", "linker-is-gnu": true, "llvm-target": "x86_64-unknown-linux-gnu", @@ -30,6 +30,13 @@ 1 ] }, + "supported-sanitizers": [ + "address", + "cfi", + "leak", + "memory", + "thread" + ], "target-c-int-width": "32", "target-endian": "little", "target-family": "unix", diff --git a/samplecode/switchless/enclave/Cargo.toml b/samplecode/switchless/enclave/Cargo.toml index 24bf333bf..19f90bc1f 100644 --- a/samplecode/switchless/enclave/Cargo.toml +++ b/samplecode/switchless/enclave/Cargo.toml @@ -15,6 +15,7 @@ sgx_types = { git = "https://github.com/apache/teaclave-sgx-sdk.git" } sgx_tstd = { git = "https://github.com/apache/teaclave-sgx-sdk.git" } [patch.'https://github.com/apache/teaclave-sgx-sdk.git'] +sgx_align_struct_attribute = { path = "../../../sgx_align_struct_attribute" } sgx_alloc = { path = "../../../sgx_alloc" } sgx_backtrace = { path = "../../../sgx_backtrace" } sgx_backtrace_sys = { path = "../../../sgx_backtrace_sys" } @@ -23,6 +24,7 @@ sgx_cov = { path = "../../../sgx_cov" } sgx_crypto_helper = { path = "../../../sgx_crypto_helper" } sgx_demangle = { path = "../../../sgx_demangle" } sgx_libc = { path = "../../../sgx_libc" } +sgx_no_tstd = { path = "../../../sgx_no_tstd" } sgx_rand = { path = "../../../sgx_rand" } sgx_rand_derive = { path = "../../../sgx_rand_derive" } sgx_serialize = { path = "../../../sgx_serialize" } diff --git a/samplecode/switchless/enclave/Xargo.toml b/samplecode/switchless/enclave/Xargo.toml index 31fb7d4a6..cd02285d5 100644 --- a/samplecode/switchless/enclave/Xargo.toml +++ b/samplecode/switchless/enclave/Xargo.toml @@ -88,6 +88,7 @@ stage = 7 [dependencies.sgx_cov] path = "../../../sgx_cov" stage = 7 + [dependencies.sgx_signal] path = "../../../sgx_signal" stage = 7 diff --git a/samplecode/switchless/enclave/x86_64-unknown-linux-sgx.json b/samplecode/switchless/enclave/x86_64-unknown-linux-sgx.json index 69b38be21..53f104e25 100644 --- a/samplecode/switchless/enclave/x86_64-unknown-linux-sgx.json +++ b/samplecode/switchless/enclave/x86_64-unknown-linux-sgx.json @@ -1,13 +1,13 @@ { "arch": "x86_64", "cpu": "x86-64", + "crt-static-respected": true, "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128", "dynamic-linking": true, "env": "sgx", - "exe-allocation-crate": "alloc_system", "executables": true, - "has-elf-tls": true, "has-rpath": true, + "has-thread-local": true, "linker-flavor": "gcc", "linker-is-gnu": true, "llvm-target": "x86_64-unknown-linux-gnu", @@ -30,6 +30,13 @@ 1 ] }, + "supported-sanitizers": [ + "address", + "cfi", + "leak", + "memory", + "thread" + ], "target-c-int-width": "32", "target-endian": "little", "target-family": "unix", diff --git a/samplecode/tcmalloc/enclave/Cargo.toml b/samplecode/tcmalloc/enclave/Cargo.toml index f4f32244b..c5477784e 100644 --- a/samplecode/tcmalloc/enclave/Cargo.toml +++ b/samplecode/tcmalloc/enclave/Cargo.toml @@ -15,6 +15,7 @@ sgx_types = { git = "https://github.com/apache/teaclave-sgx-sdk.git" } sgx_tstd = { git = "https://github.com/apache/teaclave-sgx-sdk.git" } [patch.'https://github.com/apache/teaclave-sgx-sdk.git'] +sgx_align_struct_attribute = { path = "../../../sgx_align_struct_attribute" } sgx_alloc = { path = "../../../sgx_alloc" } sgx_backtrace = { path = "../../../sgx_backtrace" } sgx_backtrace_sys = { path = "../../../sgx_backtrace_sys" } @@ -23,6 +24,7 @@ sgx_cov = { path = "../../../sgx_cov" } sgx_crypto_helper = { path = "../../../sgx_crypto_helper" } sgx_demangle = { path = "../../../sgx_demangle" } sgx_libc = { path = "../../../sgx_libc" } +sgx_no_tstd = { path = "../../../sgx_no_tstd" } sgx_rand = { path = "../../../sgx_rand" } sgx_rand_derive = { path = "../../../sgx_rand_derive" } sgx_serialize = { path = "../../../sgx_serialize" } diff --git a/samplecode/tcmalloc/enclave/Xargo.toml b/samplecode/tcmalloc/enclave/Xargo.toml index 31fb7d4a6..cd02285d5 100644 --- a/samplecode/tcmalloc/enclave/Xargo.toml +++ b/samplecode/tcmalloc/enclave/Xargo.toml @@ -88,6 +88,7 @@ stage = 7 [dependencies.sgx_cov] path = "../../../sgx_cov" stage = 7 + [dependencies.sgx_signal] path = "../../../sgx_signal" stage = 7 diff --git a/samplecode/tcmalloc/enclave/x86_64-unknown-linux-sgx.json b/samplecode/tcmalloc/enclave/x86_64-unknown-linux-sgx.json index 69b38be21..53f104e25 100644 --- a/samplecode/tcmalloc/enclave/x86_64-unknown-linux-sgx.json +++ b/samplecode/tcmalloc/enclave/x86_64-unknown-linux-sgx.json @@ -1,13 +1,13 @@ { "arch": "x86_64", "cpu": "x86-64", + "crt-static-respected": true, "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128", "dynamic-linking": true, "env": "sgx", - "exe-allocation-crate": "alloc_system", "executables": true, - "has-elf-tls": true, "has-rpath": true, + "has-thread-local": true, "linker-flavor": "gcc", "linker-is-gnu": true, "llvm-target": "x86_64-unknown-linux-gnu", @@ -30,6 +30,13 @@ 1 ] }, + "supported-sanitizers": [ + "address", + "cfi", + "leak", + "memory", + "thread" + ], "target-c-int-width": "32", "target-endian": "little", "target-family": "unix", diff --git a/samplecode/thread/enclave/Cargo.toml b/samplecode/thread/enclave/Cargo.toml index 4234637cf..7ee75d165 100644 --- a/samplecode/thread/enclave/Cargo.toml +++ b/samplecode/thread/enclave/Cargo.toml @@ -14,6 +14,7 @@ default = [] sgx_tstd = { git = "https://github.com/apache/teaclave-sgx-sdk.git" } [patch.'https://github.com/apache/teaclave-sgx-sdk.git'] +sgx_align_struct_attribute = { path = "../../../sgx_align_struct_attribute" } sgx_alloc = { path = "../../../sgx_alloc" } sgx_backtrace = { path = "../../../sgx_backtrace" } sgx_backtrace_sys = { path = "../../../sgx_backtrace_sys" } @@ -22,6 +23,7 @@ sgx_cov = { path = "../../../sgx_cov" } sgx_crypto_helper = { path = "../../../sgx_crypto_helper" } sgx_demangle = { path = "../../../sgx_demangle" } sgx_libc = { path = "../../../sgx_libc" } +sgx_no_tstd = { path = "../../../sgx_no_tstd" } sgx_rand = { path = "../../../sgx_rand" } sgx_rand_derive = { path = "../../../sgx_rand_derive" } sgx_serialize = { path = "../../../sgx_serialize" } diff --git a/samplecode/thread/enclave/Xargo.toml b/samplecode/thread/enclave/Xargo.toml index 31fb7d4a6..cd02285d5 100644 --- a/samplecode/thread/enclave/Xargo.toml +++ b/samplecode/thread/enclave/Xargo.toml @@ -88,6 +88,7 @@ stage = 7 [dependencies.sgx_cov] path = "../../../sgx_cov" stage = 7 + [dependencies.sgx_signal] path = "../../../sgx_signal" stage = 7 diff --git a/samplecode/thread/enclave/x86_64-unknown-linux-sgx.json b/samplecode/thread/enclave/x86_64-unknown-linux-sgx.json index 69b38be21..53f104e25 100644 --- a/samplecode/thread/enclave/x86_64-unknown-linux-sgx.json +++ b/samplecode/thread/enclave/x86_64-unknown-linux-sgx.json @@ -1,13 +1,13 @@ { "arch": "x86_64", "cpu": "x86-64", + "crt-static-respected": true, "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128", "dynamic-linking": true, "env": "sgx", - "exe-allocation-crate": "alloc_system", "executables": true, - "has-elf-tls": true, "has-rpath": true, + "has-thread-local": true, "linker-flavor": "gcc", "linker-is-gnu": true, "llvm-target": "x86_64-unknown-linux-gnu", @@ -30,6 +30,13 @@ 1 ] }, + "supported-sanitizers": [ + "address", + "cfi", + "leak", + "memory", + "thread" + ], "target-c-int-width": "32", "target-endian": "little", "target-family": "unix", diff --git a/samplecode/tls/tlsclient/enclave/Cargo.toml b/samplecode/tls/tlsclient/enclave/Cargo.toml index 29472968d..842017bde 100644 --- a/samplecode/tls/tlsclient/enclave/Cargo.toml +++ b/samplecode/tls/tlsclient/enclave/Cargo.toml @@ -22,6 +22,7 @@ lazy_static = { version = "1.4.0", default-features = false, features = ["spin_n # Comment out these following lines to use rust-sgx-sdk from git [patch.'https://github.com/apache/teaclave-sgx-sdk.git'] +sgx_align_struct_attribute = { path = "../../../../sgx_align_struct_attribute" } sgx_alloc = { path = "../../../../sgx_alloc" } sgx_backtrace = { path = "../../../../sgx_backtrace" } sgx_backtrace_sys = { path = "../../../../sgx_backtrace_sys" } @@ -30,6 +31,7 @@ sgx_cov = { path = "../../../../sgx_cov" } sgx_crypto_helper = { path = "../../../../sgx_crypto_helper" } sgx_demangle = { path = "../../../../sgx_demangle" } sgx_libc = { path = "../../../../sgx_libc" } +sgx_no_tstd = { path = "../../../../sgx_no_tstd" } sgx_rand = { path = "../../../../sgx_rand" } sgx_rand_derive = { path = "../../../../sgx_rand_derive" } sgx_serialize = { path = "../../../../sgx_serialize" } diff --git a/samplecode/tls/tlsclient/enclave/Xargo.toml b/samplecode/tls/tlsclient/enclave/Xargo.toml index 989d7960e..795f1f06f 100644 --- a/samplecode/tls/tlsclient/enclave/Xargo.toml +++ b/samplecode/tls/tlsclient/enclave/Xargo.toml @@ -89,6 +89,7 @@ stage = 7 [dependencies.sgx_cov] path = "../../../../sgx_cov" stage = 7 + [dependencies.sgx_signal] path = "../../../../sgx_signal" stage = 7 diff --git a/samplecode/tls/tlsclient/enclave/x86_64-unknown-linux-sgx.json b/samplecode/tls/tlsclient/enclave/x86_64-unknown-linux-sgx.json index 69b38be21..53f104e25 100644 --- a/samplecode/tls/tlsclient/enclave/x86_64-unknown-linux-sgx.json +++ b/samplecode/tls/tlsclient/enclave/x86_64-unknown-linux-sgx.json @@ -1,13 +1,13 @@ { "arch": "x86_64", "cpu": "x86-64", + "crt-static-respected": true, "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128", "dynamic-linking": true, "env": "sgx", - "exe-allocation-crate": "alloc_system", "executables": true, - "has-elf-tls": true, "has-rpath": true, + "has-thread-local": true, "linker-flavor": "gcc", "linker-is-gnu": true, "llvm-target": "x86_64-unknown-linux-gnu", @@ -30,6 +30,13 @@ 1 ] }, + "supported-sanitizers": [ + "address", + "cfi", + "leak", + "memory", + "thread" + ], "target-c-int-width": "32", "target-endian": "little", "target-family": "unix", diff --git a/samplecode/tls/tlsserver/enclave/Cargo.toml b/samplecode/tls/tlsserver/enclave/Cargo.toml index 5e9debe6b..6c3440175 100644 --- a/samplecode/tls/tlsserver/enclave/Cargo.toml +++ b/samplecode/tls/tlsserver/enclave/Cargo.toml @@ -21,6 +21,7 @@ webpki = { git = "https://github.com/mesalock-linux/webpki", branch = "mesalock_ lazy_static = { version = "1.4.0", default-features = false, features = ["spin_no_std"] } [patch.'https://github.com/apache/teaclave-sgx-sdk.git'] +sgx_align_struct_attribute = { path = "../../../../sgx_align_struct_attribute" } sgx_alloc = { path = "../../../../sgx_alloc" } sgx_backtrace = { path = "../../../../sgx_backtrace" } sgx_backtrace_sys = { path = "../../../../sgx_backtrace_sys" } @@ -29,6 +30,7 @@ sgx_cov = { path = "../../../../sgx_cov" } sgx_crypto_helper = { path = "../../../../sgx_crypto_helper" } sgx_demangle = { path = "../../../../sgx_demangle" } sgx_libc = { path = "../../../../sgx_libc" } +sgx_no_tstd = { path = "../../../../sgx_no_tstd" } sgx_rand = { path = "../../../../sgx_rand" } sgx_rand_derive = { path = "../../../../sgx_rand_derive" } sgx_serialize = { path = "../../../../sgx_serialize" } diff --git a/samplecode/tls/tlsserver/enclave/Xargo.toml b/samplecode/tls/tlsserver/enclave/Xargo.toml index 989d7960e..795f1f06f 100644 --- a/samplecode/tls/tlsserver/enclave/Xargo.toml +++ b/samplecode/tls/tlsserver/enclave/Xargo.toml @@ -89,6 +89,7 @@ stage = 7 [dependencies.sgx_cov] path = "../../../../sgx_cov" stage = 7 + [dependencies.sgx_signal] path = "../../../../sgx_signal" stage = 7 diff --git a/samplecode/tls/tlsserver/enclave/x86_64-unknown-linux-sgx.json b/samplecode/tls/tlsserver/enclave/x86_64-unknown-linux-sgx.json index 69b38be21..53f104e25 100644 --- a/samplecode/tls/tlsserver/enclave/x86_64-unknown-linux-sgx.json +++ b/samplecode/tls/tlsserver/enclave/x86_64-unknown-linux-sgx.json @@ -1,13 +1,13 @@ { "arch": "x86_64", "cpu": "x86-64", + "crt-static-respected": true, "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128", "dynamic-linking": true, "env": "sgx", - "exe-allocation-crate": "alloc_system", "executables": true, - "has-elf-tls": true, "has-rpath": true, + "has-thread-local": true, "linker-flavor": "gcc", "linker-is-gnu": true, "llvm-target": "x86_64-unknown-linux-gnu", @@ -30,6 +30,13 @@ 1 ] }, + "supported-sanitizers": [ + "address", + "cfi", + "leak", + "memory", + "thread" + ], "target-c-int-width": "32", "target-endian": "little", "target-family": "unix", diff --git a/samplecode/tr-mpc/tr-mpc-server/enclave/Cargo.toml b/samplecode/tr-mpc/tr-mpc-server/enclave/Cargo.toml index 0c9e9e698..9c7372914 100644 --- a/samplecode/tr-mpc/tr-mpc-server/enclave/Cargo.toml +++ b/samplecode/tr-mpc/tr-mpc-server/enclave/Cargo.toml @@ -32,6 +32,7 @@ webpki-roots= { git = "https://github.com/mesalock-linux/webpki-roots", branch = # Comment out these following lines to use rust-sgx-sdk from git [patch.'https://github.com/apache/teaclave-sgx-sdk.git'] +sgx_align_struct_attribute = { path = "../../../../sgx_align_struct_attribute" } sgx_alloc = { path = "../../../../sgx_alloc" } sgx_backtrace = { path = "../../../../sgx_backtrace" } sgx_backtrace_sys = { path = "../../../../sgx_backtrace_sys" } @@ -40,6 +41,7 @@ sgx_cov = { path = "../../../../sgx_cov" } sgx_crypto_helper = { path = "../../../../sgx_crypto_helper" } sgx_demangle = { path = "../../../../sgx_demangle" } sgx_libc = { path = "../../../../sgx_libc" } +sgx_no_tstd = { path = "../../../../sgx_no_tstd" } sgx_rand = { path = "../../../../sgx_rand" } sgx_rand_derive = { path = "../../../../sgx_rand_derive" } sgx_serialize = { path = "../../../../sgx_serialize" } diff --git a/samplecode/tr-mpc/tr-mpc-server/enclave/Xargo.toml b/samplecode/tr-mpc/tr-mpc-server/enclave/Xargo.toml index 989d7960e..795f1f06f 100644 --- a/samplecode/tr-mpc/tr-mpc-server/enclave/Xargo.toml +++ b/samplecode/tr-mpc/tr-mpc-server/enclave/Xargo.toml @@ -89,6 +89,7 @@ stage = 7 [dependencies.sgx_cov] path = "../../../../sgx_cov" stage = 7 + [dependencies.sgx_signal] path = "../../../../sgx_signal" stage = 7 diff --git a/samplecode/tr-mpc/tr-mpc-server/enclave/x86_64-unknown-linux-sgx.json b/samplecode/tr-mpc/tr-mpc-server/enclave/x86_64-unknown-linux-sgx.json index 69b38be21..53f104e25 100644 --- a/samplecode/tr-mpc/tr-mpc-server/enclave/x86_64-unknown-linux-sgx.json +++ b/samplecode/tr-mpc/tr-mpc-server/enclave/x86_64-unknown-linux-sgx.json @@ -1,13 +1,13 @@ { "arch": "x86_64", "cpu": "x86-64", + "crt-static-respected": true, "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128", "dynamic-linking": true, "env": "sgx", - "exe-allocation-crate": "alloc_system", "executables": true, - "has-elf-tls": true, "has-rpath": true, + "has-thread-local": true, "linker-flavor": "gcc", "linker-is-gnu": true, "llvm-target": "x86_64-unknown-linux-gnu", @@ -30,6 +30,13 @@ 1 ] }, + "supported-sanitizers": [ + "address", + "cfi", + "leak", + "memory", + "thread" + ], "target-c-int-width": "32", "target-endian": "little", "target-family": "unix", diff --git a/samplecode/ue-ra/ue-ra-server/enclave/Cargo.toml b/samplecode/ue-ra/ue-ra-server/enclave/Cargo.toml index 071e8add5..f768c196b 100644 --- a/samplecode/ue-ra/ue-ra-server/enclave/Cargo.toml +++ b/samplecode/ue-ra/ue-ra-server/enclave/Cargo.toml @@ -31,6 +31,7 @@ webpki-roots= { git = "https://github.com/mesalock-linux/webpki-roots", branch = # Comment out these following lines to use rust-sgx-sdk from git [patch.'https://github.com/apache/teaclave-sgx-sdk.git'] +sgx_align_struct_attribute = { path = "../../../../sgx_align_struct_attribute" } sgx_alloc = { path = "../../../../sgx_alloc" } sgx_backtrace = { path = "../../../../sgx_backtrace" } sgx_backtrace_sys = { path = "../../../../sgx_backtrace_sys" } @@ -39,6 +40,7 @@ sgx_cov = { path = "../../../../sgx_cov" } sgx_crypto_helper = { path = "../../../../sgx_crypto_helper" } sgx_demangle = { path = "../../../../sgx_demangle" } sgx_libc = { path = "../../../../sgx_libc" } +sgx_no_tstd = { path = "../../../../sgx_no_tstd" } sgx_rand = { path = "../../../../sgx_rand" } sgx_rand_derive = { path = "../../../../sgx_rand_derive" } sgx_serialize = { path = "../../../../sgx_serialize" } diff --git a/samplecode/ue-ra/ue-ra-server/enclave/Xargo.toml b/samplecode/ue-ra/ue-ra-server/enclave/Xargo.toml index 989d7960e..795f1f06f 100644 --- a/samplecode/ue-ra/ue-ra-server/enclave/Xargo.toml +++ b/samplecode/ue-ra/ue-ra-server/enclave/Xargo.toml @@ -89,6 +89,7 @@ stage = 7 [dependencies.sgx_cov] path = "../../../../sgx_cov" stage = 7 + [dependencies.sgx_signal] path = "../../../../sgx_signal" stage = 7 diff --git a/samplecode/ue-ra/ue-ra-server/enclave/x86_64-unknown-linux-sgx.json b/samplecode/ue-ra/ue-ra-server/enclave/x86_64-unknown-linux-sgx.json index 69b38be21..53f104e25 100644 --- a/samplecode/ue-ra/ue-ra-server/enclave/x86_64-unknown-linux-sgx.json +++ b/samplecode/ue-ra/ue-ra-server/enclave/x86_64-unknown-linux-sgx.json @@ -1,13 +1,13 @@ { "arch": "x86_64", "cpu": "x86-64", + "crt-static-respected": true, "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128", "dynamic-linking": true, "env": "sgx", - "exe-allocation-crate": "alloc_system", "executables": true, - "has-elf-tls": true, "has-rpath": true, + "has-thread-local": true, "linker-flavor": "gcc", "linker-is-gnu": true, "llvm-target": "x86_64-unknown-linux-gnu", @@ -30,6 +30,13 @@ 1 ] }, + "supported-sanitizers": [ + "address", + "cfi", + "leak", + "memory", + "thread" + ], "target-c-int-width": "32", "target-endian": "little", "target-family": "unix", diff --git a/samplecode/unit-test/enclave/Xargo.toml b/samplecode/unit-test/enclave/Xargo.toml index 61e97a95e..e383be2c9 100644 --- a/samplecode/unit-test/enclave/Xargo.toml +++ b/samplecode/unit-test/enclave/Xargo.toml @@ -92,4 +92,4 @@ stage = 7 [dependencies.sgx_signal] path = "../../../sgx_signal" -stage = 7 \ No newline at end of file +stage = 7 diff --git a/samplecode/unit-test/enclave/src/test_time.rs b/samplecode/unit-test/enclave/src/test_time.rs index a0a3f1d52..5d868e5cd 100644 --- a/samplecode/unit-test/enclave/src/test_time.rs +++ b/samplecode/unit-test/enclave/src/test_time.rs @@ -36,7 +36,7 @@ pub fn test_std_time() { { let a = Instant::now(); - should_panic!((a - Duration::new(1, 0)).duration_since(a)); + assert!((a - Duration::new(1, 0)).duration_since(a) == Duration::new(0, 0)); } { diff --git a/samplecode/unit-test/enclave/x86_64-unknown-linux-sgx.json b/samplecode/unit-test/enclave/x86_64-unknown-linux-sgx.json index 69b38be21..53f104e25 100644 --- a/samplecode/unit-test/enclave/x86_64-unknown-linux-sgx.json +++ b/samplecode/unit-test/enclave/x86_64-unknown-linux-sgx.json @@ -1,13 +1,13 @@ { "arch": "x86_64", "cpu": "x86-64", + "crt-static-respected": true, "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128", "dynamic-linking": true, "env": "sgx", - "exe-allocation-crate": "alloc_system", "executables": true, - "has-elf-tls": true, "has-rpath": true, + "has-thread-local": true, "linker-flavor": "gcc", "linker-is-gnu": true, "llvm-target": "x86_64-unknown-linux-gnu", @@ -30,6 +30,13 @@ 1 ] }, + "supported-sanitizers": [ + "address", + "cfi", + "leak", + "memory", + "thread" + ], "target-c-int-width": "32", "target-endian": "little", "target-family": "unix", diff --git a/samplecode/wasmi/enclave/Cargo.toml b/samplecode/wasmi/enclave/Cargo.toml index 410497e78..2b9dba5a3 100644 --- a/samplecode/wasmi/enclave/Cargo.toml +++ b/samplecode/wasmi/enclave/Cargo.toml @@ -20,12 +20,18 @@ lazy_static = { version = "1.1.0", features = ["spin_no_std"] } [target.'cfg(not(target_env = "sgx"))'.dependencies] sgx_types = { git = "https://github.com/apache/teaclave-sgx-sdk.git" } sgx_tstd = { git = "https://github.com/apache/teaclave-sgx-sdk.git" } + [patch.'https://github.com/apache/teaclave-sgx-sdk.git'] +sgx_align_struct_attribute = { path = "../../../sgx_align_struct_attribute" } sgx_alloc = { path = "../../../sgx_alloc" } +sgx_backtrace = { path = "../../../sgx_backtrace" } +sgx_backtrace_sys = { path = "../../../sgx_backtrace_sys" } sgx_build_helper = { path = "../../../sgx_build_helper" } sgx_cov = { path = "../../../sgx_cov" } sgx_crypto_helper = { path = "../../../sgx_crypto_helper" } +sgx_demangle = { path = "../../../sgx_demangle" } sgx_libc = { path = "../../../sgx_libc" } +sgx_no_tstd = { path = "../../../sgx_no_tstd" } sgx_rand = { path = "../../../sgx_rand" } sgx_rand_derive = { path = "../../../sgx_rand_derive" } sgx_serialize = { path = "../../../sgx_serialize" } @@ -42,6 +48,6 @@ sgx_tseal = { path = "../../../sgx_tseal" } sgx_tstd = { path = "../../../sgx_tstd" } sgx_tunittest = { path = "../../../sgx_tunittest" } sgx_types = { path = "../../../sgx_types" } -sgx_ucrypto = { path = "../../../sgx_ucrypto" } +#sgx_ucrypto = { path = "../../../sgx_ucrypto" } sgx_unwind = { path = "../../../sgx_unwind" } -sgx_urts = { path = "../../../sgx_urts" } +#sgx_urts = { path = "../../../sgx_urts" } diff --git a/samplecode/wasmi/enclave/Xargo.toml b/samplecode/wasmi/enclave/Xargo.toml index 31fb7d4a6..cd02285d5 100644 --- a/samplecode/wasmi/enclave/Xargo.toml +++ b/samplecode/wasmi/enclave/Xargo.toml @@ -88,6 +88,7 @@ stage = 7 [dependencies.sgx_cov] path = "../../../sgx_cov" stage = 7 + [dependencies.sgx_signal] path = "../../../sgx_signal" stage = 7 diff --git a/samplecode/wasmi/enclave/sgxwasm/Cargo.toml b/samplecode/wasmi/enclave/sgxwasm/Cargo.toml index 36deb2db5..853ed6ec4 100644 --- a/samplecode/wasmi/enclave/sgxwasm/Cargo.toml +++ b/samplecode/wasmi/enclave/sgxwasm/Cargo.toml @@ -14,6 +14,7 @@ sgx_types = { git = "https://github.com/apache/teaclave-sgx-sdk.git" } sgx_tstd = { git = "https://github.com/apache/teaclave-sgx-sdk.git" } [patch.'https://github.com/apache/teaclave-sgx-sdk.git'] +sgx_align_struct_attribute = { path = "../../../../sgx_align_struct_attribute" } sgx_alloc = { path = "../../../../sgx_alloc" } sgx_backtrace = { path = "../../../../sgx_backtrace" } sgx_backtrace_sys = { path = "../../../../sgx_backtrace_sys" } @@ -22,6 +23,7 @@ sgx_cov = { path = "../../../../sgx_cov" } sgx_crypto_helper = { path = "../../../../sgx_crypto_helper" } sgx_demangle = { path = "../../../../sgx_demangle" } sgx_libc = { path = "../../../../sgx_libc" } +sgx_no_tstd = { path = "../../../../sgx_no_tstd" } sgx_rand = { path = "../../../../sgx_rand" } sgx_rand_derive = { path = "../../../../sgx_rand_derive" } sgx_serialize = { path = "../../../../sgx_serialize" } diff --git a/samplecode/wasmi/enclave/x86_64-unknown-linux-sgx.json b/samplecode/wasmi/enclave/x86_64-unknown-linux-sgx.json index 69b38be21..53f104e25 100644 --- a/samplecode/wasmi/enclave/x86_64-unknown-linux-sgx.json +++ b/samplecode/wasmi/enclave/x86_64-unknown-linux-sgx.json @@ -1,13 +1,13 @@ { "arch": "x86_64", "cpu": "x86-64", + "crt-static-respected": true, "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128", "dynamic-linking": true, "env": "sgx", - "exe-allocation-crate": "alloc_system", "executables": true, - "has-elf-tls": true, "has-rpath": true, + "has-thread-local": true, "linker-flavor": "gcc", "linker-is-gnu": true, "llvm-target": "x86_64-unknown-linux-gnu", @@ -30,6 +30,13 @@ 1 ] }, + "supported-sanitizers": [ + "address", + "cfi", + "leak", + "memory", + "thread" + ], "target-c-int-width": "32", "target-endian": "little", "target-family": "unix", diff --git a/samplecode/zlib-lazy-static-sample/enclave/Cargo.toml b/samplecode/zlib-lazy-static-sample/enclave/Cargo.toml index a5ebcecbb..372d9e2bf 100644 --- a/samplecode/zlib-lazy-static-sample/enclave/Cargo.toml +++ b/samplecode/zlib-lazy-static-sample/enclave/Cargo.toml @@ -20,6 +20,7 @@ libflate = { git = "https://github.com/mesalock-linux/libflate-sgx" } lazy_static = { version = "1.1.0", features = ["spin_no_std"] } [patch.'https://github.com/apache/teaclave-sgx-sdk.git'] +sgx_align_struct_attribute = { path = "../../../sgx_align_struct_attribute" } sgx_alloc = { path = "../../../sgx_alloc" } sgx_backtrace = { path = "../../../sgx_backtrace" } sgx_backtrace_sys = { path = "../../../sgx_backtrace_sys" } @@ -28,6 +29,7 @@ sgx_cov = { path = "../../../sgx_cov" } sgx_crypto_helper = { path = "../../../sgx_crypto_helper" } sgx_demangle = { path = "../../../sgx_demangle" } sgx_libc = { path = "../../../sgx_libc" } +sgx_no_tstd = { path = "../../../sgx_no_tstd" } sgx_rand = { path = "../../../sgx_rand" } sgx_rand_derive = { path = "../../../sgx_rand_derive" } sgx_serialize = { path = "../../../sgx_serialize" } @@ -44,6 +46,6 @@ sgx_tseal = { path = "../../../sgx_tseal" } sgx_tstd = { path = "../../../sgx_tstd" } sgx_tunittest = { path = "../../../sgx_tunittest" } sgx_types = { path = "../../../sgx_types" } -sgx_ucrypto = { path = "../../../sgx_ucrypto" } +#sgx_ucrypto = { path = "../../../sgx_ucrypto" } sgx_unwind = { path = "../../../sgx_unwind" } -sgx_urts = { path = "../../../sgx_urts" } +#sgx_urts = { path = "../../../sgx_urts" } diff --git a/samplecode/zlib-lazy-static-sample/enclave/Xargo.toml b/samplecode/zlib-lazy-static-sample/enclave/Xargo.toml index 31fb7d4a6..cd02285d5 100644 --- a/samplecode/zlib-lazy-static-sample/enclave/Xargo.toml +++ b/samplecode/zlib-lazy-static-sample/enclave/Xargo.toml @@ -88,6 +88,7 @@ stage = 7 [dependencies.sgx_cov] path = "../../../sgx_cov" stage = 7 + [dependencies.sgx_signal] path = "../../../sgx_signal" stage = 7 diff --git a/samplecode/zlib-lazy-static-sample/enclave/x86_64-unknown-linux-sgx.json b/samplecode/zlib-lazy-static-sample/enclave/x86_64-unknown-linux-sgx.json index 69b38be21..53f104e25 100644 --- a/samplecode/zlib-lazy-static-sample/enclave/x86_64-unknown-linux-sgx.json +++ b/samplecode/zlib-lazy-static-sample/enclave/x86_64-unknown-linux-sgx.json @@ -1,13 +1,13 @@ { "arch": "x86_64", "cpu": "x86-64", + "crt-static-respected": true, "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128", "dynamic-linking": true, "env": "sgx", - "exe-allocation-crate": "alloc_system", "executables": true, - "has-elf-tls": true, "has-rpath": true, + "has-thread-local": true, "linker-flavor": "gcc", "linker-is-gnu": true, "llvm-target": "x86_64-unknown-linux-gnu", @@ -30,6 +30,13 @@ 1 ] }, + "supported-sanitizers": [ + "address", + "cfi", + "leak", + "memory", + "thread" + ], "target-c-int-width": "32", "target-endian": "little", "target-family": "unix", diff --git a/sgx_align_struct_attribute/Cargo.toml b/sgx_align_struct_attribute/Cargo.toml index fb8163384..46596bd79 100644 --- a/sgx_align_struct_attribute/Cargo.toml +++ b/sgx_align_struct_attribute/Cargo.toml @@ -6,7 +6,7 @@ repository = "https://github.com/apache/teaclave-sgx-sdk" license-file = "LICENSE" documentation = "https://teaclave.apache.org/sgx-sdk-docs/" description = "Rust SGX SDK provides the ability to write Intel SGX applications in Rust Programming Language." -edition = "2018" +edition = "2021" [lib] name = "sgx_align_struct_attribute" diff --git a/sgx_align_struct_attribute/src/align.rs b/sgx_align_struct_attribute/src/align.rs index 9e3a523e0..2daf865ab 100644 --- a/sgx_align_struct_attribute/src/align.rs +++ b/sgx_align_struct_attribute/src/align.rs @@ -60,10 +60,7 @@ impl Parse for AlignArgs { impl AlignArgs { pub fn get_layout(&self) -> Result { - let align_iter = self - .vars - .iter() - .find(|v| v.ident.to_string() == "align"); + let align_iter = self.vars.iter().find(|v| v.ident == "align"); let align: usize = if let Some(align_value) = align_iter { self.parse_align(&align_value.value)? } else { @@ -73,10 +70,7 @@ impl AlignArgs { )); }; - let size_iter = self - .vars - .iter() - .find(|v| v.ident.to_string() == "size"); + let size_iter = self.vars.iter().find(|v| v.ident == "size"); let size: usize = if let Some(size_value) = size_iter { self.parse_size(&size_value.value)? } else { @@ -180,21 +174,22 @@ impl AlignStruct { quote! { #attrs #align_attr - #vis struct #name#generics { + #vis struct #name #generics { #pad_item, #fields } } } + #[allow(clippy::filter_next, clippy::collapsible_match)] fn is_contains_specified_attr(&self, atrr: &str) -> bool { let mut erxcept_attr = false; for attr in &self.input.attrs { let ident = attr.path.get_ident(); let meta = attr.parse_meta(); - if ident.map_or(false, |v| v.to_string() == "repr") && meta.is_ok() { + if ident.map_or(false, |v| *v == "repr") && meta.is_ok() { if let Ok(Meta::List(ref m)) = meta { - if m.nested.len() > 0 { + if !m.nested.is_empty() { erxcept_attr = m .nested .iter() @@ -202,8 +197,7 @@ impl AlignStruct { let mut find = false; if let syn::NestedMeta::Meta(ref s) = x { if let syn::Meta::Path(p) = s { - find = - p.get_ident().map_or(false, |v| v.to_string() == atrr); + find = p.get_ident().map_or(false, |v| *v == atrr); } } find @@ -226,7 +220,7 @@ impl AlignStruct { fn generate_align_attr(&self) -> proc_macro2::TokenStream { let align = self.align_layout.align(); - let litint = LitInt::new(&format!("{}", align).to_string(), Span::call_site()); + let litint = LitInt::new(&format!("{}", align), Span::call_site()); quote! { #[repr(align(#litint))] } diff --git a/sgx_align_struct_attribute/src/layout.rs b/sgx_align_struct_attribute/src/layout.rs index 68150c4f9..861f9eeee 100644 --- a/sgx_align_struct_attribute/src/layout.rs +++ b/sgx_align_struct_attribute/src/layout.rs @@ -72,24 +72,20 @@ fn align_needed_for(layout: Layout, offset: usize) -> Result bool { (buf + len < len) || (buf + len < buf) } fn check_layout(layout: &Layout) -> bool { - if layout.size() == 0 + !(layout.size() == 0 || !layout.align().is_power_of_two() - || layout.size() > usize::MAX - (layout.align() - 1) - { - false - } else { - true - } + || layout.size() > usize::MAX - (layout.align() - 1)) } fn check_align_req(size: usize, align_req: &[AlignReq]) -> bool { - if align_req.len() == 0 { + if align_req.is_empty() { return false; } let len: usize = (size + 7) / 8; @@ -148,6 +144,7 @@ fn ror(v: i64, c: usize) -> i64 { rol(v, (0 - c as isize) as usize) } +#[allow(clippy::comparison_chain)] fn count_lzb(bmp: i64) -> i32 { if bmp == 0 { -1 @@ -195,7 +192,7 @@ fn make_bitmap(align_req: &[AlignReq]) -> i64 { if req.len > 63 { return -1; } else { - bmp |= rol(((1 as i64) << req.len) - 1, req.offset); + bmp |= rol(((1_i64) << req.len) - 1, req.offset); } } bmp diff --git a/sgx_alloc/Cargo.toml b/sgx_alloc/Cargo.toml index 02b464b42..387eae2ef 100644 --- a/sgx_alloc/Cargo.toml +++ b/sgx_alloc/Cargo.toml @@ -6,7 +6,7 @@ repository = "https://github.com/apache/teaclave-sgx-sdk" license-file = "LICENSE" documentation = "https://dingelish.github.io/" description = "Rust SGX SDK provides the ability to write Intel SGX applications in Rust Programming Language." -edition = "2018" +edition = "2021" [lib] name = "sgx_alloc" diff --git a/sgx_alloc/src/alignalloc.rs b/sgx_alloc/src/alignalloc.rs index f9afa9e32..b83c130c8 100644 --- a/sgx_alloc/src/alignalloc.rs +++ b/sgx_alloc/src/alignalloc.rs @@ -373,7 +373,7 @@ mod platform { if req.len > 63 { return -1; } else { - bmp |= rol(((1 as i64) << req.len) - 1, req.offset); + bmp |= rol(((1_i64) << req.len) - 1, req.offset); } } bmp diff --git a/sgx_alloc/src/lib.rs b/sgx_alloc/src/lib.rs index 412e4580f..f1f8451bf 100644 --- a/sgx_alloc/src/lib.rs +++ b/sgx_alloc/src/lib.rs @@ -32,6 +32,7 @@ #![feature(core_intrinsics)] #![feature(nonnull_slice_from_raw_parts)] #![feature(slice_ptr_get)] +#![allow(clippy::missing_safety_doc)] extern crate alloc; diff --git a/sgx_alloc/src/system.rs b/sgx_alloc/src/system.rs index c6d2167f5..bc7881f15 100644 --- a/sgx_alloc/src/system.rs +++ b/sgx_alloc/src/system.rs @@ -225,7 +225,6 @@ mod platform { use core::alloc::{GlobalAlloc, Layout}; use core::ffi::c_void; use core::ptr; - use libc; unsafe impl GlobalAlloc for System { #[inline] diff --git a/sgx_backtrace/Cargo.toml b/sgx_backtrace/Cargo.toml index 0c4799a75..2ae374673 100644 --- a/sgx_backtrace/Cargo.toml +++ b/sgx_backtrace/Cargo.toml @@ -7,7 +7,7 @@ repository = "https://github.com/apache/teaclave-sgx-sdk" license-file = "LICENSE" documentation = "https://teaclave.apache.org/sgx-sdk-docs/" description = "Rust SGX SDK provides the ability to write Intel SGX applications in Rust Programming Language." -edition = "2018" +edition = "2021" [target.'cfg(not(target_env = "sgx"))'.dependencies] sgx_demangle = { path = "../sgx_demangle" } diff --git a/sgx_backtrace_sys/Cargo.toml b/sgx_backtrace_sys/Cargo.toml index 81645dafb..cb874f5cc 100644 --- a/sgx_backtrace_sys/Cargo.toml +++ b/sgx_backtrace_sys/Cargo.toml @@ -6,7 +6,7 @@ repository = "https://github.com/apache/teaclave-sgx-sdk" license-file = "LICENSE" documentation = "https://teaclave.apache.org/sgx-sdk-docs/" description = "Rust SGX SDK provides the ability to write Intel SGX applications in Rust Programming Language." -edition = "2018" +edition = "2021" [lib] diff --git a/sgx_backtrace_sys/libbacktrace/read.c b/sgx_backtrace_sys/libbacktrace/read.c index 062b109eb..2a193493e 100644 --- a/sgx_backtrace_sys/libbacktrace/read.c +++ b/sgx_backtrace_sys/libbacktrace/read.c @@ -94,6 +94,7 @@ backtrace_get_view(struct backtrace_state* state, int descriptor, if (got < 0) { error_callback(data, "read", error); free(view->base); + sgx_ocfree(); return 0; } diff --git a/sgx_build_helper/Cargo.toml b/sgx_build_helper/Cargo.toml index 6705cd860..7b9ebc942 100644 --- a/sgx_build_helper/Cargo.toml +++ b/sgx_build_helper/Cargo.toml @@ -6,7 +6,7 @@ repository = "https://github.com/apache/teaclave-sgx-sdk" license-file = "LICENSE" documentation = "https://teaclave.apache.org/sgx-sdk-docs/" description = "Rust SGX SDK provides the ability to write Intel SGX applications in Rust Programming Language." -edition = "2018" +edition = "2021" [lib] name = "sgx_build_helper" diff --git a/sgx_cov/Cargo.toml b/sgx_cov/Cargo.toml index d2b41a9b1..2e5d17357 100644 --- a/sgx_cov/Cargo.toml +++ b/sgx_cov/Cargo.toml @@ -6,7 +6,7 @@ repository = "https://github.com/apache/teaclave-sgx-sdk" license-file = "LICENSE" documentation = "https://teaclave.apache.org/sgx-sdk-docs/" description = "Enabling gcov for SGX crates." -edition = "2018" +edition = "2021" [lib] name = "sgx_cov" diff --git a/sgx_crypto_helper/Cargo.toml b/sgx_crypto_helper/Cargo.toml index 9d4a145ab..b2fe6368e 100644 --- a/sgx_crypto_helper/Cargo.toml +++ b/sgx_crypto_helper/Cargo.toml @@ -6,7 +6,7 @@ repository = "https://github.com/apache/teaclave-sgx-sdk" license-file = "LICENSE" documentation = "https://teaclave.apache.org/sgx-sdk-docs/" description = "Rust SGX SDK provides the ability to write Intel SGX applications in Rust Programming Language." -edition = "2018" +edition = "2021" [lib] name = "sgx_crypto_helper" diff --git a/sgx_demangle/Cargo.toml b/sgx_demangle/Cargo.toml index c05799dd7..5f165b2a2 100644 --- a/sgx_demangle/Cargo.toml +++ b/sgx_demangle/Cargo.toml @@ -7,7 +7,7 @@ repository = "https://github.com/apache/teaclave-sgx-sdk" license-file = "LICENSE" documentation = "https://teaclave.apache.org/sgx-sdk-docs/" description = "Rust SGX SDK provides the ability to write Intel SGX applications in Rust Programming Language." -edition = "2018" +edition = "2021" [lib] name = "sgx_demangle" diff --git a/sgx_edl/Cargo.toml b/sgx_edl/Cargo.toml index b46a6dbcd..098860bbf 100644 --- a/sgx_edl/Cargo.toml +++ b/sgx_edl/Cargo.toml @@ -6,7 +6,7 @@ repository = "https://github.com/apache/teaclave-sgx-sdk" license-file = "LICENSE" documentation = "https://teaclave.apache.org/sgx-sdk-docs/" description = "Rust SGX SDK provides the ability to write Intel SGX applications in Rust Programming Language." -edition = "2018" +edition = "2021" include = [ "src/lib.rs", diff --git a/sgx_edl/edl/sgx_file.edl b/sgx_edl/edl/sgx_file.edl index 07fb1eb17..c70ec599a 100644 --- a/sgx_edl/edl/sgx_file.edl +++ b/sgx_edl/edl/sgx_file.edl @@ -27,6 +27,7 @@ enclave { untrusted { int u_open_ocall([out] int *error, [in, string] const char *pathname, int flags); int u_open64_ocall([out] int *error, [in, string] const char *path, int oflag, int mode); + int u_openat_ocall([out] int *error, int dirfd, [in, string] const char *pathname, int flags); int u_fstat_ocall([out] int *error, int fd, [out] struct stat_t *buf); int u_fstat64_ocall([out] int *error, int fd, [out] struct stat64_t *buf); @@ -46,6 +47,7 @@ enclave { int u_fchmod_ocall([out] int *error, int fd, uint32_t mode); int u_unlink_ocall([out] int *error, [in, string] const char *pathname); int u_link_ocall([out] int *error, [in, string] const char *oldpath, [in, string] const char *newpath); + int u_unlinkat_ocall([out] int *error, int dirfd, [in, string] const char *pathname, int flags); int u_linkat_ocall([out] int *error, int olddirfd, [in, string] const char *oldpath, int newdirfd, [in, string] const char *newpath, int flags); int u_rename_ocall([out] int *error, [in, string] const char *oldpath, [in, string] const char *newpath); int u_chmod_ocall([out] int *error, [in, string] const char *path, uint32_t mode); @@ -54,6 +56,7 @@ enclave { char *u_realpath_ocall([out] int *error, [in, string] const char *pathname); int u_mkdir_ocall([out] int *error, [in, string] const char *pathname, uint32_t mode); int u_rmdir_ocall([out] int *error, [in, string] const char *pathname); + void *u_fdopendir_ocall([out] int *error, int fd); void *u_opendir_ocall([out] int *error, [in, string] const char *pathname); int u_readdir64_r_ocall([user_check] void *dirp, [in, out] struct dirent64_t *entry, [out] struct dirent64_t **result); int u_closedir_ocall([out] int *error, [user_check] void *dirp); diff --git a/sgx_libc/BUILD b/sgx_libc/BUILD index 7c5d2265e..0d66538fc 100644 --- a/sgx_libc/BUILD +++ b/sgx_libc/BUILD @@ -4,7 +4,7 @@ rust_library( name = "sgx_libc", srcs = glob(["src/*.rs"]), crate_features = ["align"], - edition = "2018", + edition = "2021", visibility = ["//visibility:public"], deps = ["//sgx_types"], ) diff --git a/sgx_libc/Cargo.toml b/sgx_libc/Cargo.toml index 7441fb53d..7f7f3647b 100644 --- a/sgx_libc/Cargo.toml +++ b/sgx_libc/Cargo.toml @@ -6,7 +6,7 @@ repository = "https://github.com/apache/teaclave-sgx-sdk" license-file = "LICENSE" documentation = "https://teaclave.apache.org/sgx-sdk-docs/" description = "Rust SGX SDK provides the ability to write Intel SGX applications in Rust Programming Language." -edition = "2018" +edition = "2021" [lib] name = "sgx_libc" diff --git a/sgx_libc/src/lib.rs b/sgx_libc/src/lib.rs index d60cd390e..01d2dd1da 100644 --- a/sgx_libc/src/lib.rs +++ b/sgx_libc/src/lib.rs @@ -22,7 +22,10 @@ #![allow(overflowing_literals)] #![allow(non_snake_case)] #![allow(unused_macros)] +#![allow(clippy::cmp_null)] #![allow(unused_assignments)] +#![allow(clippy::missing_safety_doc)] +#![allow(clippy::absurd_extreme_comparisons)] #[macro_use] extern crate alloc; diff --git a/sgx_libc/src/linux/x86_64/mod.rs b/sgx_libc/src/linux/x86_64/mod.rs index 314e805b4..dc55613ba 100644 --- a/sgx_libc/src/linux/x86_64/mod.rs +++ b/sgx_libc/src/linux/x86_64/mod.rs @@ -1418,9 +1418,9 @@ pub const SA_ONSTACK: c_int = 0x08000000; pub const SA_SIGINFO: c_int = 0x00000004; pub const SA_NOCLDWAIT: c_int = 0x00000002; -pub const SIG_DFL: sighandler_t = 0 as sighandler_t; -pub const SIG_IGN: sighandler_t = 1 as sighandler_t; -pub const SIG_ERR: sighandler_t = !0 as sighandler_t; +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 SIGTRAP: c_int = 5; pub const SIGCHLD: c_int = 17; @@ -1536,7 +1536,7 @@ pub unsafe fn CPU_EQUAL(set1: &cpu_set_t, set2: &cpu_set_t) -> bool { #[inline] unsafe fn __sigmask(sig: c_int) -> u64 { - (1 as u64) << (((sig) - 1) % (8 * mem::size_of::()) as i32) + (1_u64) << (((sig) - 1) % (8 * mem::size_of::()) as i32) } #[inline] @@ -1612,7 +1612,7 @@ pub unsafe fn sigismember(set: *const sigset_t, signum: c_int) -> c_int { #[inline] pub const fn CMSG_ALIGN(len: usize) -> usize { - len + mem::size_of::() - 1 & !(mem::size_of::() - 1) + (len + mem::size_of::() - 1) & !(mem::size_of::() - 1) } #[inline] @@ -1620,7 +1620,7 @@ pub unsafe fn CMSG_FIRSTHDR(mhdr: *const msghdr) -> *mut cmsghdr { if (*mhdr).msg_controllen as usize >= mem::size_of::() { (*mhdr).msg_control as *mut cmsghdr } else { - 0 as *mut cmsghdr + ptr::null_mut::() } } @@ -1642,14 +1642,14 @@ 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::() { - return 0 as *mut cmsghdr; + return ptr::null_mut::(); }; 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; if (next.offset(1)) as usize > max || next as usize + CMSG_ALIGN((*next).cmsg_len as usize) > max { - 0 as *mut cmsghdr + ptr::null_mut::() } else { next as *mut cmsghdr } @@ -1666,7 +1666,7 @@ pub unsafe fn major(dev: dev_t) -> c_uint { #[inline] pub unsafe fn minor(dev: dev_t) -> c_uint { let mut minor = 0; - minor |= (dev & 0x00000000000000ff) >> 0; + minor |= dev & 0x00000000000000ff; minor |= (dev & 0x00000ffffff00000) >> 12; minor as c_uint } @@ -1678,7 +1678,7 @@ pub unsafe fn makedev(major: c_uint, minor: c_uint) -> dev_t { let mut dev = 0; dev |= (major & 0x00000fff) << 8; dev |= (major & 0xfffff000) << 32; - dev |= (minor & 0x000000ff) << 0; + dev |= minor & 0x000000ff; dev |= (minor & 0xffffff00) << 12; dev } diff --git a/sgx_libc/src/linux/x86_64/ocall.rs b/sgx_libc/src/linux/x86_64/ocall.rs index 8a17915fe..c6a0c826e 100644 --- a/sgx_libc/src/linux/x86_64/ocall.rs +++ b/sgx_libc/src/linux/x86_64/ocall.rs @@ -111,6 +111,13 @@ extern "C" { oflag: c_int, mode: c_int, ) -> sgx_status_t; + pub fn u_openat_ocall( + result: *mut c_int, + error: *mut c_int, + dirfd: c_int, + pathname: *const c_char, + flags: c_int, + ) -> sgx_status_t; pub fn u_fstat_ocall( result: *mut c_int, error: *mut c_int, @@ -204,6 +211,13 @@ extern "C" { oldpath: *const c_char, newpath: *const c_char, ) -> sgx_status_t; + pub fn u_unlinkat_ocall( + result: *mut c_int, + error: *mut c_int, + dirfd: c_int, + pathname: *const c_char, + flags: c_int, + ) -> sgx_status_t; pub fn u_linkat_ocall( result: *mut c_int, error: *mut c_int, @@ -254,6 +268,7 @@ extern "C" { error: *mut c_int, pathname: *const c_char, ) -> sgx_status_t; + pub fn u_fdopendir_ocall(result: *mut *mut DIR, error: *mut c_int, fd: c_int) -> sgx_status_t; pub fn u_opendir_ocall( result: *mut *mut DIR, error: *mut c_int, @@ -684,14 +699,14 @@ pub unsafe fn mmap( if result as isize != -1 { if sgx_is_outside_enclave(result, length) == 0 { set_errno(ESGX); - result = -1 as isize as *mut c_void; + result = -1_isize as *mut c_void; } } else { set_errno(error); } } else { set_errno(ESGX); - result = -1 as isize as *mut c_void; + result = -1_isize as *mut c_void; } result } @@ -1008,6 +1023,29 @@ pub unsafe fn open64(path: *const c_char, oflag: c_int, mode: c_int) -> c_int { result } +pub unsafe fn openat(dirfd: c_int, pathname: *const c_char, flags: c_int) -> c_int { + let mut result: c_int = 0; + let mut error: c_int = 0; + + let status = u_openat_ocall( + &mut result as *mut c_int, + &mut error as *mut c_int, + dirfd, + pathname, + flags, + ); + + if status == sgx_status_t::SGX_SUCCESS { + if result == -1 { + set_errno(error); + } + } else { + set_errno(ESGX); + result = -1; + } + result +} + pub unsafe fn fstat(fd: c_int, buf: *mut stat) -> c_int { let mut result: c_int = 0; let mut error: c_int = 0; @@ -1346,6 +1384,29 @@ pub unsafe fn link(oldpath: *const c_char, newpath: *const c_char) -> c_int { result } +pub unsafe fn unlinkat(dirfd: c_int, pathname: *const c_char, flags: c_int) -> c_int { + let mut result: c_int = 0; + let mut error: c_int = 0; + + let status = u_unlinkat_ocall( + &mut result as *mut c_int, + &mut error as *mut c_int, + dirfd, + pathname, + flags, + ); + + if status == sgx_status_t::SGX_SUCCESS { + if result == -1 { + set_errno(error); + } + } else { + set_errno(ESGX); + result = -1; + } + result +} + pub unsafe fn linkat( olddirfd: c_int, oldpath: *const c_char, @@ -1528,6 +1589,23 @@ pub unsafe fn rmdir(pathname: *const c_char) -> c_int { result } +pub unsafe fn fdopendir(fd: c_int) -> *mut DIR { + let mut result: *mut DIR = ptr::null_mut(); + let mut error: c_int = 0; + + let status = u_fdopendir_ocall(&mut result as *mut *mut DIR, &mut error as *mut c_int, fd); + + if status == sgx_status_t::SGX_SUCCESS { + if result.is_null() { + set_errno(error); + } + } else { + set_errno(ESGX); + result = ptr::null_mut(); + } + result +} + pub unsafe fn opendir(pathname: *const c_char) -> *mut DIR { let mut result: *mut DIR = ptr::null_mut(); let mut error: c_int = 0; @@ -2425,7 +2503,7 @@ pub unsafe fn accept(sockfd: c_int, addr: *mut sockaddr, addrlen: *mut socklen_t let mut result: c_int = 0; let mut error: c_int = 0; let len_in: socklen_t = if !addrlen.is_null() { *addrlen } else { 0 }; - let mut len_out: socklen_t = 0 as socklen_t; + let mut len_out: socklen_t = 0; let status = u_accept_ocall( &mut result as *mut c_int, &mut error as *mut c_int, @@ -2459,7 +2537,7 @@ pub unsafe fn accept4( let mut result: c_int = 0; let mut error: c_int = 0; let len_in: socklen_t = if !addrlen.is_null() { *addrlen } else { 0 }; - let mut len_out: socklen_t = 0 as socklen_t; + let mut len_out: socklen_t = 0; let status = u_accept4_ocall( &mut result as *mut c_int, &mut error as *mut c_int, @@ -2781,7 +2859,7 @@ pub unsafe fn recvfrom( let mut result: ssize_t = 0; let mut error: c_int = 0; let len_in: socklen_t = if !addrlen.is_null() { *addrlen } else { 0 }; - let mut len_out: socklen_t = 0 as socklen_t; + let mut len_out: socklen_t = 0; if buf.is_null() || sgx_is_within_enclave(buf, len) == 0 { set_errno(EINVAL); @@ -3012,7 +3090,7 @@ pub unsafe fn getsockopt( let mut result: c_int = 0; let mut error: c_int = 0; let len_in: socklen_t = if !optlen.is_null() { *optlen } else { 0 }; - let mut len_out: socklen_t = 0 as socklen_t; + let mut len_out: socklen_t = 0; let status = u_getsockopt_ocall( &mut result as *mut c_int, @@ -3044,7 +3122,7 @@ pub unsafe fn getpeername(sockfd: c_int, address: *mut sockaddr, addrlen: *mut s let mut result: c_int = 0; let mut error: c_int = 0; let len_in: socklen_t = if !addrlen.is_null() { *addrlen } else { 0 }; - let mut len_out: socklen_t = 0 as socklen_t; + let mut len_out: socklen_t = 0; let status = u_getpeername_ocall( &mut result as *mut c_int, &mut error as *mut c_int, @@ -3073,7 +3151,7 @@ pub unsafe fn getsockname(sockfd: c_int, address: *mut sockaddr, addrlen: *mut s let mut result: c_int = 0; let mut error: c_int = 0; let len_in: socklen_t = if !addrlen.is_null() { *addrlen } else { 0 }; - let mut len_out: socklen_t = 0 as socklen_t; + let mut len_out: socklen_t = 0; let status = u_getsockname_ocall( &mut result as *mut c_int, &mut error as *mut c_int, @@ -3219,7 +3297,7 @@ pub unsafe fn getaddrinfo( cur_ptr = cur.ai_next; } - if addrinfo_vec.len() > 0 { + if !addrinfo_vec.is_empty() { if result == 0 { for i in 0..addrinfo_vec.len() - 1 { addrinfo_vec[i].ai_next = addrinfo_vec[i + 1].as_mut() as *mut addrinfo; diff --git a/sgx_no_tstd/Cargo.toml b/sgx_no_tstd/Cargo.toml index 213e6a6e7..914b1f68e 100644 --- a/sgx_no_tstd/Cargo.toml +++ b/sgx_no_tstd/Cargo.toml @@ -7,7 +7,7 @@ repository = "https://github.com/apache/teaclave-sgx-sdk" license-file = "LICENSE" documentation = "https://teaclave.apache.org/sgx-sdk-docs/" description = "Rust SGX SDK provides the ability to write Intel SGX applications in Rust Programming Language." -edition = "2018" +edition = "2021" [lib] name = "sgx_no_tstd" diff --git a/sgx_no_tstd/build.rs b/sgx_no_tstd/build.rs index e1d22fac6..c529feebf 100644 --- a/sgx_no_tstd/build.rs +++ b/sgx_no_tstd/build.rs @@ -15,8 +15,6 @@ // specific language governing permissions and limitations // under the License. -#![feature(available_parallelism)] - extern crate sgx_build_helper as build_helper; use build_helper::{native_lib_boilerplate, run}; diff --git a/sgx_panic_abort/Cargo.toml b/sgx_panic_abort/Cargo.toml index d8084b0b3..0e017799a 100644 --- a/sgx_panic_abort/Cargo.toml +++ b/sgx_panic_abort/Cargo.toml @@ -6,7 +6,7 @@ repository = "https://github.com/apache/teaclave-sgx-sdk" license-file = "LICENSE" documentation = "https://dingelish.github.io/" description = "Rust SGX SDK provides the ability to write Intel SGX applications in Rust Programming Language." -edition = "2018" +edition = "2021" [lib] test = false diff --git a/sgx_panic_unwind/Cargo.toml b/sgx_panic_unwind/Cargo.toml index df1a35c12..9f654bec4 100644 --- a/sgx_panic_unwind/Cargo.toml +++ b/sgx_panic_unwind/Cargo.toml @@ -6,7 +6,7 @@ repository = "https://github.com/apache/teaclave-sgx-sdk" license-file = "LICENSE" documentation = "https://dingelish.github.io/" description = "Rust SGX SDK provides the ability to write Intel SGX applications in Rust Programming Language." -edition = "2018" +edition = "2021" [lib] test = false diff --git a/sgx_panic_unwind/src/dwarf/eh.rs b/sgx_panic_unwind/src/dwarf/eh.rs index 7394feab8..6c59df325 100644 --- a/sgx_panic_unwind/src/dwarf/eh.rs +++ b/sgx_panic_unwind/src/dwarf/eh.rs @@ -138,7 +138,11 @@ fn interpret_cs_action(cs_action: u64, lpad: usize) -> EHAction { #[inline] fn round_up(unrounded: usize, align: usize) -> Result { - if align.is_power_of_two() { Ok((unrounded + align - 1) & !(align - 1)) } else { Err(()) } + if align.is_power_of_two() { + Ok((unrounded + align - 1) & !(align - 1)) + } else { + Err(()) + } } unsafe fn read_encoded_pointer( diff --git a/sgx_panic_unwind/src/gcc.rs b/sgx_panic_unwind/src/gcc.rs index 4f507f58c..56d95ea3b 100644 --- a/sgx_panic_unwind/src/gcc.rs +++ b/sgx_panic_unwind/src/gcc.rs @@ -87,7 +87,7 @@ pub unsafe fn cleanup(ptr: *mut u8) -> Box { // determine whether the exception was thrown by their own runtime. fn rust_exception_class() -> uw::_Unwind_Exception_Class { // M O Z \0 R U S T -- vendor, language - 0x4d4f5a_00_52555354 + 0x4d4f_5a00_5255_5354 } // Register ids were lifted from LLVM's TargetLowering::getExceptionPointerRegister() @@ -122,16 +122,14 @@ unsafe extern "C" fn rust_eh_personality_impl( }; if actions as i32 & uw::_UA_SEARCH_PHASE as i32 != 0 { match eh_action { - EHAction::None | - EHAction::Cleanup(_) => uw::_URC_CONTINUE_UNWIND, + 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) => { + 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); @@ -167,4 +165,3 @@ unsafe fn find_eh_action(context: *mut uw::_Unwind_Context) -> Result *mut (dyn Any + Send + 'static) { Box::into_raw(imp::cleanup(payload)) } +/// # Safety // Entry point for raising an exception, just delegates to the platform-specific // implementation. #[rustc_std_internal_symbol] diff --git a/sgx_rand/Cargo.toml b/sgx_rand/Cargo.toml index 09a75454c..1a942d538 100644 --- a/sgx_rand/Cargo.toml +++ b/sgx_rand/Cargo.toml @@ -6,7 +6,7 @@ repository = "https://github.com/apache/teaclave-sgx-sdk" license-file = "LICENSE" documentation = "https://teaclave.apache.org/sgx-sdk-docs/" description = "Rust SGX SDK provides the ability to write Intel SGX applications in Rust Programming Language." -edition = "2018" +edition = "2021" [lib] name = "sgx_rand" diff --git a/sgx_rand_derive/Cargo.toml b/sgx_rand_derive/Cargo.toml index be5026c1f..0b77310a9 100644 --- a/sgx_rand_derive/Cargo.toml +++ b/sgx_rand_derive/Cargo.toml @@ -6,7 +6,7 @@ repository = "https://github.com/apache/teaclave-sgx-sdk" license-file = "LICENSE" documentation = "https://teaclave.apache.org/sgx-sdk-docs/" description = "Rust SGX SDK provides the ability to write Intel SGX applications in Rust Programming Language." -edition = "2018" +edition = "2021" [lib] name = "sgx_rand_derive" diff --git a/sgx_serialize/Cargo.toml b/sgx_serialize/Cargo.toml index f415fa56c..665244f8f 100644 --- a/sgx_serialize/Cargo.toml +++ b/sgx_serialize/Cargo.toml @@ -6,7 +6,7 @@ repository = "https://github.com/apache/teaclave-sgx-sdk" license-file = "LICENSE" documentation = "https://teaclave.apache.org/sgx-sdk-docs/" description = "Rust SGX SDK provides the ability to write Intel SGX applications in Rust Programming Language." -edition = "2018" +edition = "2021" [lib] name = "sgx_serialize" diff --git a/sgx_serialize_derive/Cargo.toml b/sgx_serialize_derive/Cargo.toml index 961900541..5ce9db30b 100644 --- a/sgx_serialize_derive/Cargo.toml +++ b/sgx_serialize_derive/Cargo.toml @@ -6,7 +6,7 @@ repository = "https://github.com/apache/teaclave-sgx-sdk" license-file = "LICENSE" documentation = "https://teaclave.apache.org/sgx-sdk-docs/" description = "Rust SGX SDK provides the ability to write Intel SGX applications in Rust Programming Language." -edition = "2018" +edition = "2021" [lib] name = "sgx_serialize_derive" diff --git a/sgx_serialize_derive_internals/Cargo.toml b/sgx_serialize_derive_internals/Cargo.toml index b499f09ba..239cd3c0e 100644 --- a/sgx_serialize_derive_internals/Cargo.toml +++ b/sgx_serialize_derive_internals/Cargo.toml @@ -6,7 +6,7 @@ repository = "https://github.com/apache/teaclave-sgx-sdk" license-file = "LICENSE" documentation = "https://teaclave.apache.org/sgx-sdk-docs/" description = "Rust SGX SDK provides the ability to write Intel SGX applications in Rust Programming Language." -edition = "2018" +edition = "2021" [lib] name = "sgx_serialize_derive_internals" diff --git a/sgx_signal/Cargo.toml b/sgx_signal/Cargo.toml index 0db899263..7ba3f472f 100644 --- a/sgx_signal/Cargo.toml +++ b/sgx_signal/Cargo.toml @@ -6,7 +6,7 @@ repository = "https://github.com/apache/teaclave-sgx-sdk" license-file = "LICENSE" documentation = "https://teaclave.apache.org/sgx-sdk-docs/" description = "Rust SGX SDK provides the ability to write Intel SGX applications in Rust Programming Language." -edition = "2018" +edition = "2021" [lib] name = "sgx_signal" diff --git a/sgx_signal/src/exception.rs b/sgx_signal/src/exception.rs index 0f9f7a868..daa541ed2 100644 --- a/sgx_signal/src/exception.rs +++ b/sgx_signal/src/exception.rs @@ -46,7 +46,7 @@ impl From for i32 { } #[allow(unknown_lints, bare_trait_objects)] -type ExceptionHandler = Fn(&mut sgx_exception_info_t) -> ContinueType + Send + Sync; +type ExceptionHandler = dyn Fn(&mut sgx_exception_info_t) -> ContinueType + Send + Sync; #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] pub struct HandlerId(NonZeroU64); diff --git a/sgx_tcrypto/Cargo.toml b/sgx_tcrypto/Cargo.toml index 2d010cbed..379b830bb 100644 --- a/sgx_tcrypto/Cargo.toml +++ b/sgx_tcrypto/Cargo.toml @@ -6,7 +6,7 @@ repository = "https://github.com/apache/teaclave-sgx-sdk" license-file = "LICENSE" documentation = "https://teaclave.apache.org/sgx-sdk-docs/" description = "Rust SGX SDK provides the ability to write Intel SGX applications in Rust Programming Language." -edition = "2018" +edition = "2021" [lib] name = "sgx_tcrypto" diff --git a/sgx_tcrypto_helper/Cargo.toml b/sgx_tcrypto_helper/Cargo.toml index e85af176f..b24f01c6c 100644 --- a/sgx_tcrypto_helper/Cargo.toml +++ b/sgx_tcrypto_helper/Cargo.toml @@ -6,7 +6,7 @@ repository = "https://github.com/apache/teaclave-sgx-sdk" license-file = "LICENSE" documentation = "https://teaclave.apache.org/sgx-sdk-docs/" description = "Rust SGX SDK provides the ability to write Intel SGX applications in Rust Programming Language." -edition = "2018" +edition = "2021" [lib] name = "sgx_tcrypto_helper" diff --git a/sgx_tcrypto_helper/x86_64-unknown-linux-sgx.json b/sgx_tcrypto_helper/x86_64-unknown-linux-sgx.json deleted file mode 100644 index 69b38be21..000000000 --- a/sgx_tcrypto_helper/x86_64-unknown-linux-sgx.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "arch": "x86_64", - "cpu": "x86-64", - "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128", - "dynamic-linking": true, - "env": "sgx", - "exe-allocation-crate": "alloc_system", - "executables": true, - "has-elf-tls": true, - "has-rpath": true, - "linker-flavor": "gcc", - "linker-is-gnu": true, - "llvm-target": "x86_64-unknown-linux-gnu", - "max-atomic-width": 64, - "os": "linux", - "position-independent-executables": true, - "pre-link-args": { - "gcc": [ - "-Wl,--as-needed", - "-Wl,-z,noexecstack", - "-m64" - ] - }, - "relro-level": "full", - "stack-probes": { - "kind": "inline-or-call", - "min-llvm-version-for-inline": [ - 11, - 0, - 1 - ] - }, - "target-c-int-width": "32", - "target-endian": "little", - "target-family": "unix", - "target-pointer-width": "64", - "vendor": "mesalock" -} diff --git a/sgx_tdh/Cargo.toml b/sgx_tdh/Cargo.toml index cf3052463..f65a59475 100644 --- a/sgx_tdh/Cargo.toml +++ b/sgx_tdh/Cargo.toml @@ -6,7 +6,7 @@ repository = "https://github.com/apache/teaclave-sgx-sdk" license-file = "LICENSE" documentation = "https://teaclave.apache.org/sgx-sdk-docs/" description = "Rust SGX SDK provides the ability to write Intel SGX applications in Rust Programming Language." -edition = "2018" +edition = "2021" [lib] name = "sgx_tdh" diff --git a/sgx_tkey_exchange/Cargo.toml b/sgx_tkey_exchange/Cargo.toml index fae39e226..f55cc8edf 100644 --- a/sgx_tkey_exchange/Cargo.toml +++ b/sgx_tkey_exchange/Cargo.toml @@ -6,7 +6,7 @@ repository = "https://github.com/apache/teaclave-sgx-sdk" license-file = "LICENSE" documentation = "https://teaclave.apache.org/sgx-sdk-docs/" description = "Rust SGX SDK provides the ability to write Intel SGX applications in Rust Programming Language." -edition = "2018" +edition = "2021" [lib] name = "sgx_tkey_exchange" diff --git a/sgx_tprotected_fs/Cargo.toml b/sgx_tprotected_fs/Cargo.toml index 480896807..3978625ab 100644 --- a/sgx_tprotected_fs/Cargo.toml +++ b/sgx_tprotected_fs/Cargo.toml @@ -6,7 +6,7 @@ repository = "https://github.com/apache/teaclave-sgx-sdk" license-file = "LICENSE" documentation = "https://teaclave.apache.org/sgx-sdk-docs/" description = "Rust SGX SDK provides the ability to write Intel SGX applications in Rust Programming Language." -edition = "2018" +edition = "2021" [lib] name = "sgx_tprotected_fs" diff --git a/sgx_trts/BUILD b/sgx_trts/BUILD index 4027e9e96..9dec8b668 100644 --- a/sgx_trts/BUILD +++ b/sgx_trts/BUILD @@ -3,7 +3,7 @@ load("@io_bazel_rules_rust//rust:rust.bzl", "rust_library") rust_library( name = "sgx_trts", srcs = glob(["src/*.rs"]), - edition = "2018", + edition = "2021", visibility = ["//visibility:public"], deps = [ "//sgx_libc", diff --git a/sgx_trts/Cargo.toml b/sgx_trts/Cargo.toml index 79a0919f1..d43b81aaa 100644 --- a/sgx_trts/Cargo.toml +++ b/sgx_trts/Cargo.toml @@ -6,7 +6,7 @@ repository = "https://github.com/apache/teaclave-sgx-sdk" license-file = "LICENSE" documentation = "https://teaclave.apache.org/sgx-sdk-docs/" description = "Rust SGX SDK provides the ability to write Intel SGX applications in Rust Programming Language." -edition = "2018" +edition = "2021" [lib] name = "sgx_trts" diff --git a/sgx_trts/src/c_str.rs b/sgx_trts/src/c_str.rs index 329b96fe7..da052e16d 100644 --- a/sgx_trts/src/c_str.rs +++ b/sgx_trts/src/c_str.rs @@ -366,7 +366,6 @@ impl FromVecWithNulError { /// Basic usage: /// /// ``` - /// #![feature(cstring_from_vec_with_nul)] /// use std::ffi::CString; /// /// // Some invalid bytes in a vector @@ -443,38 +442,61 @@ impl CString { /// internal 0 byte. The [`NulError`] returned will contain the bytes as well as /// the position of the nul byte. pub fn new>>(t: T) -> Result { - trait SpecIntoVec { - fn into_vec(self) -> Vec; + trait SpecNewImpl { + fn spec_new_impl(self) -> Result; } - impl>> SpecIntoVec for T { - default fn into_vec(self) -> Vec { - self.into() + + impl>> SpecNewImpl for T { + default fn spec_new_impl(self) -> Result { + let bytes: Vec = 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. - impl SpecIntoVec for &'_ [u8] { - fn into_vec(self) -> Vec { - let mut v = Vec::with_capacity(self.len() + 1); - v.extend(self); - v + + // Specialization for avoiding reallocation + #[inline(always)] // Without that it is not inlined into specializations + fn spec_new_impl_bytes(bytes: &[u8]) -> Result { + // 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 SpecIntoVec for &'_ str { - fn into_vec(self) -> Vec { - let mut v = Vec::with_capacity(self.len() + 1); - v.extend(self.as_bytes()); - v + + impl SpecNewImpl for &'_ [u8] { + fn spec_new_impl(self) -> Result { + spec_new_impl_bytes(self) } } - Self::_new(SpecIntoVec::into_vec(t)) - } + impl SpecNewImpl for &'_ str { + fn spec_new_impl(self) -> Result { + spec_new_impl_bytes(self.as_bytes()) + } + } - fn _new(bytes: Vec) -> Result { - match memchr::memchr(0, &bytes) { - Some(i) => Err(NulError(i, bytes)), - None => Ok(unsafe { CString::from_vec_unchecked(bytes) }), + impl SpecNewImpl for &'_ mut [u8] { + fn spec_new_impl(self) -> Result { + spec_new_impl_bytes(self) + } } + + t.spec_new_impl() } /// Creates a C-compatible string by consuming a byte vector, @@ -497,10 +519,15 @@ impl CString { /// } /// ``` #[must_use] - pub unsafe fn from_vec_unchecked(mut v: Vec) -> CString { + pub unsafe fn from_vec_unchecked(v: Vec) -> Self { + debug_assert!(memchr::memchr(0, &v).is_none()); + Self::_from_vec_unchecked(v) + } + + unsafe fn _from_vec_unchecked(mut v: Vec) -> Self { v.reserve_exact(1); v.push(0); - CString { + Self { inner: v.into_boxed_slice(), } } @@ -620,11 +647,10 @@ impl CString { /// 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::from_utf8(self.into_bytes()).map_err(|e| IntoStringError { error: e.utf8_error(), - inner: unsafe { CString::from_vec_unchecked(e.into_bytes()) }, + inner: unsafe { Self::_from_vec_unchecked(e.into_bytes()) }, }) } @@ -766,7 +792,6 @@ impl CString { /// # Example /// /// ``` - /// #![feature(cstring_from_vec_with_nul)] /// use std::ffi::CString; /// assert_eq!( /// unsafe { CString::from_vec_with_nul_unchecked(b"abc\0".to_vec()) }, @@ -775,6 +800,11 @@ impl CString { /// ``` #[must_use] pub unsafe fn from_vec_with_nul_unchecked(v: Vec) -> 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) -> Self { Self { inner: v.into_boxed_slice(), } @@ -796,7 +826,6 @@ impl CString { /// when called without the ending nul byte. /// /// ``` - /// #![feature(cstring_from_vec_with_nul)] /// use std::ffi::CString; /// assert_eq!( /// CString::from_vec_with_nul(b"abc\0".to_vec()) @@ -808,7 +837,6 @@ impl CString { /// An incorrectly formatted [`Vec`] will produce an error. /// /// ``` - /// #![feature(cstring_from_vec_with_nul)] /// use std::ffi::{CString, FromVecWithNulError}; /// // Interior nul byte /// let _: FromVecWithNulError = CString::from_vec_with_nul(b"a\0bc".to_vec()).unwrap_err(); @@ -821,7 +849,7 @@ impl CString { 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) }) + Ok(unsafe { Self::_from_vec_with_nul_unchecked(v) }) } Some(nul_pos) => Err(FromVecWithNulError { error_kind: FromBytesWithNulErrorKind::InteriorNul(nul_pos), @@ -852,7 +880,7 @@ impl ops::Deref for CString { #[inline] fn deref(&self) -> &CStr { - unsafe { CStr::from_bytes_with_nul_unchecked(self.as_bytes_with_nul()) } + unsafe { CStr::_from_bytes_with_nul_unchecked(self.as_bytes_with_nul()) } } } @@ -909,6 +937,8 @@ impl Borrow for CString { } impl<'a> From> 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() @@ -916,6 +946,8 @@ impl<'a> From> for CString { } impl From<&CStr> for Box { + /// Converts a `&CStr` into a `Box`, + /// by copying the contents into a newly allocated [`Box`]. fn from(s: &CStr) -> Box { let boxed: Box<[u8]> = Box::from(s.to_bytes_with_nul()); unsafe { Box::from_raw(Box::into_raw(boxed) as *mut CStr) } @@ -923,6 +955,8 @@ impl From<&CStr> for Box { } impl From> for Box { + /// Converts a `Cow<'a, CStr>` into a `Box`, + /// by copying the contents if they are borrowed. #[inline] fn from(cow: Cow<'_, CStr>) -> Box { match cow { @@ -956,7 +990,7 @@ impl From> for CString { }; // SAFETY: `v` cannot contain null bytes, given the type-level // invariant of `NonZeroU8`. - CString::from_vec_unchecked(v) + Self::_from_vec_unchecked(v) } } } @@ -1001,7 +1035,8 @@ impl<'a> From<&'a CString> for Cow<'a, CStr> { } impl From for Arc { - /// Converts a [`CString`] into an [Arc]<[CStr]> without copying or allocating. + /// Converts a [`CString`] into an [Arc]<[CStr]> by moving the [`CString`] + /// data into a new [`Arc`] buffer. #[inline] fn from(s: CString) -> Arc { let arc: Arc<[u8]> = Arc::from(s.into_inner()); @@ -1010,6 +1045,8 @@ impl From for Arc { } impl From<&CStr> for Arc { + /// Converts a `&CStr` into a `Arc`, + /// by copying the contents into a newly allocated [`Arc`]. #[inline] fn from(s: &CStr) -> Arc { let arc: Arc<[u8]> = Arc::from(s.to_bytes_with_nul()); @@ -1018,7 +1055,8 @@ impl From<&CStr> for Arc { } impl From for Rc { - /// Converts a [`CString`] into an [Rc]<[CStr]> without copying or allocating. + /// Converts a [`CString`] into an [Rc]<[CStr]> by moving the [`CString`] + /// data into a new [`Arc`] buffer. #[inline] fn from(s: CString) -> Rc { let rc: Rc<[u8]> = Rc::from(s.into_inner()); @@ -1027,6 +1065,8 @@ impl From for Rc { } impl From<&CStr> for Rc { + /// Converts a `&CStr` into a `Rc`, + /// by copying the contents into a newly allocated [`Rc`]. #[inline] fn from(s: &CStr) -> Rc { let rc: Rc<[u8]> = Rc::from(s.to_bytes_with_nul()); @@ -1146,7 +1186,7 @@ impl CStr { // 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; - CStr::from_bytes_with_nul_unchecked(slice::from_raw_parts(ptr, len as usize + 1)) + Self::_from_bytes_with_nul_unchecked(slice::from_raw_parts(ptr, len as usize + 1)) } /// Creates a C string wrapper from a byte slice. @@ -1181,15 +1221,16 @@ impl 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<&CStr, FromBytesWithNulError> { + pub fn from_bytes_with_nul(bytes: &[u8]) -> Result<&Self, FromBytesWithNulError> { let nul_pos = memchr::memchr(0, bytes); - if let Some(nul_pos) = nul_pos { - if nul_pos + 1 != bytes.len() { - return Err(FromBytesWithNulError::interior_nul(nul_pos)); + 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) }) } - Ok(unsafe { CStr::from_bytes_with_nul_unchecked(bytes) }) - } else { - Err(FromBytesWithNulError::not_nul_terminated()) + Some(nul_pos) => Err(FromBytesWithNulError::interior_nul(nul_pos)), + None => Err(FromBytesWithNulError::not_nul_terminated()), } } @@ -1213,12 +1254,19 @@ impl CStr { #[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 CStr) + &*(bytes as *const [u8] as *const Self) } /// Returns the inner pointer to this C string. @@ -1450,6 +1498,7 @@ impl ToOwned for CStr { } impl From<&CStr> for CString { + /// Copies the contents of the `&CStr` into a newly allocated `CString`. fn from(s: &CStr) -> CString { s.to_owned() } @@ -1473,7 +1522,7 @@ impl ops::Index> for CStr { // 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..]) } + unsafe { CStr::_from_bytes_with_nul_unchecked(&bytes[index.start..]) } } else { panic!( "index out of bounds: the len is {} but the index is {}", diff --git a/sgx_trts/src/enclave.rs b/sgx_trts/src/enclave.rs index 675949184..76f510fe6 100644 --- a/sgx_trts/src/enclave.rs +++ b/sgx_trts/src/enclave.rs @@ -562,6 +562,7 @@ pub fn rsgx_get_tcs_max_num() -> u32 { unsafe { g_global_data.tcs_max_num as u32 } } +#[allow(clippy::collapsible_if, clippy::nonminimal_bool)] pub fn rsgx_get_tcs_num() -> (u32, u32, u32) { let gd = unsafe { let p = rsgx_get_global_data(); diff --git a/sgx_trts/src/lib.rs b/sgx_trts/src/lib.rs index 15be2d4a2..7659bdc30 100644 --- a/sgx_trts/src/lib.rs +++ b/sgx_trts/src/lib.rs @@ -64,17 +64,17 @@ #![no_std] #![cfg_attr(target_env = "sgx", feature(rustc_private))] -#![allow(incomplete_features)] #![feature(allocator_api)] -#![feature(asm)] -#![feature(const_raw_ptr_deref)] -#![allow(non_camel_case_types)] -#![allow(non_upper_case_globals)] -#![allow(non_snake_case)] #![feature(specialization)] #![feature(vec_into_raw_parts)] #![feature(toowned_clone_into)] #![feature(rustc_attrs)] +#![allow(incomplete_features)] +#![allow(non_camel_case_types)] +#![allow(non_upper_case_globals)] +#![allow(non_snake_case)] +#![allow(clippy::missing_safety_doc)] +#![allow(clippy::derive_hash_xor_eq)] #[cfg(target_env = "sgx")] extern crate sgx_types; diff --git a/sgx_trts/src/veh.rs b/sgx_trts/src/veh.rs index 88ae6873b..19b7342d4 100644 --- a/sgx_trts/src/veh.rs +++ b/sgx_trts/src/veh.rs @@ -107,6 +107,7 @@ pub fn rsgx_register_exception_handler( /// /// The exception handler was not unregistered (not a valid pointer, handler not found). /// +#[allow(clippy::not_unsafe_ptr_arg_deref)] pub fn rsgx_unregister_exception_handler(handle: exception_handle) -> bool { let ret = unsafe { sgx_unregister_exception_handler(handle) }; ret != 0 diff --git a/sgx_tse/Cargo.toml b/sgx_tse/Cargo.toml index 2ece5880a..2ba59fdcd 100644 --- a/sgx_tse/Cargo.toml +++ b/sgx_tse/Cargo.toml @@ -6,7 +6,7 @@ repository = "https://github.com/apache/teaclave-sgx-sdk" license-file = "LICENSE" documentation = "https://teaclave.apache.org/sgx-sdk-docs/" description = "Rust SGX SDK provides the ability to write Intel SGX applications in Rust Programming Language." -edition = "2018" +edition = "2021" [lib] name = "sgx_tse" diff --git a/sgx_tseal/Cargo.toml b/sgx_tseal/Cargo.toml index 180edd011..45cb55a4c 100644 --- a/sgx_tseal/Cargo.toml +++ b/sgx_tseal/Cargo.toml @@ -6,7 +6,7 @@ repository = "https://github.com/apache/teaclave-sgx-sdk" license-file = "LICENSE" documentation = "https://teaclave.apache.org/sgx-sdk-docs/" description = "Rust SGX SDK provides the ability to write Intel SGX applications in Rust Programming Language." -edition = "2018" +edition = "2021" [lib] name = "sgx_tseal" diff --git a/sgx_tstd/Cargo.toml b/sgx_tstd/Cargo.toml index 2d27a6e38..cac5bd6b0 100644 --- a/sgx_tstd/Cargo.toml +++ b/sgx_tstd/Cargo.toml @@ -6,7 +6,7 @@ repository = "https://github.com/apache/teaclave-sgx-sdk" license-file = "LICENSE" documentation = "https://teaclave.apache.org/sgx-sdk-docs/" description = "Rust SGX SDK provides the ability to write Intel SGX applications in Rust Programming Language." -edition = "2018" +edition = "2021" [lib] name = "sgx_tstd" diff --git a/sgx_tstd/hashbrown/CHANGELOG.md b/sgx_tstd/hashbrown/CHANGELOG.md index c88d3e0fe..4637bd006 100644 --- a/sgx_tstd/hashbrown/CHANGELOG.md +++ b/sgx_tstd/hashbrown/CHANGELOG.md @@ -2,11 +2,41 @@ All notable changes to this project will be documented in this file. -The format is based on [Keep a Changelog](http://keepachangelog.com/) -and this project adheres to [Semantic Versioning](http://semver.org/). +The format is based on [Keep a Changelog](https://keepachangelog.com/) +and this project adheres to [Semantic Versioning](https://semver.org/). ## [Unreleased] +## [v0.12.0] - 2022-01-17 + +## Added + +- Added `From<[T; N]>` and `From<[(K, V); N]>` for `HashSet` and `HashMap` respectively. (#297) +- Added an `allocator()` getter to HashMap and HashSet. (#257) +- Added `insert_unique_unchecked` to `HashMap` and `HashSet`. (#293) +- Added `into_keys` and `into_values` to HashMap. (#295) +- Implement `From` on `HashSet` and `HashMap`. (#298) +- Added `entry_ref` API to `HashMap`. (#201) + +## Changed + +- Bumped minimum Rust version to 1.56.1 and edition to 2021. +- Use u64 for the GroupWord on WebAssembly. (#271) +- Optimized `find`. (#279) +- Made rehashing and resizing less generic to reduce compilation time. (#282) +- Inlined small functions. (#283) +- Use `BuildHasher::hash_one` when `feature = "nightly"` is enabled. (#292) +- Relaxed the bounds on `Debug` for `HashSet`. (#296) +- Rename `get_each_mut` to `get_many_mut` and align API with the stdlib. (#291) +- Don't hash the key when searching in an empty table. (#305) + +## Fixed + +- Guard against allocations exceeding isize::MAX. (#268) +- Made `RawTable::insert_no_grow` unsafe. (#254) +- Inline `static_empty`. (#280) +- Fixed trait bounds on Send/Sync impls. (#303) + ## [v0.11.2] - 2021-03-25 ## Fixed @@ -307,7 +337,8 @@ This release was _yanked_ due to a breaking change for users of `no-default-feat - Initial release -[Unreleased]: https://github.com/rust-lang/hashbrown/compare/v0.11.2...HEAD +[Unreleased]: https://github.com/rust-lang/hashbrown/compare/v0.12.0...HEAD +[v0.12.0]: https://github.com/rust-lang/hashbrown/compare/v0.11.2...v0.12.0 [v0.11.2]: https://github.com/rust-lang/hashbrown/compare/v0.11.1...v0.11.2 [v0.11.1]: https://github.com/rust-lang/hashbrown/compare/v0.11.0...v0.11.1 [v0.11.0]: https://github.com/rust-lang/hashbrown/compare/v0.10.0...v0.11.0 diff --git a/sgx_tstd/hashbrown/Cargo.toml b/sgx_tstd/hashbrown/Cargo.toml index 7bcb6ba31..6927577ae 100644 --- a/sgx_tstd/hashbrown/Cargo.toml +++ b/sgx_tstd/hashbrown/Cargo.toml @@ -1,85 +1,63 @@ -# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO -# -# When uploading crates to the registry Cargo will automatically -# "normalize" Cargo.toml files for maximal compatibility -# with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g., crates.io) dependencies -# -# If you believe there's an error in this file please file an -# issue against the rust-lang/cargo repository. If you're -# editing this file be aware that the upstream Cargo.toml -# will likely look very different (and much more reasonable) - [package] -edition = "2018" name = "hashbrown_tstd" -version = "0.11.2" +version = "0.12.0" authors = ["Amanieu d'Antras "] -exclude = [".travis.yml", "bors.toml", "/ci/*"] description = "A Rust port of Google's SwissTable hash map" +license = "Apache-2.0/MIT" +repository = "https://github.com/rust-lang/hashbrown" readme = "README.md" keywords = ["hash", "no_std", "hashmap", "swisstable"] categories = ["data-structures", "no-std"] -license = "Apache-2.0/MIT" -repository = "https://github.com/rust-lang/hashbrown" -[package.metadata.docs.rs] -features = ["nightly", "rayon", "serde", "raw"] -[dependencies.ahash] -version = "0.7.0" -optional = true -default-features = false - -# [dependencies.alloc] -# version = "1.0.0" -# optional = true -# package = "rustc-std-workspace-alloc" - -[dependencies.bumpalo] -version = "3.5.0" -optional = true - -# [dependencies.compiler_builtins] -# version = "0.1.2" -# optional = true - -# [dependencies.core] -# version = "1.0.0" -# optional = true -# package = "rustc-std-workspace-core" - -[dependencies.rayon] -version = "1.0" -optional = true +exclude = [".github", "bors.toml", "/ci/*"] +edition = "2021" -[dependencies.serde] -version = "1.0.25" -optional = true -default-features = false -[dev-dependencies.doc-comment] -version = "0.3.1" +[dependencies] +# For the default hasher +ahash = { version = "0.7.0", default-features = false, optional = true } -[dev-dependencies.fnv] -version = "1.0.7" +# For external trait impls +rayon = { version = "1.0", optional = true } +serde = { version = "1.0.25", default-features = false, optional = true } -[dev-dependencies.lazy_static] -version = "1.4" +# When built as part of libstd +# core = { version = "1.0.0", optional = true, package = "rustc-std-workspace-core" } +# compiler_builtins = { version = "0.1.2", optional = true } +# alloc = { version = "1.0.0", optional = true, package = "rustc-std-workspace-alloc" } -[dev-dependencies.rand] -version = "0.7.3" -features = ["small_rng"] +# Optional support for bumpalo +bumpalo = { version = "3.5.0", optional = true } -[dev-dependencies.rayon] -version = "1.0" - -[dev-dependencies.serde_test] -version = "1.0" +[dev-dependencies] +lazy_static = "1.4" +rand = { version = "0.8.3", features = ["small_rng"] } +rayon = "1.0" +fnv = "1.0.7" +serde_test = "1.0" +doc-comment = "0.3.1" [features] -ahash-compile-time-rng = ["ahash/compile-time-rng"] default = ["ahash", "inline-more"] -inline-more = [] + +ahash-compile-time-rng = ["ahash/compile-time-rng"] nightly = [] -raw = [] -# rustc-dep-of-std = ["nightly", "core", "compiler_builtins", "alloc", "rustc-internal-api"] -rustc-dep-of-std = ["nightly", "rustc-internal-api"] rustc-internal-api = [] +# rustc-dep-of-std = [ +# "nightly", +# "core", +# "compiler_builtins", +# "alloc", +# "rustc-internal-api", +# ] +rustc-dep-of-std = [ + "nightly", + "rustc-internal-api", +] +raw = [] + +# Enables usage of `#[inline]` on far more functions than by default in this +# crate. This may lead to a performance increase but often comes at a compile +# time cost. +inline-more = [] + +[package.metadata.docs.rs] +features = ["nightly", "rayon", "serde", "raw"] diff --git a/sgx_tstd/hashbrown/Cargo.toml.orig b/sgx_tstd/hashbrown/Cargo.toml.orig deleted file mode 100644 index a056c3c6b..000000000 --- a/sgx_tstd/hashbrown/Cargo.toml.orig +++ /dev/null @@ -1,59 +0,0 @@ -[package] -name = "hashbrown" -version = "0.11.2" -authors = ["Amanieu d'Antras "] -description = "A Rust port of Google's SwissTable hash map" -license = "Apache-2.0/MIT" -repository = "https://github.com/rust-lang/hashbrown" -readme = "README.md" -keywords = ["hash", "no_std", "hashmap", "swisstable"] -categories = ["data-structures", "no-std"] -exclude = [".travis.yml", "bors.toml", "/ci/*"] -edition = "2018" - -[dependencies] -# For the default hasher -ahash = { version = "0.7.0", default-features = false, optional = true } - -# For external trait impls -rayon = { version = "1.0", optional = true } -serde = { version = "1.0.25", default-features = false, optional = true } - -# When built as part of libstd -core = { version = "1.0.0", optional = true, package = "rustc-std-workspace-core" } -compiler_builtins = { version = "0.1.2", optional = true } -alloc = { version = "1.0.0", optional = true, package = "rustc-std-workspace-alloc" } - -# Optional support for bumpalo -bumpalo = { version = "3.5.0", optional = true } - -[dev-dependencies] -lazy_static = "1.4" -rand = { version = "0.7.3", features = ["small_rng"] } -rayon = "1.0" -fnv = "1.0.7" -serde_test = "1.0" -doc-comment = "0.3.1" - -[features] -default = ["ahash", "inline-more"] - -ahash-compile-time-rng = ["ahash/compile-time-rng"] -nightly = [] -rustc-internal-api = [] -rustc-dep-of-std = [ - "nightly", - "core", - "compiler_builtins", - "alloc", - "rustc-internal-api", -] -raw = [] - -# Enables usage of `#[inline]` on far more functions than by default in this -# crate. This may lead to a performance increase but often comes at a compile -# time cost. -inline-more = [] - -[package.metadata.docs.rs] -features = ["nightly", "rayon", "serde", "raw"] diff --git a/sgx_tstd/hashbrown/README.md b/sgx_tstd/hashbrown/README.md index 86664c4ce..0b29cb57a 100644 --- a/sgx_tstd/hashbrown/README.md +++ b/sgx_tstd/hashbrown/README.md @@ -1,10 +1,10 @@ hashbrown ========= -[![Build Status](https://travis-ci.com/rust-lang/hashbrown.svg?branch=master)](https://travis-ci.com/rust-lang/hashbrown) +[![Build Status](https://github.com/rust-lang/hashbrown/actions/workflows/rust.yml/badge.svg)](https://github.com/rust-lang/hashbrown/actions) [![Crates.io](https://img.shields.io/crates/v/hashbrown.svg)](https://crates.io/crates/hashbrown) [![Documentation](https://docs.rs/hashbrown/badge.svg)](https://docs.rs/hashbrown) -[![Rust](https://img.shields.io/badge/rust-1.49.0%2B-blue.svg?maxAge=3600)](https://github.com/rust-lang/hashbrown) +[![Rust](https://img.shields.io/badge/rust-1.56.1%2B-blue.svg?maxAge=3600)](https://github.com/rust-lang/hashbrown) This crate is a Rust port of Google's high-performance [SwissTable] hash map, adapted to make it a drop-in replacement for Rust's standard `HashMap` @@ -114,8 +114,8 @@ this pre-generates seeds at compile time and embeds them as constants. See [aHas Licensed under either of: - * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) - * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) + * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or https://www.apache.org/licenses/LICENSE-2.0) + * MIT license ([LICENSE-MIT](LICENSE-MIT) or https://opensource.org/licenses/MIT) at your option. diff --git a/sgx_tstd/hashbrown/benches/bench.rs b/sgx_tstd/hashbrown/benches/bench.rs index 568c513e1..c393b9a70 100644 --- a/sgx_tstd/hashbrown/benches/bench.rs +++ b/sgx_tstd/hashbrown/benches/bench.rs @@ -38,7 +38,7 @@ impl Iterator for RandomKeys { type Item = usize; fn next(&mut self) -> Option { // Add 1 then multiply by some 32 bit prime. - self.state = self.state.wrapping_add(1).wrapping_mul(3787392781); + self.state = self.state.wrapping_add(1).wrapping_mul(3_787_392_781); Some(self.state) } } diff --git a/sgx_tstd/hashbrown/benches/insert_unique_unchecked.rs b/sgx_tstd/hashbrown/benches/insert_unique_unchecked.rs new file mode 100644 index 000000000..857ad18e5 --- /dev/null +++ b/sgx_tstd/hashbrown/benches/insert_unique_unchecked.rs @@ -0,0 +1,32 @@ +//! Compare `insert` and `insert_unique_unchecked` operations performance. + +#![feature(test)] + +extern crate test; + +use hashbrown::HashMap; +use test::Bencher; + +#[bench] +fn insert(b: &mut Bencher) { + let keys: Vec = (0..1000).map(|i| format!("xxxx{}yyyy", i)).collect(); + b.iter(|| { + let mut m = HashMap::with_capacity(1000); + for k in &keys { + m.insert(k, k); + } + m + }); +} + +#[bench] +fn insert_unique_unchecked(b: &mut Bencher) { + let keys: Vec = (0..1000).map(|i| format!("xxxx{}yyyy", i)).collect(); + b.iter(|| { + let mut m = HashMap::with_capacity(1000); + for k in &keys { + m.insert_unique_unchecked(k, k); + } + m + }); +} diff --git a/sgx_tstd/hashbrown/ci/miri.sh b/sgx_tstd/hashbrown/ci/miri.sh new file mode 100644 index 000000000..6b95c2d97 --- /dev/null +++ b/sgx_tstd/hashbrown/ci/miri.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env sh + +set -ex + +export CARGO_NET_RETRY=5 +export CARGO_NET_TIMEOUT=10 + +MIRI_NIGHTLY=nightly-$(curl -s https://rust-lang.github.io/rustup-components-history/x86_64-unknown-linux-gnu/miri) +echo "Installing latest nightly with Miri: $MIRI_NIGHTLY" +rustup default "$MIRI_NIGHTLY" + +rustup component add miri +cargo miri setup + +cargo miri test diff --git a/sgx_tstd/hashbrown/ci/run.sh b/sgx_tstd/hashbrown/ci/run.sh new file mode 100644 index 000000000..a8257e559 --- /dev/null +++ b/sgx_tstd/hashbrown/ci/run.sh @@ -0,0 +1,47 @@ +#!/usr/bin/env sh + +set -ex + +: "${TARGET?The TARGET environment variable must be set.}" + +if [ "${NO_STD}" = "1" ]; then + # Unfortunately serde currently doesn't work without std due to a cargo bug. + FEATURES="rustc-internal-api" + OP="build" +else + FEATURES="rustc-internal-api,serde,rayon,raw,bumpalo" + OP="test" +fi +if [ "${CHANNEL}" = "nightly" ]; then + FEATURES="${FEATURES},nightly" + export RUSTFLAGS="$RUSTFLAGS -D warnings" +fi + +CARGO=cargo +if [ "${CROSS}" = "1" ]; then + export CARGO_NET_RETRY=5 + export CARGO_NET_TIMEOUT=10 + + cargo install --git https://github.com/rust-embedded/cross.git + CARGO=cross +fi + +# Make sure we can compile without the default hasher +"${CARGO}" -vv build --target="${TARGET}" --no-default-features +"${CARGO}" -vv build --target="${TARGET}" --release --no-default-features + +"${CARGO}" -vv ${OP} --target="${TARGET}" +"${CARGO}" -vv ${OP} --target="${TARGET}" --features "${FEATURES}" + +"${CARGO}" -vv ${OP} --target="${TARGET}" --release +"${CARGO}" -vv ${OP} --target="${TARGET}" --release --features "${FEATURES}" + +if [ "${CHANNEL}" = "nightly" ] && [ "${NO_STD}" != 1 ]; then + # Run benchmark on native targets, build them on non-native ones: + NO_RUN="" + if [ "${CROSS}" = "1" ]; then + NO_RUN="--no-run" + fi + + "${CARGO}" -vv bench "${NO_RUN}" --features "${FEATURES}" +fi diff --git a/sgx_tstd/hashbrown/ci/tools.sh b/sgx_tstd/hashbrown/ci/tools.sh new file mode 100644 index 000000000..5ae8b2e8a --- /dev/null +++ b/sgx_tstd/hashbrown/ci/tools.sh @@ -0,0 +1,41 @@ +#!/usr/bin/env sh + +set -ex + +retry() { + result=0 + count=1 + max=5 + while [ "$count" -le 3 ]; do + [ "$result" -ne 0 ] && { + printf "\nRetrying, %d of %d\n" $count $max >&2 + } + "$@" + result=$? + [ $result -eq 0 ] && break + count=$((count + 1)) + sleep 1 + done + + [ "$count" -gt 3 ] && { + printf "\nFailed %d times.\n" $max >&2 + } + + return $result +} + + +if retry rustup component add rustfmt ; then + cargo fmt --all -- --check +fi + +if retry rustup component add clippy ; then + cargo clippy --all --tests --features serde,rayon,bumpalo -- -D clippy::all -D clippy::pedantic + cargo clippy --all --tests --features raw -- -D clippy::all -D clippy::pedantic \ + -A clippy::missing_safety_doc -A clippy::missing_errors_doc +fi + +if command -v shellcheck ; then + shellcheck --version + shellcheck ci/*.sh +fi diff --git a/sgx_tstd/hashbrown/src/external_trait_impls/rayon/helpers.rs b/sgx_tstd/hashbrown/src/external_trait_impls/rayon/helpers.rs index 9382007ea..070b08cd5 100644 --- a/sgx_tstd/hashbrown/src/external_trait_impls/rayon/helpers.rs +++ b/sgx_tstd/hashbrown/src/external_trait_impls/rayon/helpers.rs @@ -4,6 +4,7 @@ use alloc::vec::Vec; use rayon::iter::{IntoParallelIterator, ParallelIterator}; /// Helper for collecting parallel iterators to an intermediary +#[allow(clippy::linkedlist)] // yes, we need linked list here for efficient appending! pub(super) fn collect(iter: I) -> (LinkedList>, usize) { let list = iter .into_par_iter() diff --git a/sgx_tstd/hashbrown/src/external_trait_impls/rayon/map.rs b/sgx_tstd/hashbrown/src/external_trait_impls/rayon/map.rs index 61b738061..14d91c220 100644 --- a/sgx_tstd/hashbrown/src/external_trait_impls/rayon/map.rs +++ b/sgx_tstd/hashbrown/src/external_trait_impls/rayon/map.rs @@ -512,7 +512,7 @@ mod test_par_map { where H: Hasher, { - self.k.hash(state) + self.k.hash(state); } } @@ -679,7 +679,7 @@ mod test_par_map { fn test_values_mut() { let vec = vec![(1, 1), (2, 2), (3, 3)]; let mut map: HashMap<_, _> = vec.into_par_iter().collect(); - map.par_values_mut().for_each(|value| *value = (*value) * 2); + map.par_values_mut().for_each(|value| *value *= 2); let values: Vec<_> = map.par_values().cloned().collect(); assert_eq!(values.len(), 3); assert!(values.contains(&2)); diff --git a/sgx_tstd/hashbrown/src/external_trait_impls/rayon/raw.rs b/sgx_tstd/hashbrown/src/external_trait_impls/rayon/raw.rs index 18da1eacd..883303e27 100644 --- a/sgx_tstd/hashbrown/src/external_trait_impls/rayon/raw.rs +++ b/sgx_tstd/hashbrown/src/external_trait_impls/rayon/raw.rs @@ -87,7 +87,7 @@ impl RawIntoParIter { } } -impl ParallelIterator for RawIntoParIter { +impl ParallelIterator for RawIntoParIter { type Item = T; #[cfg_attr(feature = "inline-more", inline)] @@ -116,7 +116,7 @@ pub struct RawParDrain<'a, T, A: Allocator + Clone = Global> { marker: PhantomData<&'a RawTable>, } -unsafe impl Send for RawParDrain<'_, T, A> {} +unsafe impl Send for RawParDrain<'_, T, A> {} impl RawParDrain<'_, T, A> { #[cfg_attr(feature = "inline-more", inline)] @@ -134,7 +134,7 @@ impl ParallelIterator for RawParDrain<'_, T, A> { C: UnindexedConsumer, { let _guard = guard(self.table, |table| unsafe { - table.as_mut().clear_no_drop() + table.as_mut().clear_no_drop(); }); let iter = unsafe { self.table.as_ref().iter().iter }; mem::forget(self); @@ -146,7 +146,9 @@ impl ParallelIterator for RawParDrain<'_, T, A> { impl Drop for RawParDrain<'_, T, A> { fn drop(&mut self) { // If drive_unindexed is not called then simply clear the table. - unsafe { self.table.as_mut().clear() } + unsafe { + self.table.as_mut().clear(); + } } } @@ -175,7 +177,7 @@ impl UnindexedProducer for ParDrainProducer { { // Make sure to modify the iterator in-place so that any remaining // elements are processed in our Drop impl. - while let Some(item) = self.iter.next() { + for item in &mut self.iter { folder = folder.consume(unsafe { item.read() }); if folder.full() { return folder; @@ -193,7 +195,7 @@ impl Drop for ParDrainProducer { fn drop(&mut self) { // Drop all remaining elements if mem::needs_drop::() { - while let Some(item) = self.iter.next() { + for item in &mut self.iter { unsafe { item.drop(); } diff --git a/sgx_tstd/hashbrown/src/external_trait_impls/serde.rs b/sgx_tstd/hashbrown/src/external_trait_impls/serde.rs index 7816e7803..4d62deeb7 100644 --- a/sgx_tstd/hashbrown/src/external_trait_impls/serde.rs +++ b/sgx_tstd/hashbrown/src/external_trait_impls/serde.rs @@ -161,6 +161,7 @@ mod set { deserializer.deserialize_seq(visitor) } + #[allow(clippy::missing_errors_doc)] fn deserialize_in_place(deserializer: D, place: &mut Self) -> Result<(), D::Error> where D: Deserializer<'de>, diff --git a/sgx_tstd/hashbrown/src/lib.rs b/sgx_tstd/hashbrown/src/lib.rs index b2d6584ff..701b6ea6b 100644 --- a/sgx_tstd/hashbrown/src/lib.rs +++ b/sgx_tstd/hashbrown/src/lib.rs @@ -21,7 +21,8 @@ allocator_api, slice_ptr_get, nonnull_slice_from_raw_parts, - maybe_uninit_array_assume_init + maybe_uninit_array_assume_init, + build_hasher_simple_hash_one ) )] #![allow( @@ -128,20 +129,6 @@ pub enum TryReserveError { }, } -/// The error type for [`RawTable::get_each_mut`](crate::raw::RawTable::get_each_mut), -/// [`HashMap::get_each_mut`], and [`HashMap::get_each_key_value_mut`]. -#[cfg(feature = "nightly")] -#[derive(Clone, PartialEq, Eq, Debug)] -pub enum UnavailableMutError { - /// The requested entry is not present in the table. - Absent, - /// The requested entry is present, but a mutable reference to it was already created and - /// returned from this call to `get_each_mut` or `get_each_key_value_mut`. - /// - /// Includes the index of the existing mutable reference in the returned array. - Duplicate(usize), -} - /// Wrapper around `Bump` which allows it to be used as an allocator for /// `HashMap`, `HashSet` and `RawTable`. /// diff --git a/sgx_tstd/hashbrown/src/macros.rs b/sgx_tstd/hashbrown/src/macros.rs index 027959731..4de6b5aa1 100644 --- a/sgx_tstd/hashbrown/src/macros.rs +++ b/sgx_tstd/hashbrown/src/macros.rs @@ -57,8 +57,8 @@ macro_rules! cfg_if { // default fn syntax for specialization changes in the future. #[cfg(feature = "nightly")] macro_rules! default_fn { - ($($tt:tt)*) => { - default $($tt)* + (#[$($a:tt)*] $($tt:tt)*) => { + #[$($a)*] default $($tt)* } } #[cfg(not(feature = "nightly"))] diff --git a/sgx_tstd/hashbrown/src/map.rs b/sgx_tstd/hashbrown/src/map.rs index ab1128879..d0592cb7f 100644 --- a/sgx_tstd/hashbrown/src/map.rs +++ b/sgx_tstd/hashbrown/src/map.rs @@ -1,15 +1,11 @@ use crate::raw::{Allocator, Bucket, Global, RawDrain, RawIntoIter, RawIter, RawTable}; use crate::TryReserveError; -#[cfg(feature = "nightly")] -use crate::UnavailableMutError; use core::borrow::Borrow; use core::fmt::{self, Debug}; use core::hash::{BuildHasher, Hash}; use core::iter::{FromIterator, FusedIterator}; use core::marker::PhantomData; use core::mem; -#[cfg(feature = "nightly")] -use core::mem::MaybeUninit; use core::ops::Index; /// Default hasher for `HashMap`. @@ -244,6 +240,7 @@ where move |x| k.eq(x.borrow()) } +#[cfg(not(feature = "nightly"))] #[cfg_attr(feature = "inline-more", inline)] pub(crate) fn make_hash(hash_builder: &S, val: &Q) -> u64 where @@ -257,6 +254,18 @@ where state.finish() } +#[cfg(feature = "nightly")] +#[cfg_attr(feature = "inline-more", inline)] +pub(crate) fn make_hash(hash_builder: &S, val: &Q) -> u64 +where + K: Borrow, + Q: Hash + ?Sized, + S: BuildHasher, +{ + hash_builder.hash_one(val) +} + +#[cfg(not(feature = "nightly"))] #[cfg_attr(feature = "inline-more", inline)] pub(crate) fn make_insert_hash(hash_builder: &S, val: &K) -> u64 where @@ -269,6 +278,16 @@ where state.finish() } +#[cfg(feature = "nightly")] +#[cfg_attr(feature = "inline-more", inline)] +pub(crate) fn make_insert_hash(hash_builder: &S, val: &K) -> u64 +where + K: Hash, + S: BuildHasher, +{ + hash_builder.hash_one(val) +} + #[cfg(feature = "ahash")] impl HashMap { /// Creates an empty `HashMap`. @@ -395,6 +414,12 @@ impl HashMap { } impl HashMap { + /// Returns a reference to the underlying allocator. + #[inline] + pub fn allocator(&self) -> &A { + self.table.allocator() + } + /// Creates an empty `HashMap` which will use the given hash builder to hash /// keys. It will be allocated with the given allocator. /// @@ -773,6 +798,52 @@ impl HashMap { pub fn clear(&mut self) { self.table.clear(); } + + /// Creates a consuming iterator visiting all the keys in arbitrary order. + /// The map cannot be used after calling this. + /// The iterator element type is `K`. + /// + /// # Examples + /// + /// ``` + /// use hashbrown::HashMap; + /// + /// let mut map = HashMap::new(); + /// map.insert("a", 1); + /// map.insert("b", 2); + /// map.insert("c", 3); + /// + /// let vec: Vec<&str> = map.into_keys().collect(); + /// ``` + #[inline] + pub fn into_keys(self) -> IntoKeys { + IntoKeys { + inner: self.into_iter(), + } + } + + /// Creates a consuming iterator visiting all the values in arbitrary order. + /// The map cannot be used after calling this. + /// The iterator element type is `V`. + /// + /// # Examples + /// + /// ``` + /// use hashbrown::HashMap; + /// + /// let mut map = HashMap::new(); + /// map.insert("a", 1); + /// map.insert("b", 2); + /// map.insert("c", 3); + /// + /// let vec: Vec = map.into_values().collect(); + /// ``` + #[inline] + pub fn into_values(self) -> IntoValues { + IntoValues { + inner: self.into_iter(), + } + } } impl HashMap @@ -915,6 +986,46 @@ where } } + /// Gets the given key's corresponding entry by reference in the map for in-place manipulation. + /// + /// # Examples + /// + /// ``` + /// use hashbrown::HashMap; + /// + /// let mut words: HashMap = HashMap::new(); + /// let source = ["poneyland", "horseyland", "poneyland", "poneyland"]; + /// for (i, &s) in source.iter().enumerate() { + /// let counter = words.entry_ref(s).or_insert(0); + /// *counter += 1; + /// } + /// + /// assert_eq!(words["poneyland"], 3); + /// assert_eq!(words["horseyland"], 1); + /// ``` + #[cfg_attr(feature = "inline-more", inline)] + pub fn entry_ref<'a, 'b, Q: ?Sized>(&'a mut self, key: &'b Q) -> EntryRef<'a, 'b, K, Q, V, S, A> + where + K: Borrow, + Q: Hash + Eq, + { + let hash = make_hash::(&self.hash_builder, key); + if let Some(elem) = self.table.find(hash, equivalent_key(key)) { + EntryRef::Occupied(OccupiedEntryRef { + hash, + key: Some(KeyOrRef::Borrowed(key)), + elem, + table: self, + }) + } else { + EntryRef::Vacant(VacantEntryRef { + hash, + key: KeyOrRef::Borrowed(key), + table: self, + }) + } + } + /// Returns a reference to the value corresponding to the key. /// /// The key may be any borrowed form of the map's key type, but @@ -985,8 +1096,12 @@ where K: Borrow, Q: Hash + Eq, { - let hash = make_hash::(&self.hash_builder, k); - self.table.get(hash, equivalent_key(k)) + if self.table.is_empty() { + None + } else { + let hash = make_hash::(&self.hash_builder, k); + self.table.get(hash, equivalent_key(k)) + } } /// Returns the key-value pair corresponding to the supplied key, with a mutable reference to value. @@ -1093,24 +1208,24 @@ where K: Borrow, Q: Hash + Eq, { - let hash = make_hash::(&self.hash_builder, k); - self.table.get_mut(hash, equivalent_key(k)) + if self.table.is_empty() { + None + } else { + let hash = make_hash::(&self.hash_builder, k); + self.table.get_mut(hash, equivalent_key(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. An - /// `Err(UnavailableMutError::Duplicate(i))` in the returned array indicates that a suitable - /// key-value pair exists, but a mutable reference to the value already occurs at index `i` in - /// the returned array. - /// - /// This method is available only if the `nightly` feature is enabled. + /// 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 /// /// ``` - /// use hashbrown::{HashMap, UnavailableMutError}; + /// use hashbrown::HashMap; /// /// let mut libraries = HashMap::new(); /// libraries.insert("Bodleian Library".to_string(), 1602); @@ -1118,58 +1233,108 @@ where /// libraries.insert("Herzogin-Anna-Amalia-Bibliothek".to_string(), 1691); /// libraries.insert("Library of Congress".to_string(), 1800); /// - /// let got = libraries.get_each_mut([ + /// 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); + /// ``` + pub fn get_many_mut(&mut self, ks: [&Q; N]) -> Option<[&'_ mut V; N]> + where + K: Borrow, + Q: Hash + Eq, + { + self.get_many_mut_inner(ks).map(|res| res.map(|(_, v)| v)) + } + + /// 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`]. + /// + /// # 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 + /// + /// ``` + /// use hashbrown::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, - /// [ - /// Ok(&mut 1807), - /// Err(UnavailableMutError::Absent), - /// Err(UnavailableMutError::Duplicate(0)), - /// Ok(&mut 1800), - /// ] + /// 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); /// ``` - #[cfg(feature = "nightly")] - pub fn get_each_mut( + pub unsafe fn get_many_unchecked_mut( &mut self, ks: [&Q; N], - ) -> [Result<&'_ mut V, UnavailableMutError>; N] + ) -> Option<[&'_ mut V; N]> where K: Borrow, Q: Hash + Eq, { - let mut pairs = self.get_each_inner_mut(ks); - // TODO use `MaybeUninit::uninit_array` here instead once that's stable. - let mut out: [MaybeUninit>; N] = - unsafe { MaybeUninit::uninit().assume_init() }; - for i in 0..N { - out[i] = MaybeUninit::new( - mem::replace(&mut pairs[i], Err(UnavailableMutError::Absent)).map(|(_, v)| v), - ); - } - unsafe { MaybeUninit::array_assume_init(out) } + self.get_many_unchecked_mut_inner(ks) + .map(|res| res.map(|(_, v)| v)) } /// Attempts to get mutable references to `N` values in the map at once, with immutable /// references to the corresponding keys. /// - /// 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. An - /// `Err(UnavailableMutError::Duplicate(i))` in the returned array indicates that a suitable - /// key-value pair exists, but a mutable reference to the value already occurs at index `i` in - /// the returned array. - /// - /// This method is available only if the `nightly` feature is enabled. + /// 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 /// /// ``` - /// use hashbrown::{HashMap, UnavailableMutError}; + /// use hashbrown::HashMap; /// /// let mut libraries = HashMap::new(); /// libraries.insert("Bodleian Library".to_string(), 1602); @@ -1177,49 +1342,127 @@ where /// libraries.insert("Herzogin-Anna-Amalia-Bibliothek".to_string(), 1691); /// libraries.insert("Library of Congress".to_string(), 1800); /// - /// let got = libraries.get_each_key_value_mut([ + /// let got = libraries.get_many_key_value_mut([ /// "Bodleian Library", /// "Herzogin-Anna-Amalia-Bibliothek", - /// "Herzogin-Anna-Amalia-Bibliothek", + /// ]); + /// assert_eq!( + /// got, + /// Some([ + /// (&"Bodleian Library".to_string(), &mut 1602), + /// (&"Herzogin-Anna-Amalia-Bibliothek".to_string(), &mut 1691), + /// ]), + /// ); + /// // Missing keys result in None + /// let got = libraries.get_many_key_value_mut([ + /// "Bodleian Library", /// "Gewandhaus", /// ]); + /// assert_eq!(got, None); + /// + /// // Duplicate keys result in None + /// let got = libraries.get_many_key_value_mut([ + /// "Bodleian Library", + /// "Herzogin-Anna-Amalia-Bibliothek", + /// "Herzogin-Anna-Amalia-Bibliothek", + /// ]); + /// assert_eq!(got, None); + /// ``` + pub fn get_many_key_value_mut( + &mut self, + ks: [&Q; N], + ) -> Option<[(&'_ K, &'_ mut V); N]> + where + K: Borrow, + Q: Hash + Eq, + { + self.get_many_mut_inner(ks) + .map(|res| res.map(|(k, v)| (&*k, v))) + } + + /// Attempts to get mutable references to `N` values in the map at once, with immutable + /// references to the corresponding keys, 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_key_value_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 + /// + /// ``` + /// use hashbrown::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_key_value_mut([ + /// "Bodleian Library", + /// "Herzogin-Anna-Amalia-Bibliothek", + /// ]); /// assert_eq!( /// got, - /// [ - /// Ok((&"Bodleian Library".to_string(), &mut 1602)), - /// Ok((&"Herzogin-Anna-Amalia-Bibliothek".to_string(), &mut 1691)), - /// Err(UnavailableMutError::Duplicate(1)), - /// Err(UnavailableMutError::Absent), - /// ] + /// Some([ + /// (&"Bodleian Library".to_string(), &mut 1602), + /// (&"Herzogin-Anna-Amalia-Bibliothek".to_string(), &mut 1691), + /// ]), /// ); + /// // Missing keys result in None + /// let got = libraries.get_many_key_value_mut([ + /// "Bodleian Library", + /// "Gewandhaus", + /// ]); + /// assert_eq!(got, None); /// ``` - #[cfg(feature = "nightly")] - pub fn get_each_key_value_mut( + pub unsafe fn get_many_key_value_unchecked_mut( &mut self, ks: [&Q; N], - ) -> [Result<(&'_ K, &'_ mut V), UnavailableMutError>; N] + ) -> Option<[(&'_ K, &'_ mut V); N]> where K: Borrow, Q: Hash + Eq, { - let mut pairs = self.get_each_inner_mut(ks); - // TODO use `MaybeUninit::uninit_array` here instead once that's stable. - let mut out: [MaybeUninit>; N] = - unsafe { MaybeUninit::uninit().assume_init() }; - for i in 0..N { - out[i] = MaybeUninit::new( - mem::replace(&mut pairs[i], Err(UnavailableMutError::Absent)) - .map(|(k, v)| (&*k, v)), - ); - } - unsafe { MaybeUninit::array_assume_init(out) } + self.get_many_unchecked_mut_inner(ks) + .map(|res| res.map(|(k, v)| (&*k, v))) } - #[cfg(feature = "nightly")] - fn get_each_inner_mut( + fn get_many_mut_inner( + &mut self, + ks: [&Q; N], + ) -> Option<[&'_ mut (K, V); N]> + where + K: Borrow, + Q: Hash + Eq, + { + let hashes = self.build_hashes_inner(ks); + self.table + .get_many_mut(hashes, |i, (k, _)| ks[i].eq(k.borrow())) + } + + unsafe fn get_many_unchecked_mut_inner( &mut self, ks: [&Q; N], - ) -> [Result<&'_ mut (K, V), UnavailableMutError>; N] + ) -> Option<[&'_ mut (K, V); N]> + where + K: Borrow, + Q: Hash + Eq, + { + let hashes = self.build_hashes_inner(ks); + self.table + .get_many_unchecked_mut(hashes, |i, (k, _)| ks[i].eq(k.borrow())) + } + + fn build_hashes_inner(&self, ks: [&Q; N]) -> [u64; N] where K: Borrow, Q: Hash + Eq, @@ -1228,8 +1471,7 @@ where for i in 0..N { hashes[i] = make_hash::(&self.hash_builder, ks[i]); } - self.table - .get_each_mut(hashes, |i, (k, _)| ks[i].eq(k.borrow())) + hashes } /// Inserts a key-value pair into the map. @@ -1269,6 +1511,36 @@ where } } + /// Insert a key-value pair into the map without checking + /// if the key already exists in the map. + /// + /// Returns a reference to the key and value just inserted. + /// + /// This operation is safe if a key does not exist in the map. + /// + /// However, if a key exists in the map already, the behavior is unspecified: + /// this operation may panic, loop forever, or any following operation with the map + /// may panic, loop forever or return arbitrary result. + /// + /// That said, this operation (and following operations) are guaranteed to + /// not violate memory safety. + /// + /// This operation is faster than regular insert, because it does not perform + /// lookup before insertion. + /// + /// This operation is useful during initial population of the map. + /// For example, when constructing a map from another map, we know + /// that keys are unique. + #[cfg_attr(feature = "inline-more", inline)] + pub fn insert_unique_unchecked(&mut self, k: K, v: V) -> (&K, &mut V) { + let hash = make_insert_hash::(&self.hash_builder, &k); + let bucket = self + .table + .insert(hash, (k, v), make_hasher::(&self.hash_builder)); + let (k_ref, v_ref) = unsafe { bucket.as_mut() }; + (k_ref, v_ref) + } + /// Tries to insert a key-value pair into the map, and returns /// a mutable reference to the value in the entry. /// @@ -1495,6 +1767,27 @@ where } } +// The default hasher is used to match the std implementation signature +#[cfg(feature = "ahash")] +impl From<[(K, V); N]> for HashMap +where + K: Eq + Hash, + A: Default + Allocator + Clone, +{ + /// # Examples + /// + /// ``` + /// use hashbrown::HashMap; + /// + /// let map1 = HashMap::from([(1, 2), (3, 4)]); + /// let map2: HashMap<_, _> = [(1, 2), (3, 4)].into(); + /// assert_eq!(map1, map2); + /// ``` + fn from(arr: [(K, V); N]) -> Self { + arr.into_iter().collect() + } +} + /// An iterator over the entries of a `HashMap`. /// /// This `struct` is created by the [`iter`] method on [`HashMap`]. See its @@ -1575,30 +1868,112 @@ impl IntoIter { } } -/// An iterator over the keys of a `HashMap`. +/// An owning iterator over the keys of a `HashMap`. /// -/// This `struct` is created by the [`keys`] method on [`HashMap`]. See its -/// documentation for more. +/// This `struct` is created by the [`into_keys`] method on [`HashMap`]. +/// See its documentation for more. /// -/// [`keys`]: struct.HashMap.html#method.keys +/// [`into_keys`]: struct.HashMap.html#method.into_keys /// [`HashMap`]: struct.HashMap.html -pub struct Keys<'a, K, V> { - inner: Iter<'a, K, V>, +pub struct IntoKeys { + inner: IntoIter, } -// FIXME(#26925) Remove in favor of `#[derive(Clone)]` -impl Clone for Keys<'_, K, V> { - #[cfg_attr(feature = "inline-more", inline)] - fn clone(&self) -> Self { - Keys { - inner: self.inner.clone(), - } +impl Iterator for IntoKeys { + type Item = K; + + #[inline] + fn next(&mut self) -> Option { + self.inner.next().map(|(k, _)| k) + } + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.inner.size_hint() } } -impl fmt::Debug for Keys<'_, K, V> { +impl ExactSizeIterator for IntoKeys { + #[inline] + fn len(&self) -> usize { + self.inner.len() + } +} + +impl FusedIterator for IntoKeys {} + +impl fmt::Debug for IntoKeys { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_list().entries(self.clone()).finish() + f.debug_list() + .entries(self.inner.iter().map(|(k, _)| k)) + .finish() + } +} + +/// An owning iterator over the values of a `HashMap`. +/// +/// This `struct` is created by the [`into_values`] method on [`HashMap`]. +/// See its documentation for more. +/// +/// [`into_values`]: struct.HashMap.html#method.into_values +/// [`HashMap`]: struct.HashMap.html +pub struct IntoValues { + inner: IntoIter, +} + +impl Iterator for IntoValues { + type Item = V; + + #[inline] + fn next(&mut self) -> Option { + self.inner.next().map(|(_, v)| v) + } + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.inner.size_hint() + } +} + +impl ExactSizeIterator for IntoValues { + #[inline] + fn len(&self) -> usize { + self.inner.len() + } +} + +impl FusedIterator for IntoValues {} + +impl fmt::Debug for IntoValues { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_list() + .entries(self.inner.iter().map(|(k, _)| k)) + .finish() + } +} + +/// An iterator over the keys of a `HashMap`. +/// +/// This `struct` is created by the [`keys`] method on [`HashMap`]. See its +/// documentation for more. +/// +/// [`keys`]: struct.HashMap.html#method.keys +/// [`HashMap`]: struct.HashMap.html +pub struct Keys<'a, K, V> { + inner: Iter<'a, K, V>, +} + +// FIXME(#26925) Remove in favor of `#[derive(Clone)]` +impl Clone for Keys<'_, K, V> { + #[cfg_attr(feature = "inline-more", inline)] + fn clone(&self) -> Self { + Keys { + inner: self.inner.clone(), + } + } +} + +impl fmt::Debug for Keys<'_, K, V> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_list().entries(self.clone()).finish() } } @@ -1686,7 +2061,7 @@ pub(super) struct ConsumeAllOnDrop<'a, T: Iterator>(pub &'a mut T); impl Drop for ConsumeAllOnDrop<'_, T> { #[cfg_attr(feature = "inline-more", inline)] fn drop(&mut self) { - self.0.for_each(drop) + self.0.for_each(drop); } } @@ -1723,7 +2098,7 @@ impl DrainFilterInner<'_, K, V, A> { F: FnMut(&K, &mut V) -> bool, { unsafe { - while let Some(item) = self.iter.next() { + for item in &mut self.iter { let &mut (ref key, ref mut value) = item.as_mut(); if f(key, value) { return Some(self.table.remove(item)); @@ -1786,6 +2161,7 @@ unsafe impl Send for RawOccupiedEntryMut<'_, K, V, S, A> where K: Send, V: Send, + S: Send, A: Send + Allocator + Clone, { } @@ -1793,7 +2169,8 @@ unsafe impl Sync for RawOccupiedEntryMut<'_, K, V, S, A> where K: Sync, V: Sync, - A: Send + Allocator + Clone, + S: Sync, + A: Sync + Allocator + Clone, { } @@ -2413,6 +2790,119 @@ impl Debug for VacantEntry<'_, K, V, S, A> } } +/// A view into a single entry in a map, which may either be vacant or occupied. +/// +/// This `enum` is constructed from the [`entry_ref`] method on [`HashMap`]. +/// +/// [`HashMap`]: struct.HashMap.html +/// [`entry_ref`]: struct.HashMap.html#method.entry_ref +pub enum EntryRef<'a, 'b, K, Q: ?Sized, V, S, A = Global> +where + A: Allocator + Clone, +{ + /// An occupied entry. + Occupied(OccupiedEntryRef<'a, 'b, K, Q, V, S, A>), + + /// A vacant entry. + Vacant(VacantEntryRef<'a, 'b, K, Q, V, S, A>), +} + +impl, Q: ?Sized + Debug, V: Debug, S, A: Allocator + Clone> Debug + for EntryRef<'_, '_, K, Q, V, S, A> +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match *self { + EntryRef::Vacant(ref v) => f.debug_tuple("EntryRef").field(v).finish(), + EntryRef::Occupied(ref o) => f.debug_tuple("EntryRef").field(o).finish(), + } + } +} + +enum KeyOrRef<'a, K, Q: ?Sized> { + Borrowed(&'a Q), + Owned(K), +} + +impl<'a, K, Q: ?Sized> KeyOrRef<'a, K, Q> { + fn into_owned(self) -> K + where + K: From<&'a Q>, + { + match self { + Self::Borrowed(borrowed) => borrowed.into(), + Self::Owned(owned) => owned, + } + } +} + +impl<'a, K: Borrow, Q: ?Sized> AsRef for KeyOrRef<'a, K, Q> { + fn as_ref(&self) -> &Q { + match self { + Self::Borrowed(borrowed) => borrowed, + Self::Owned(owned) => owned.borrow(), + } + } +} + +/// A view into an occupied entry in a `HashMap`. +/// It is part of the [`EntryRef`] enum. +/// +/// [`EntryRef`]: enum.EntryRef.html +pub struct OccupiedEntryRef<'a, 'b, K, Q: ?Sized, V, S, A: Allocator + Clone = Global> { + hash: u64, + key: Option>, + elem: Bucket<(K, V)>, + table: &'a mut HashMap, +} + +unsafe impl<'a, 'b, K, Q, V, S, A> Send for OccupiedEntryRef<'a, 'b, K, Q, V, S, A> +where + K: Send, + Q: Sync + ?Sized, + V: Send, + S: Send, + A: Send + Allocator + Clone, +{ +} +unsafe impl<'a, 'b, K, Q, V, S, A> Sync for OccupiedEntryRef<'a, 'b, K, Q, V, S, A> +where + K: Sync, + Q: Sync + ?Sized, + V: Sync, + S: Sync, + A: Sync + Allocator + Clone, +{ +} + +impl, Q: ?Sized + Debug, V: Debug, S, A: Allocator + Clone> Debug + for OccupiedEntryRef<'_, '_, K, Q, V, S, A> +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("OccupiedEntryRef") + .field("key", &self.key()) + .field("value", &self.get()) + .finish() + } +} + +/// A view into a vacant entry in a `HashMap`. +/// It is part of the [`EntryRef`] enum. +/// +/// [`EntryRef`]: enum.EntryRef.html +pub struct VacantEntryRef<'a, 'b, K, Q: ?Sized, V, S, A: Allocator + Clone = Global> { + hash: u64, + key: KeyOrRef<'b, K, Q>, + table: &'a mut HashMap, +} + +impl, Q: ?Sized + Debug, V, S, A: Allocator + Clone> Debug + for VacantEntryRef<'_, '_, K, Q, V, S, A> +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("VacantEntryRef").field(&self.key()).finish() + } +} + /// The error returned by [`try_insert`](HashMap::try_insert) when the key already exists. /// /// Contains the occupied entry, and the value that was not inserted. @@ -3235,18 +3725,692 @@ impl<'a, K, V, S, A: Allocator + Clone> OccupiedEntry<'a, K, V, S, A> { /// }; /// /// match entry { - /// Entry::Vacant(e) => { - /// assert_eq!(e.key(), &"poneyland"); + /// Entry::Vacant(e) => { + /// assert_eq!(e.key(), &"poneyland"); + /// } + /// Entry::Occupied(_) => panic!(), + /// } + /// + /// assert!(!map.contains_key("poneyland")); + /// ``` + #[cfg_attr(feature = "inline-more", inline)] + pub fn replace_entry_with(self, f: F) -> Entry<'a, K, V, S, A> + where + F: FnOnce(&K, V) -> Option, + { + unsafe { + let mut spare_key = None; + + self.table + .table + .replace_bucket_with(self.elem.clone(), |(key, value)| { + if let Some(new_value) = f(&key, value) { + Some((key, new_value)) + } else { + spare_key = Some(key); + None + } + }); + + if let Some(key) = spare_key { + Entry::Vacant(VacantEntry { + hash: self.hash, + key, + table: self.table, + }) + } else { + Entry::Occupied(self) + } + } + } +} + +impl<'a, K, V, S, A: Allocator + Clone> VacantEntry<'a, K, V, S, A> { + /// Gets a reference to the key that would be used when inserting a value + /// through the `VacantEntry`. + /// + /// # Examples + /// + /// ``` + /// use hashbrown::HashMap; + /// + /// let mut map: HashMap<&str, u32> = HashMap::new(); + /// assert_eq!(map.entry("poneyland").key(), &"poneyland"); + /// ``` + #[cfg_attr(feature = "inline-more", inline)] + pub fn key(&self) -> &K { + &self.key + } + + /// Take ownership of the key. + /// + /// # Examples + /// + /// ``` + /// use hashbrown::HashMap; + /// use hashbrown::hash_map::Entry; + /// + /// let mut map: HashMap<&str, u32> = HashMap::new(); + /// + /// if let Entry::Vacant(v) = map.entry("poneyland") { + /// v.into_key(); + /// } + /// ``` + #[cfg_attr(feature = "inline-more", inline)] + pub fn into_key(self) -> K { + self.key + } + + /// Sets the value of the entry with the VacantEntry's key, + /// and returns a mutable reference to it. + /// + /// # Examples + /// + /// ``` + /// use hashbrown::HashMap; + /// use hashbrown::hash_map::Entry; + /// + /// let mut map: HashMap<&str, u32> = HashMap::new(); + /// + /// if let Entry::Vacant(o) = map.entry("poneyland") { + /// o.insert(37); + /// } + /// assert_eq!(map["poneyland"], 37); + /// ``` + #[cfg_attr(feature = "inline-more", inline)] + pub fn insert(self, value: V) -> &'a mut V + where + K: Hash, + S: BuildHasher, + { + let table = &mut self.table.table; + let entry = table.insert_entry( + self.hash, + (self.key, value), + make_hasher::(&self.table.hash_builder), + ); + &mut entry.1 + } + + #[cfg_attr(feature = "inline-more", inline)] + fn insert_entry(self, value: V) -> OccupiedEntry<'a, K, V, S, A> + where + K: Hash, + S: BuildHasher, + { + let elem = self.table.table.insert( + self.hash, + (self.key, value), + make_hasher::(&self.table.hash_builder), + ); + OccupiedEntry { + hash: self.hash, + key: None, + elem, + table: self.table, + } + } +} + +impl<'a, 'b, K, Q: ?Sized, V, S, A: Allocator + Clone> EntryRef<'a, 'b, K, Q, V, S, A> { + /// Sets the value of the entry, and returns an OccupiedEntryRef. + /// + /// # Examples + /// + /// ``` + /// use hashbrown::HashMap; + /// + /// let mut map: HashMap = HashMap::new(); + /// let entry = map.entry_ref("horseyland").insert(37); + /// + /// assert_eq!(entry.key(), "horseyland"); + /// ``` + #[cfg_attr(feature = "inline-more", inline)] + pub fn insert(self, value: V) -> OccupiedEntryRef<'a, 'b, K, Q, V, S, A> + where + K: Hash + From<&'b Q>, + S: BuildHasher, + { + match self { + EntryRef::Occupied(mut entry) => { + entry.insert(value); + entry + } + EntryRef::Vacant(entry) => entry.insert_entry(value), + } + } + + /// Ensures a value is in the entry by inserting the default if empty, and returns + /// a mutable reference to the value in the entry. + /// + /// # Examples + /// + /// ``` + /// use hashbrown::HashMap; + /// + /// let mut map: HashMap = HashMap::new(); + /// + /// map.entry_ref("poneyland").or_insert(3); + /// assert_eq!(map["poneyland"], 3); + /// + /// *map.entry_ref("poneyland").or_insert(10) *= 2; + /// assert_eq!(map["poneyland"], 6); + /// ``` + #[cfg_attr(feature = "inline-more", inline)] + pub fn or_insert(self, default: V) -> &'a mut V + where + K: Hash + From<&'b Q>, + S: BuildHasher, + { + match self { + EntryRef::Occupied(entry) => entry.into_mut(), + EntryRef::Vacant(entry) => entry.insert(default), + } + } + + /// Ensures a value is in the entry by inserting the result of the default function if empty, + /// and returns a mutable reference to the value in the entry. + /// + /// # Examples + /// + /// ``` + /// use hashbrown::HashMap; + /// + /// let mut map: HashMap = HashMap::new(); + /// let s = "hoho".to_string(); + /// + /// map.entry_ref("poneyland").or_insert_with(|| s); + /// + /// assert_eq!(map["poneyland"], "hoho".to_string()); + /// ``` + #[cfg_attr(feature = "inline-more", inline)] + pub fn or_insert_with V>(self, default: F) -> &'a mut V + where + K: Hash + From<&'b Q>, + S: BuildHasher, + { + match self { + EntryRef::Occupied(entry) => entry.into_mut(), + EntryRef::Vacant(entry) => entry.insert(default()), + } + } + + /// Ensures a value is in the entry by inserting, if empty, the result of the default function. + /// This method allows for generating key-derived values for insertion by providing the default + /// function a reference to the key that was moved during the `.entry_ref(key)` method call. + /// + /// The reference to the moved key is provided so that cloning or copying the key is + /// unnecessary, unlike with `.or_insert_with(|| ... )`. + /// + /// # Examples + /// + /// ``` + /// use hashbrown::HashMap; + /// + /// let mut map: HashMap = HashMap::new(); + /// + /// map.entry_ref("poneyland").or_insert_with_key(|key| key.chars().count()); + /// + /// assert_eq!(map["poneyland"], 9); + /// ``` + #[cfg_attr(feature = "inline-more", inline)] + pub fn or_insert_with_key V>(self, default: F) -> &'a mut V + where + K: Hash + Borrow + From<&'b Q>, + S: BuildHasher, + { + match self { + EntryRef::Occupied(entry) => entry.into_mut(), + EntryRef::Vacant(entry) => { + let value = default(entry.key.as_ref()); + entry.insert(value) + } + } + } + + /// Returns a reference to this entry's key. + /// + /// # Examples + /// + /// ``` + /// use hashbrown::HashMap; + /// + /// let mut map: HashMap = HashMap::new(); + /// assert_eq!(map.entry_ref("poneyland").key(), "poneyland"); + /// ``` + #[cfg_attr(feature = "inline-more", inline)] + pub fn key(&self) -> &Q + where + K: Borrow, + { + match *self { + EntryRef::Occupied(ref entry) => entry.key(), + EntryRef::Vacant(ref entry) => entry.key(), + } + } + + /// Provides in-place mutable access to an occupied entry before any + /// potential inserts into the map. + /// + /// # Examples + /// + /// ``` + /// use hashbrown::HashMap; + /// + /// let mut map: HashMap = HashMap::new(); + /// + /// map.entry_ref("poneyland") + /// .and_modify(|e| { *e += 1 }) + /// .or_insert(42); + /// assert_eq!(map["poneyland"], 42); + /// + /// map.entry_ref("poneyland") + /// .and_modify(|e| { *e += 1 }) + /// .or_insert(42); + /// assert_eq!(map["poneyland"], 43); + /// ``` + #[cfg_attr(feature = "inline-more", inline)] + pub fn and_modify(self, f: F) -> Self + where + F: FnOnce(&mut V), + { + match self { + EntryRef::Occupied(mut entry) => { + f(entry.get_mut()); + EntryRef::Occupied(entry) + } + EntryRef::Vacant(entry) => EntryRef::Vacant(entry), + } + } + + /// Provides shared access to the key and owned access to the value of + /// an occupied entry and allows to replace or remove it based on the + /// value of the returned option. + /// + /// # Examples + /// + /// ``` + /// use hashbrown::HashMap; + /// use hashbrown::hash_map::EntryRef; + /// + /// let mut map: HashMap = HashMap::new(); + /// + /// let entry = map + /// .entry_ref("poneyland") + /// .and_replace_entry_with(|_k, _v| panic!()); + /// + /// match entry { + /// EntryRef::Vacant(e) => { + /// assert_eq!(e.key(), "poneyland"); + /// } + /// EntryRef::Occupied(_) => panic!(), + /// } + /// + /// map.insert("poneyland".to_string(), 42); + /// + /// let entry = map + /// .entry_ref("poneyland") + /// .and_replace_entry_with(|k, v| { + /// assert_eq!(k, "poneyland"); + /// assert_eq!(v, 42); + /// Some(v + 1) + /// }); + /// + /// match entry { + /// EntryRef::Occupied(e) => { + /// assert_eq!(e.key(), "poneyland"); + /// assert_eq!(e.get(), &43); + /// } + /// EntryRef::Vacant(_) => panic!(), + /// } + /// + /// assert_eq!(map["poneyland"], 43); + /// + /// let entry = map + /// .entry_ref("poneyland") + /// .and_replace_entry_with(|_k, _v| None); + /// + /// match entry { + /// EntryRef::Vacant(e) => assert_eq!(e.key(), "poneyland"), + /// EntryRef::Occupied(_) => panic!(), + /// } + /// + /// assert!(!map.contains_key("poneyland")); + /// ``` + #[cfg_attr(feature = "inline-more", inline)] + pub fn and_replace_entry_with(self, f: F) -> Self + where + F: FnOnce(&Q, V) -> Option, + K: Borrow, + { + match self { + EntryRef::Occupied(entry) => entry.replace_entry_with(f), + EntryRef::Vacant(_) => self, + } + } +} + +impl<'a, 'b, K, Q: ?Sized, V: Default, S, A: Allocator + Clone> EntryRef<'a, 'b, K, Q, V, S, A> { + /// Ensures a value is in the entry by inserting the default value if empty, + /// and returns a mutable reference to the value in the entry. + /// + /// # Examples + /// + /// ``` + /// use hashbrown::HashMap; + /// + /// let mut map: HashMap<&str, Option> = HashMap::new(); + /// map.entry("poneyland").or_default(); + /// + /// assert_eq!(map["poneyland"], None); + /// ``` + #[cfg_attr(feature = "inline-more", inline)] + pub fn or_default(self) -> &'a mut V + where + K: Hash + From<&'b Q>, + S: BuildHasher, + { + match self { + EntryRef::Occupied(entry) => entry.into_mut(), + EntryRef::Vacant(entry) => entry.insert(Default::default()), + } + } +} + +impl<'a, 'b, K, Q: ?Sized, V, S, A: Allocator + Clone> OccupiedEntryRef<'a, 'b, K, Q, V, S, A> { + /// Gets a reference to the key in the entry. + /// + /// # Examples + /// + /// ``` + /// use hashbrown::HashMap; + /// + /// let mut map: HashMap = HashMap::new(); + /// map.entry_ref("poneyland").or_insert(12); + /// assert_eq!(map.entry_ref("poneyland").key(), "poneyland"); + /// ``` + #[cfg_attr(feature = "inline-more", inline)] + pub fn key(&self) -> &Q + where + K: Borrow, + { + unsafe { &self.elem.as_ref().0 }.borrow() + } + + /// Take the ownership of the key and value from the map. + /// + /// # Examples + /// + /// ``` + /// use hashbrown::HashMap; + /// use hashbrown::hash_map::EntryRef; + /// + /// let mut map: HashMap = HashMap::new(); + /// map.entry_ref("poneyland").or_insert(12); + /// + /// if let EntryRef::Occupied(o) = map.entry_ref("poneyland") { + /// // We delete the entry from the map. + /// o.remove_entry(); + /// } + /// + /// assert_eq!(map.contains_key("poneyland"), false); + /// ``` + #[cfg_attr(feature = "inline-more", inline)] + pub fn remove_entry(self) -> (K, V) { + unsafe { self.table.table.remove(self.elem) } + } + + /// Gets a reference to the value in the entry. + /// + /// # Examples + /// + /// ``` + /// use hashbrown::HashMap; + /// use hashbrown::hash_map::EntryRef; + /// + /// let mut map: HashMap = HashMap::new(); + /// map.entry_ref("poneyland").or_insert(12); + /// + /// if let EntryRef::Occupied(o) = map.entry_ref("poneyland") { + /// assert_eq!(o.get(), &12); + /// } + /// ``` + #[cfg_attr(feature = "inline-more", inline)] + pub fn get(&self) -> &V { + unsafe { &self.elem.as_ref().1 } + } + + /// Gets a mutable reference to the value in the entry. + /// + /// If you need a reference to the `OccupiedEntryRef` which may outlive the + /// destruction of the `EntryRef` value, see [`into_mut`]. + /// + /// [`into_mut`]: #method.into_mut + /// + /// # Examples + /// + /// ``` + /// use hashbrown::HashMap; + /// use hashbrown::hash_map::EntryRef; + /// + /// let mut map: HashMap = HashMap::new(); + /// map.entry_ref("poneyland").or_insert(12); + /// + /// assert_eq!(map["poneyland"], 12); + /// if let EntryRef::Occupied(mut o) = map.entry_ref("poneyland") { + /// *o.get_mut() += 10; + /// assert_eq!(*o.get(), 22); + /// + /// // We can use the same Entry multiple times. + /// *o.get_mut() += 2; + /// } + /// + /// assert_eq!(map["poneyland"], 24); + /// ``` + #[cfg_attr(feature = "inline-more", inline)] + pub fn get_mut(&mut self) -> &mut V { + unsafe { &mut self.elem.as_mut().1 } + } + + /// Converts the OccupiedEntryRef into a mutable reference to the value in the entry + /// with a lifetime bound to the map itself. + /// + /// If you need multiple references to the `OccupiedEntryRef`, see [`get_mut`]. + /// + /// [`get_mut`]: #method.get_mut + /// + /// # Examples + /// + /// ``` + /// use hashbrown::HashMap; + /// use hashbrown::hash_map::EntryRef; + /// + /// let mut map: HashMap = HashMap::new(); + /// map.entry_ref("poneyland").or_insert(12); + /// + /// assert_eq!(map["poneyland"], 12); + /// if let EntryRef::Occupied(o) = map.entry_ref("poneyland") { + /// *o.into_mut() += 10; + /// } + /// + /// assert_eq!(map["poneyland"], 22); + /// ``` + #[cfg_attr(feature = "inline-more", inline)] + pub fn into_mut(self) -> &'a mut V { + unsafe { &mut self.elem.as_mut().1 } + } + + /// Sets the value of the entry, and returns the entry's old value. + /// + /// # Examples + /// + /// ``` + /// use hashbrown::HashMap; + /// use hashbrown::hash_map::EntryRef; + /// + /// let mut map: HashMap = HashMap::new(); + /// map.entry_ref("poneyland").or_insert(12); + /// + /// if let EntryRef::Occupied(mut o) = map.entry_ref("poneyland") { + /// assert_eq!(o.insert(15), 12); + /// } + /// + /// assert_eq!(map["poneyland"], 15); + /// ``` + #[cfg_attr(feature = "inline-more", inline)] + pub fn insert(&mut self, mut value: V) -> V { + let old_value = self.get_mut(); + mem::swap(&mut value, old_value); + value + } + + /// Takes the value out of the entry, and returns it. + /// + /// # Examples + /// + /// ``` + /// use hashbrown::HashMap; + /// use hashbrown::hash_map::EntryRef; + /// + /// let mut map: HashMap = HashMap::new(); + /// map.entry_ref("poneyland").or_insert(12); + /// + /// if let EntryRef::Occupied(o) = map.entry_ref("poneyland") { + /// assert_eq!(o.remove(), 12); + /// } + /// + /// assert_eq!(map.contains_key("poneyland"), false); + /// ``` + #[cfg_attr(feature = "inline-more", inline)] + pub fn remove(self) -> V { + self.remove_entry().1 + } + + /// Replaces the entry, returning the old key and value. The new key in the hash map will be + /// the key used to create this entry. + /// + /// # Panics + /// + /// Will panic if this OccupiedEntry was created through [`EntryRef::insert`]. + /// + /// # Examples + /// + /// ``` + /// use hashbrown::hash_map::{EntryRef, HashMap}; + /// use std::rc::Rc; + /// + /// let mut map: HashMap, u32> = HashMap::new(); + /// map.insert(Rc::from("Stringthing"), 15); + /// + /// if let EntryRef::Occupied(entry) = map.entry_ref("Stringthing") { + /// // Also replace the key with a handle to our other key. + /// let (old_key, old_value): (Rc, u32) = entry.replace_entry(16); + /// } + /// + /// ``` + #[cfg_attr(feature = "inline-more", inline)] + pub fn replace_entry(self, value: V) -> (K, V) + where + K: From<&'b Q>, + { + let entry = unsafe { self.elem.as_mut() }; + + let old_key = mem::replace(&mut entry.0, self.key.unwrap().into_owned()); + let old_value = mem::replace(&mut entry.1, value); + + (old_key, old_value) + } + + /// Replaces the key in the hash map with the key used to create this entry. + /// + /// # Panics + /// + /// Will panic if this OccupiedEntry was created through [`Entry::insert`]. + /// + /// # Examples + /// + /// ``` + /// use hashbrown::hash_map::{EntryRef, HashMap}; + /// use std::rc::Rc; + /// + /// let mut map: HashMap, u32> = HashMap::new(); + /// let mut known_strings: Vec> = Vec::new(); + /// + /// // Initialise known strings, run program, etc. + /// + /// reclaim_memory(&mut map, &known_strings); + /// + /// fn reclaim_memory(map: &mut HashMap, u32>, known_strings: &[Rc] ) { + /// for s in known_strings { + /// if let EntryRef::Occupied(entry) = map.entry_ref(s.as_ref()) { + /// // Replaces the entry's key with our version of it in `known_strings`. + /// entry.replace_key(); + /// } + /// } + /// } + /// ``` + #[cfg_attr(feature = "inline-more", inline)] + pub fn replace_key(self) -> K + where + K: From<&'b Q>, + { + let entry = unsafe { self.elem.as_mut() }; + mem::replace(&mut entry.0, self.key.unwrap().into_owned()) + } + + /// Provides shared access to the key and owned access to the value of + /// the entry and allows to replace or remove it based on the + /// value of the returned option. + /// + /// # Examples + /// + /// ``` + /// use hashbrown::HashMap; + /// use hashbrown::hash_map::EntryRef; + /// + /// let mut map: HashMap = HashMap::new(); + /// map.insert("poneyland".to_string(), 42); + /// + /// let entry = match map.entry_ref("poneyland") { + /// EntryRef::Occupied(e) => { + /// e.replace_entry_with(|k, v| { + /// assert_eq!(k, "poneyland"); + /// assert_eq!(v, 42); + /// Some(v + 1) + /// }) + /// } + /// EntryRef::Vacant(_) => panic!(), + /// }; + /// + /// match entry { + /// EntryRef::Occupied(e) => { + /// assert_eq!(e.key(), "poneyland"); + /// assert_eq!(e.get(), &43); + /// } + /// EntryRef::Vacant(_) => panic!(), + /// } + /// + /// assert_eq!(map["poneyland"], 43); + /// + /// let entry = match map.entry_ref("poneyland") { + /// EntryRef::Occupied(e) => e.replace_entry_with(|_k, _v| None), + /// EntryRef::Vacant(_) => panic!(), + /// }; + /// + /// match entry { + /// EntryRef::Vacant(e) => { + /// assert_eq!(e.key(), "poneyland"); /// } - /// Entry::Occupied(_) => panic!(), + /// EntryRef::Occupied(_) => panic!(), /// } /// /// assert!(!map.contains_key("poneyland")); /// ``` #[cfg_attr(feature = "inline-more", inline)] - pub fn replace_entry_with(self, f: F) -> Entry<'a, K, V, S, A> + pub fn replace_entry_with(self, f: F) -> EntryRef<'a, 'b, K, Q, V, S, A> where - F: FnOnce(&K, V) -> Option, + F: FnOnce(&Q, V) -> Option, + K: Borrow, { unsafe { let mut spare_key = None; @@ -3254,42 +4418,46 @@ impl<'a, K, V, S, A: Allocator + Clone> OccupiedEntry<'a, K, V, S, A> { self.table .table .replace_bucket_with(self.elem.clone(), |(key, value)| { - if let Some(new_value) = f(&key, value) { + if let Some(new_value) = f(key.borrow(), value) { Some((key, new_value)) } else { - spare_key = Some(key); + spare_key = Some(KeyOrRef::Owned(key)); None } }); if let Some(key) = spare_key { - Entry::Vacant(VacantEntry { + EntryRef::Vacant(VacantEntryRef { hash: self.hash, key, table: self.table, }) } else { - Entry::Occupied(self) + EntryRef::Occupied(self) } } } } -impl<'a, K, V, S, A: Allocator + Clone> VacantEntry<'a, K, V, S, A> { +impl<'a, 'b, K, Q: ?Sized, V, S, A: Allocator + Clone> VacantEntryRef<'a, 'b, K, Q, V, S, A> { /// Gets a reference to the key that would be used when inserting a value - /// through the `VacantEntry`. + /// through the `VacantEntryRef`. /// /// # Examples /// /// ``` /// use hashbrown::HashMap; /// - /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// assert_eq!(map.entry("poneyland").key(), &"poneyland"); + /// let mut map: HashMap = HashMap::new(); + /// let key: &str = "poneyland"; + /// assert_eq!(map.entry_ref(key).key(), "poneyland"); /// ``` #[cfg_attr(feature = "inline-more", inline)] - pub fn key(&self) -> &K { - &self.key + pub fn key(&self) -> &Q + where + K: Borrow, + { + self.key.as_ref() } /// Take ownership of the key. @@ -3298,31 +4466,36 @@ impl<'a, K, V, S, A: Allocator + Clone> VacantEntry<'a, K, V, S, A> { /// /// ``` /// use hashbrown::HashMap; - /// use hashbrown::hash_map::Entry; + /// use hashbrown::hash_map::EntryRef; /// - /// let mut map: HashMap<&str, u32> = HashMap::new(); + /// let mut map: HashMap = HashMap::new(); + /// let key: &str = "poneyland"; /// - /// if let Entry::Vacant(v) = map.entry("poneyland") { + /// if let EntryRef::Vacant(v) = map.entry_ref(key) { /// v.into_key(); /// } /// ``` #[cfg_attr(feature = "inline-more", inline)] - pub fn into_key(self) -> K { - self.key + pub fn into_key(self) -> K + where + K: From<&'b Q>, + { + self.key.into_owned() } - /// Sets the value of the entry with the VacantEntry's key, + /// Sets the value of the entry with the VacantEntryRef's key, /// and returns a mutable reference to it. /// /// # Examples /// /// ``` /// use hashbrown::HashMap; - /// use hashbrown::hash_map::Entry; + /// use hashbrown::hash_map::EntryRef; /// - /// let mut map: HashMap<&str, u32> = HashMap::new(); + /// let mut map: HashMap = HashMap::new(); + /// let key: &str = "poneyland"; /// - /// if let Entry::Vacant(o) = map.entry("poneyland") { + /// if let EntryRef::Vacant(o) = map.entry_ref(key) { /// o.insert(37); /// } /// assert_eq!(map["poneyland"], 37); @@ -3330,30 +4503,30 @@ impl<'a, K, V, S, A: Allocator + Clone> VacantEntry<'a, K, V, S, A> { #[cfg_attr(feature = "inline-more", inline)] pub fn insert(self, value: V) -> &'a mut V where - K: Hash, + K: Hash + From<&'b Q>, S: BuildHasher, { let table = &mut self.table.table; let entry = table.insert_entry( self.hash, - (self.key, value), + (self.key.into_owned(), value), make_hasher::(&self.table.hash_builder), ); &mut entry.1 } #[cfg_attr(feature = "inline-more", inline)] - fn insert_entry(self, value: V) -> OccupiedEntry<'a, K, V, S, A> + fn insert_entry(self, value: V) -> OccupiedEntryRef<'a, 'b, K, Q, V, S, A> where - K: Hash, + K: Hash + From<&'b Q>, S: BuildHasher, { let elem = self.table.table.insert( self.hash, - (self.key, value), + (self.key.into_owned(), value), make_hasher::(&self.table.hash_builder), ); - OccupiedEntry { + OccupiedEntryRef { hash: self.hash, key: None, elem, @@ -3500,8 +4673,8 @@ fn assert_covariance() { mod test_map { use super::DefaultHashBuilder; use super::Entry::{Occupied, Vacant}; + use super::EntryRef; use super::{HashMap, RawEntryMut}; - use crate::TryReserveError::*; use rand::{rngs::SmallRng, Rng, SeedableRng}; use std::borrow::ToOwned; use std::cell::RefCell; @@ -3570,6 +4743,7 @@ mod test_map { assert_eq!(m.len(), 1); assert!(m.insert(2, 4).is_none()); assert_eq!(m.len(), 2); + #[allow(clippy::redundant_clone)] let m2 = m.clone(); assert_eq!(*m2.get(&1).unwrap(), 2); assert_eq!(*m2.get(&2).unwrap(), 4); @@ -3723,6 +4897,7 @@ mod test_map { } }); + #[allow(clippy::let_underscore_drop)] // kind-of a false positive for _ in half.by_ref() {} DROP_VECTOR.with(|v| { @@ -3759,6 +4934,17 @@ mod test_map { assert_eq!(m.len(), 1); } + #[test] + fn test_empty_entry_ref() { + let mut m: HashMap = HashMap::new(); + match m.entry_ref("poneyland") { + EntryRef::Occupied(_) => panic!(), + EntryRef::Vacant(_) => {} + } + assert!(*m.entry_ref("poneyland").or_insert(true)); + assert_eq!(m.len(), 1); + } + #[test] fn test_empty_iter() { let mut m: HashMap = HashMap::new(); @@ -3888,6 +5074,18 @@ mod test_map { assert_eq!(*m.get(&5).unwrap(), 3); } + #[test] + fn test_insert_unique_unchecked() { + let mut map = HashMap::new(); + let (k1, v1) = map.insert_unique_unchecked(10, 11); + assert_eq!((&10, &mut 11), (k1, v1)); + let (k2, v2) = map.insert_unique_unchecked(20, 21); + assert_eq!((&20, &mut 21), (k2, v2)); + assert_eq!(Some(&11), map.get(&10)); + assert_eq!(Some(&21), map.get(&20)); + assert_eq!(None, map.get(&30)); + } + #[test] fn test_is_empty() { let mut m = HashMap::with_capacity(4); @@ -3934,7 +5132,7 @@ mod test_map { fn test_keys() { let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')]; let map: HashMap<_, _> = vec.into_iter().collect(); - let keys: Vec<_> = map.keys().cloned().collect(); + let keys: Vec<_> = map.keys().copied().collect(); assert_eq!(keys.len(), 3); assert!(keys.contains(&1)); assert!(keys.contains(&2)); @@ -3945,7 +5143,7 @@ mod test_map { fn test_values() { let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')]; let map: HashMap<_, _> = vec.into_iter().collect(); - let values: Vec<_> = map.values().cloned().collect(); + let values: Vec<_> = map.values().copied().collect(); assert_eq!(values.len(), 3); assert!(values.contains(&'a')); assert!(values.contains(&'b')); @@ -3957,15 +5155,39 @@ mod test_map { let vec = vec![(1, 1), (2, 2), (3, 3)]; let mut map: HashMap<_, _> = vec.into_iter().collect(); for value in map.values_mut() { - *value = (*value) * 2 + *value *= 2; } - let values: Vec<_> = map.values().cloned().collect(); + let values: Vec<_> = map.values().copied().collect(); assert_eq!(values.len(), 3); assert!(values.contains(&2)); assert!(values.contains(&4)); assert!(values.contains(&6)); } + #[test] + fn test_into_keys() { + let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')]; + let map: HashMap<_, _> = vec.into_iter().collect(); + let keys: Vec<_> = map.into_keys().collect(); + + assert_eq!(keys.len(), 3); + assert!(keys.contains(&1)); + assert!(keys.contains(&2)); + assert!(keys.contains(&3)); + } + + #[test] + fn test_into_values() { + let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')]; + let map: HashMap<_, _> = vec.into_iter().collect(); + let values: Vec<_> = map.into_values().collect(); + + assert_eq!(values.len(), 3); + assert!(values.contains(&'a')); + assert!(values.contains(&'b')); + assert!(values.contains(&'c')); + } + #[test] fn test_find() { let mut m = HashMap::new(); @@ -4124,7 +5346,7 @@ mod test_map { fn test_from_iter() { let xs = [(1, 1), (2, 2), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)]; - let map: HashMap<_, _> = xs.iter().cloned().collect(); + let map: HashMap<_, _> = xs.iter().copied().collect(); for &(k, v) in &xs { assert_eq!(map.get(&k), Some(&v)); @@ -4137,7 +5359,7 @@ mod test_map { fn test_size_hint() { let xs = [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)]; - let map: HashMap<_, _> = xs.iter().cloned().collect(); + let map: HashMap<_, _> = xs.iter().copied().collect(); let mut iter = map.iter(); @@ -4150,7 +5372,7 @@ mod test_map { fn test_iter_len() { let xs = [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)]; - let map: HashMap<_, _> = xs.iter().cloned().collect(); + let map: HashMap<_, _> = xs.iter().copied().collect(); let mut iter = map.iter(); @@ -4163,7 +5385,7 @@ mod test_map { fn test_mut_size_hint() { let xs = [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)]; - let mut map: HashMap<_, _> = xs.iter().cloned().collect(); + let mut map: HashMap<_, _> = xs.iter().copied().collect(); let mut iter = map.iter_mut(); @@ -4176,7 +5398,7 @@ mod test_map { fn test_iter_mut_len() { let xs = [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)]; - let mut map: HashMap<_, _> = xs.iter().cloned().collect(); + let mut map: HashMap<_, _> = xs.iter().copied().collect(); let mut iter = map.iter_mut(); @@ -4205,6 +5427,7 @@ mod test_map { map.insert(2, 1); map.insert(3, 4); + #[allow(clippy::no_effect)] // false positive lint map[&4]; } @@ -4212,7 +5435,7 @@ mod test_map { fn test_entry() { let xs = [(1, 10), (2, 20), (3, 30), (4, 40), (5, 50), (6, 60)]; - let mut map: HashMap<_, _> = xs.iter().cloned().collect(); + let mut map: HashMap<_, _> = xs.iter().copied().collect(); // Existing key (insert) match map.entry(1) { @@ -4258,6 +5481,63 @@ mod test_map { assert_eq!(map.len(), 6); } + #[test] + fn test_entry_ref() { + let xs = [ + ("One".to_owned(), 10), + ("Two".to_owned(), 20), + ("Three".to_owned(), 30), + ("Four".to_owned(), 40), + ("Five".to_owned(), 50), + ("Six".to_owned(), 60), + ]; + + let mut map: HashMap<_, _> = xs.iter().cloned().collect(); + + // Existing key (insert) + match map.entry_ref("One") { + EntryRef::Vacant(_) => unreachable!(), + EntryRef::Occupied(mut view) => { + assert_eq!(view.get(), &10); + assert_eq!(view.insert(100), 10); + } + } + assert_eq!(map.get("One").unwrap(), &100); + assert_eq!(map.len(), 6); + + // Existing key (update) + match map.entry_ref("Two") { + EntryRef::Vacant(_) => unreachable!(), + EntryRef::Occupied(mut view) => { + let v = view.get_mut(); + let new_v = (*v) * 10; + *v = new_v; + } + } + assert_eq!(map.get("Two").unwrap(), &200); + assert_eq!(map.len(), 6); + + // Existing key (take) + match map.entry_ref("Three") { + EntryRef::Vacant(_) => unreachable!(), + EntryRef::Occupied(view) => { + assert_eq!(view.remove(), 30); + } + } + assert_eq!(map.get("Three"), None); + assert_eq!(map.len(), 5); + + // Inexistent key (insert) + match map.entry_ref("Ten") { + EntryRef::Occupied(_) => unreachable!(), + EntryRef::Vacant(view) => { + assert_eq!(*view.insert(1000), 1000); + } + } + assert_eq!(map.get("Ten").unwrap(), &1000); + assert_eq!(map.len(), 6); + } + #[test] fn test_entry_take_doesnt_corrupt() { #![allow(deprecated)] //rand @@ -4271,18 +5551,18 @@ mod test_map { let mut m = HashMap::new(); let mut rng = { - let seed = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; - SmallRng::from_seed(seed) + let seed = u64::from_le_bytes(*b"testseed"); + SmallRng::seed_from_u64(seed) }; // Populate the map with some items. for _ in 0..50 { - let x = rng.gen_range(-10, 10); + let x = rng.gen_range(-10..10); m.insert(x, ()); } for _ in 0..1000 { - let x = rng.gen_range(-10, 10); + let x = rng.gen_range(-10..10); match m.entry(x) { Vacant(_) => {} Occupied(e) => { @@ -4294,6 +5574,44 @@ mod test_map { } } + #[test] + fn test_entry_ref_take_doesnt_corrupt() { + #![allow(deprecated)] //rand + // Test for #19292 + fn check(m: &HashMap) { + for k in m.keys() { + assert!(m.contains_key(k), "{} is in keys() but not in the map?", k); + } + } + + let mut m = HashMap::new(); + + let mut rng = { + let seed = u64::from_le_bytes(*b"testseed"); + SmallRng::seed_from_u64(seed) + }; + + // Populate the map with some items. + for _ in 0..50 { + let mut x = std::string::String::with_capacity(1); + x.push(rng.gen_range('a'..='z')); + m.insert(x, ()); + } + + for _ in 0..1000 { + let mut x = std::string::String::with_capacity(1); + x.push(rng.gen_range('a'..='z')); + match m.entry_ref(x.as_str()) { + EntryRef::Vacant(_) => {} + EntryRef::Occupied(e) => { + e.remove(); + } + } + + check(&m); + } + } + #[test] fn test_extend_ref() { let mut a = HashMap::new(); @@ -4341,11 +5659,11 @@ mod test_map { let key = "hello there"; let value = "value goes here"; assert!(a.is_empty()); - a.insert(key.clone(), value.clone()); + a.insert(key, value); assert_eq!(a.len(), 1); assert_eq!(a[key], value); - match a.entry(key.clone()) { + match a.entry(key) { Vacant(_) => panic!(), Occupied(e) => assert_eq!(key, *e.key()), } @@ -4353,6 +5671,24 @@ mod test_map { assert_eq!(a[key], value); } + #[test] + fn test_occupied_entry_ref_key() { + let mut a = HashMap::new(); + let key = "hello there"; + let value = "value goes here"; + assert!(a.is_empty()); + a.insert(key.to_owned(), value); + assert_eq!(a.len(), 1); + assert_eq!(a[key], value); + + match a.entry_ref(key) { + EntryRef::Vacant(_) => panic!(), + EntryRef::Occupied(e) => assert_eq!(key, e.key()), + } + assert_eq!(a.len(), 1); + assert_eq!(a[key], value); + } + #[test] fn test_vacant_entry_key() { let mut a = HashMap::new(); @@ -4360,11 +5696,29 @@ mod test_map { let value = "value goes here"; assert!(a.is_empty()); - match a.entry(key.clone()) { + match a.entry(key) { Occupied(_) => panic!(), Vacant(e) => { assert_eq!(key, *e.key()); - e.insert(value.clone()); + e.insert(value); + } + } + assert_eq!(a.len(), 1); + assert_eq!(a[key], value); + } + + #[test] + fn test_vacant_entry_ref_key() { + let mut a: HashMap = HashMap::new(); + let key = "hello there"; + let value = "value goes here"; + + assert!(a.is_empty()); + match a.entry_ref(key) { + EntryRef::Occupied(_) => panic!(), + EntryRef::Vacant(e) => { + assert_eq!(key, e.key()); + e.insert(value); } } assert_eq!(a.len(), 1); @@ -4414,6 +5768,49 @@ mod test_map { assert_eq!(a.len(), 0); } + #[test] + fn test_occupied_entry_ref_replace_entry_with() { + let mut a: HashMap = HashMap::new(); + + let key = "a key"; + let value = "an initial value"; + let new_value = "a new value"; + + let entry = a.entry_ref(key).insert(value).replace_entry_with(|k, v| { + assert_eq!(k, key); + assert_eq!(v, value); + Some(new_value) + }); + + match entry { + EntryRef::Occupied(e) => { + assert_eq!(e.key(), key); + assert_eq!(e.get(), &new_value); + } + EntryRef::Vacant(_) => panic!(), + } + + assert_eq!(a[key], new_value); + assert_eq!(a.len(), 1); + + let entry = match a.entry_ref(key) { + EntryRef::Occupied(e) => e.replace_entry_with(|k, v| { + assert_eq!(k, key); + assert_eq!(v, new_value); + None + }), + EntryRef::Vacant(_) => panic!(), + }; + + match entry { + EntryRef::Vacant(e) => assert_eq!(e.key(), key), + EntryRef::Occupied(_) => panic!(), + } + + assert!(!a.contains_key(key)); + assert_eq!(a.len(), 0); + } + #[test] fn test_entry_and_replace_entry_with() { let mut a = HashMap::new(); @@ -4463,6 +5860,55 @@ mod test_map { assert_eq!(a.len(), 0); } + #[test] + fn test_entry_ref_and_replace_entry_with() { + let mut a = HashMap::new(); + + let key = "a key"; + let value = "an initial value"; + let new_value = "a new value"; + + let entry = a.entry_ref(key).and_replace_entry_with(|_, _| panic!()); + + match entry { + EntryRef::Vacant(e) => assert_eq!(e.key(), key), + EntryRef::Occupied(_) => panic!(), + } + + a.insert(key.to_owned(), value); + + let entry = a.entry_ref(key).and_replace_entry_with(|k, v| { + assert_eq!(k, key); + assert_eq!(v, value); + Some(new_value) + }); + + match entry { + EntryRef::Occupied(e) => { + assert_eq!(e.key(), key); + assert_eq!(e.get(), &new_value); + } + EntryRef::Vacant(_) => panic!(), + } + + assert_eq!(a[key], new_value); + assert_eq!(a.len(), 1); + + let entry = a.entry_ref(key).and_replace_entry_with(|k, v| { + assert_eq!(k, key); + assert_eq!(v, new_value); + None + }); + + match entry { + EntryRef::Vacant(e) => assert_eq!(e.key(), key), + EntryRef::Occupied(_) => panic!(), + } + + assert!(!a.contains_key(key)); + assert_eq!(a.len(), 0); + } + #[test] fn test_raw_occupied_entry_replace_entry_with() { let mut a = HashMap::new(); @@ -4581,23 +6027,55 @@ mod test_map { let mut m = HashMap::new(); let mut rng = { - let seed = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; - SmallRng::from_seed(seed) + let seed = u64::from_le_bytes(*b"testseed"); + SmallRng::seed_from_u64(seed) }; // Populate the map with some items. for _ in 0..50 { - let x = rng.gen_range(-10, 10); + let x = rng.gen_range(-10..10); m.insert(x, ()); } for _ in 0..1000 { - let x = rng.gen_range(-10, 10); + let x = rng.gen_range(-10..10); m.entry(x).and_replace_entry_with(|_, _| None); check(&m); } } + #[test] + fn test_replace_entry_ref_with_doesnt_corrupt() { + #![allow(deprecated)] //rand + // Test for #19292 + fn check(m: &HashMap) { + for k in m.keys() { + assert!(m.contains_key(k), "{} is in keys() but not in the map?", k); + } + } + + let mut m = HashMap::new(); + + let mut rng = { + let seed = u64::from_le_bytes(*b"testseed"); + SmallRng::seed_from_u64(seed) + }; + + // Populate the map with some items. + for _ in 0..50 { + let mut x = std::string::String::with_capacity(1); + x.push(rng.gen_range('a'..='z')); + m.insert(x, ()); + } + + for _ in 0..1000 { + let mut x = std::string::String::with_capacity(1); + x.push(rng.gen_range('a'..='z')); + m.entry_ref(x.as_str()).and_replace_entry_with(|_, _| None); + check(&m); + } + } + #[test] fn test_retain() { let mut map: HashMap = (0..100).map(|x| (x, x * 10)).collect(); @@ -4629,21 +6107,27 @@ mod test_map { #[test] #[cfg_attr(miri, ignore)] // FIXME: no OOM signalling (https://github.com/rust-lang/miri/issues/613) fn test_try_reserve() { - let mut empty_bytes: HashMap = HashMap::new(); + use crate::TryReserveError::{AllocError, CapacityOverflow}; const MAX_USIZE: usize = usize::MAX; + let mut empty_bytes: HashMap = HashMap::new(); + if let Err(CapacityOverflow) = empty_bytes.try_reserve(MAX_USIZE) { } else { panic!("usize::MAX should trigger an overflow!"); } - if let Err(AllocError { .. }) = empty_bytes.try_reserve(MAX_USIZE / 8) { + if let Err(AllocError { .. }) = empty_bytes.try_reserve(MAX_USIZE / 16) { } else { // This may succeed if there is enough free memory. Attempt to - // allocate a second hashmap to ensure the allocation will fail. + // allocate a few more hashmaps to ensure the allocation will fail. let mut empty_bytes2: HashMap = HashMap::new(); - if let Err(AllocError { .. }) = empty_bytes2.try_reserve(MAX_USIZE / 8) { + let _ = empty_bytes2.try_reserve(MAX_USIZE / 16); + let mut empty_bytes3: HashMap = HashMap::new(); + let _ = empty_bytes3.try_reserve(MAX_USIZE / 16); + let mut empty_bytes4: HashMap = HashMap::new(); + if let Err(AllocError { .. }) = empty_bytes4.try_reserve(MAX_USIZE / 16) { } else { panic!("usize::MAX / 8 should trigger an OOM!"); } @@ -4654,9 +6138,9 @@ mod test_map { fn test_raw_entry() { use super::RawEntryMut::{Occupied, Vacant}; - let xs = [(1i32, 10i32), (2, 20), (3, 30), (4, 40), (5, 50), (6, 60)]; + let xs = [(1_i32, 10_i32), (2, 20), (3, 30), (4, 40), (5, 50), (6, 60)]; - let mut map: HashMap<_, _> = xs.iter().cloned().collect(); + let mut map: HashMap<_, _> = xs.iter().copied().collect(); let compute_hash = |map: &HashMap, k: i32| -> u64 { super::make_insert_hash::(map.hasher(), &k) @@ -4729,7 +6213,7 @@ mod test_map { // Ensure all lookup methods produce equivalent results. for k in 0..12 { let hash = compute_hash(&map, k); - let v = map.get(&k).cloned(); + let v = map.get(&k).copied(); let kv = v.as_ref().map(|v| (&k, v)); assert_eq!(map.raw_entry().from_key(&k), kv); @@ -4799,8 +6283,6 @@ mod test_map { #[test] #[cfg(feature = "raw")] fn test_into_iter_refresh() { - use core::hash::{BuildHasher, Hash, Hasher}; - #[cfg(miri)] const N: usize = 32; #[cfg(not(miri))] @@ -4808,13 +6290,13 @@ mod test_map { let mut rng = rand::thread_rng(); for n in 0..N { - let mut m = HashMap::new(); + let mut map = HashMap::new(); for i in 0..n { - assert!(m.insert(i, 2 * i).is_none()); + assert!(map.insert(i, 2 * i).is_none()); } - let hasher = m.hasher().clone(); + let hash_builder = map.hasher().clone(); - let mut it = unsafe { m.table.iter() }; + let mut it = unsafe { map.table.iter() }; assert_eq!(it.len(), n); let mut i = 0; @@ -4823,23 +6305,21 @@ mod test_map { loop { // occasionally remove some elements if i < n && rng.gen_bool(0.1) { - let mut hsh = hasher.build_hasher(); - i.hash(&mut hsh); - let hash = hsh.finish(); + let hash_value = super::make_insert_hash(&hash_builder, &i); unsafe { - let e = m.table.find(hash, |q| q.0.eq(&i)); + let e = map.table.find(hash_value, |q| q.0.eq(&i)); if let Some(e) = e { it.reflect_remove(&e); - let t = m.table.remove(e); + let t = map.table.remove(e); removed.push(t); left -= 1; } else { assert!(removed.contains(&(i, 2 * i)), "{} not in {:?}", i, removed); - let e = m.table.insert( - hash, + let e = map.table.insert( + hash_value, (i, 2 * i), - super::make_hasher::(&hasher), + super::make_hasher::(&hash_builder), ); it.reflect_insert(&e); if let Some(p) = removed.iter().position(|e| e == &(i, 2 * i)) { @@ -4857,14 +6337,14 @@ mod test_map { assert!(i < n); let t = unsafe { e.unwrap().as_ref() }; assert!(!removed.contains(t)); - let (k, v) = t; - assert_eq!(*v, 2 * k); + let (key, value) = t; + assert_eq!(*value, 2 * key); i += 1; } assert!(i <= n); // just for safety: - assert_eq!(m.table.len(), left); + assert_eq!(map.table.len(), left); } } @@ -4886,37 +6366,38 @@ mod test_map { const EMPTY_MAP: HashMap = HashMap::with_hasher(MyHasher); - let mut map = EMPTY_MAP.clone(); + let mut map = EMPTY_MAP; map.insert(17, "seventeen".to_owned()); assert_eq!("seventeen", map[&17]); } #[test] - #[cfg(feature = "nightly")] fn test_get_each_mut() { - use crate::UnavailableMutError::*; - let mut map = HashMap::new(); map.insert("foo".to_owned(), 0); map.insert("bar".to_owned(), 10); map.insert("baz".to_owned(), 20); map.insert("qux".to_owned(), 30); - let xs = map.get_each_mut(["foo", "dud", "foo", "qux"]); - assert_eq!( - xs, - [Ok(&mut 0), Err(Absent), Err(Duplicate(0)), Ok(&mut 30)] - ); + let xs = map.get_many_mut(["foo", "qux"]); + assert_eq!(xs, Some([&mut 0, &mut 30])); - let ys = map.get_each_key_value_mut(["bar", "baz", "baz", "dip"]); + let xs = map.get_many_mut(["foo", "dud"]); + assert_eq!(xs, None); + + let xs = map.get_many_mut(["foo", "foo"]); + assert_eq!(xs, None); + + let ys = map.get_many_key_value_mut(["bar", "baz"]); assert_eq!( ys, - [ - Ok((&"bar".to_owned(), &mut 10)), - Ok((&"baz".to_owned(), &mut 20)), - Err(Duplicate(1)), - Err(Absent), - ] + Some([(&"bar".to_owned(), &mut 10), (&"baz".to_owned(), &mut 20),]), ); + + let ys = map.get_many_key_value_mut(["bar", "dip"]); + assert_eq!(ys, None); + + let ys = map.get_many_key_value_mut(["baz", "baz"]); + assert_eq!(ys, None); } } diff --git a/sgx_tstd/hashbrown/src/raw/alloc.rs b/sgx_tstd/hashbrown/src/raw/alloc.rs index de6c45506..76fe1e923 100644 --- a/sgx_tstd/hashbrown/src/raw/alloc.rs +++ b/sgx_tstd/hashbrown/src/raw/alloc.rs @@ -33,6 +33,7 @@ mod inner { use crate::alloc::alloc::{alloc, dealloc, Layout}; use core::ptr::NonNull; + #[allow(clippy::missing_safety_doc)] // not exposed outside of this crate pub unsafe trait Allocator { fn allocate(&self, layout: Layout) -> Result, ()>; unsafe fn deallocate(&self, ptr: NonNull, layout: Layout); @@ -47,7 +48,7 @@ mod inner { } #[inline] unsafe fn deallocate(&self, ptr: NonNull, layout: Layout) { - dealloc(ptr.as_ptr(), layout) + dealloc(ptr.as_ptr(), layout); } } impl Default for Global { diff --git a/sgx_tstd/hashbrown/src/raw/bitmask.rs b/sgx_tstd/hashbrown/src/raw/bitmask.rs index 99b2d5341..7d4f9fc38 100644 --- a/sgx_tstd/hashbrown/src/raw/bitmask.rs +++ b/sgx_tstd/hashbrown/src/raw/bitmask.rs @@ -106,7 +106,7 @@ impl IntoIterator for BitMask { } } -/// Iterator over the contents of a `BitMask`, returning the indicies of set +/// Iterator over the contents of a `BitMask`, returning the indices of set /// bits. pub struct BitMaskIter(BitMask); diff --git a/sgx_tstd/hashbrown/src/raw/generic.rs b/sgx_tstd/hashbrown/src/raw/generic.rs index ef066e8d0..b4d31e62c 100644 --- a/sgx_tstd/hashbrown/src/raw/generic.rs +++ b/sgx_tstd/hashbrown/src/raw/generic.rs @@ -9,12 +9,14 @@ use core::{mem, ptr}; target_pointer_width = "64", target_arch = "aarch64", target_arch = "x86_64", + target_arch = "wasm32", ))] type GroupWord = u64; #[cfg(all( target_pointer_width = "32", not(target_arch = "aarch64"), not(target_arch = "x86_64"), + not(target_arch = "wasm32"), ))] type GroupWord = u32; @@ -37,7 +39,7 @@ fn repeat(byte: u8) -> GroupWord { #[derive(Copy, Clone)] pub struct Group(GroupWord); -// We perform all operations in the native endianess, and convert to +// We perform all operations in the native endianness, and convert to // little-endian just before creating a BitMask. The can potentially // enable the compiler to eliminate unnecessary byte swaps if we are // only checking whether a BitMask is empty. @@ -50,6 +52,7 @@ impl Group { /// value for an empty hash table. /// /// This is guaranteed to be aligned to the group size. + #[inline] pub const fn static_empty() -> &'static [u8; Group::WIDTH] { #[repr(C)] struct AlignedBytes { @@ -103,7 +106,7 @@ impl Group { #[inline] pub fn match_byte(self, byte: u8) -> BitMask { // This algorithm is derived from - // http://graphics.stanford.edu/~seander/bithacks.html##ValueInWord + // https://graphics.stanford.edu/~seander/bithacks.html##ValueInWord let cmp = self.0 ^ repeat(byte); BitMask((cmp.wrapping_sub(repeat(0x01)) & !cmp & repeat(0x80)).to_le()) } diff --git a/sgx_tstd/hashbrown/src/raw/mod.rs b/sgx_tstd/hashbrown/src/raw/mod.rs index 3ae698033..fce54d9f0 100644 --- a/sgx_tstd/hashbrown/src/raw/mod.rs +++ b/sgx_tstd/hashbrown/src/raw/mod.rs @@ -1,16 +1,13 @@ use crate::alloc::alloc::{handle_alloc_error, Layout}; use crate::scopeguard::guard; use crate::TryReserveError; -#[cfg(feature = "nightly")] -use crate::UnavailableMutError; -use core::hint; use core::iter::FusedIterator; use core::marker::PhantomData; use core::mem; use core::mem::ManuallyDrop; -#[cfg(feature = "nightly")] use core::mem::MaybeUninit; use core::ptr::NonNull; +use core::{hint, ptr}; cfg_if! { // Use the SSE2 implementation if possible: it allows us to scan 16 buckets @@ -59,7 +56,7 @@ fn cold() {} #[inline] fn likely(b: bool) -> bool { if !b { - cold() + cold(); } b } @@ -67,18 +64,18 @@ fn likely(b: bool) -> bool { #[inline] fn unlikely(b: bool) -> bool { if b { - cold() + cold(); } b } #[cfg(feature = "nightly")] -#[cfg_attr(feature = "inline-more", inline)] +#[inline] unsafe fn offset_from(to: *const T, from: *const T) -> usize { to.offset_from(from) as usize } #[cfg(not(feature = "nightly"))] -#[cfg_attr(feature = "inline-more", inline)] +#[inline] unsafe fn offset_from(to: *const T, from: *const T) -> usize { (to as usize - from as usize) / mem::size_of::() } @@ -211,7 +208,7 @@ fn capacity_to_buckets(cap: usize) -> Option { // Any overflows will have been caught by the checked_mul. Also, any // rounding errors from the division above will be cleaned up by - // next_power_of_two (which can't overflow because of the previous divison). + // next_power_of_two (which can't overflow because of the previous division). Some(adjusted_cap.next_power_of_two()) } @@ -292,14 +289,14 @@ pub struct Bucket { unsafe impl Send for Bucket {} impl Clone for Bucket { - #[cfg_attr(feature = "inline-more", inline)] + #[inline] fn clone(&self) -> Self { Self { ptr: self.ptr } } } impl Bucket { - #[cfg_attr(feature = "inline-more", inline)] + #[inline] unsafe fn from_base_index(base: NonNull, index: usize) -> Self { let ptr = if mem::size_of::() == 0 { // won't overflow because index must be less than length @@ -311,7 +308,7 @@ impl Bucket { ptr: NonNull::new_unchecked(ptr), } } - #[cfg_attr(feature = "inline-more", inline)] + #[inline] unsafe fn to_base_index(&self, base: NonNull) -> usize { if mem::size_of::() == 0 { self.ptr.as_ptr() as usize - 1 @@ -319,7 +316,7 @@ impl Bucket { offset_from(base.as_ptr(), self.ptr.as_ptr()) } } - #[cfg_attr(feature = "inline-more", inline)] + #[inline] pub fn as_ptr(&self) -> *mut T { if mem::size_of::() == 0 { // Just return an arbitrary ZST pointer which is properly aligned @@ -328,7 +325,7 @@ impl Bucket { unsafe { self.ptr.as_ptr().sub(1) } } } - #[cfg_attr(feature = "inline-more", inline)] + #[inline] unsafe fn next_n(&self, offset: usize) -> Self { let ptr = if mem::size_of::() == 0 { (self.ptr.as_ptr() as usize + offset) as *mut T @@ -343,23 +340,24 @@ impl Bucket { pub unsafe fn drop(&self) { self.as_ptr().drop_in_place(); } - #[cfg_attr(feature = "inline-more", inline)] + #[inline] pub unsafe fn read(&self) -> T { self.as_ptr().read() } - #[cfg_attr(feature = "inline-more", inline)] + #[inline] pub unsafe fn write(&self, val: T) { self.as_ptr().write(val); } - #[cfg_attr(feature = "inline-more", inline)] + #[inline] pub unsafe fn as_ref<'a>(&self) -> &'a T { &*self.as_ptr() } - #[cfg_attr(feature = "inline-more", inline)] + #[inline] pub unsafe fn as_mut<'a>(&self) -> &'a mut T { &mut *self.as_ptr() } - #[cfg_attr(feature = "inline-more", inline)] + #[cfg(feature = "raw")] + #[inline] pub unsafe fn copy_from_nonoverlapping(&self, other: &Self) { self.as_ptr().copy_from_nonoverlapping(other.as_ptr(), 1); } @@ -398,7 +396,7 @@ impl RawTable { /// In effect this returns a table with exactly 1 bucket. However we can /// leave the data pointer dangling since that bucket is never written to /// due to our load factor forcing us to always have at least 1 free bucket. - #[cfg_attr(feature = "inline-more", inline)] + #[inline] pub const fn new() -> Self { Self { table: RawTableInner::new_in(Global), @@ -427,7 +425,7 @@ impl RawTable { /// In effect this returns a table with exactly 1 bucket. However we can /// leave the data pointer dangling since that bucket is never written to /// due to our load factor forcing us to always have at least 1 free bucket. - #[cfg_attr(feature = "inline-more", inline)] + #[inline] pub fn new_in(alloc: A) -> Self { Self { table: RawTableInner::new_in(alloc), @@ -492,33 +490,39 @@ impl RawTable { } } + /// Returns a reference to the underlying allocator. + #[inline] + pub fn allocator(&self) -> &A { + &self.table.alloc + } + /// Deallocates the table without dropping any entries. #[cfg_attr(feature = "inline-more", inline)] unsafe fn free_buckets(&mut self) { - self.table.free_buckets(TableLayout::new::()) + self.table.free_buckets(TableLayout::new::()); } /// Returns pointer to one past last element of data table. - #[cfg_attr(feature = "inline-more", inline)] + #[inline] pub unsafe fn data_end(&self) -> NonNull { NonNull::new_unchecked(self.table.ctrl.as_ptr().cast()) } /// Returns pointer to start of data table. - #[cfg_attr(feature = "inline-more", inline)] + #[inline] #[cfg(feature = "nightly")] pub unsafe fn data_start(&self) -> *mut T { self.data_end().as_ptr().wrapping_sub(self.buckets()) } /// Returns the index of a bucket from a `Bucket`. - #[cfg_attr(feature = "inline-more", inline)] + #[inline] pub unsafe fn bucket_index(&self, bucket: &Bucket) -> usize { bucket.to_base_index(self.data_end()) } /// Returns a pointer to an element in the table. - #[cfg_attr(feature = "inline-more", inline)] + #[inline] pub unsafe fn bucket(&self, index: usize) -> Bucket { debug_assert_ne!(self.table.bucket_mask, 0); debug_assert!(index < self.buckets()); @@ -530,7 +534,7 @@ impl RawTable { #[deprecated(since = "0.8.1", note = "use erase or remove instead")] pub unsafe fn erase_no_drop(&mut self, item: &Bucket) { let index = self.bucket_index(item); - self.table.erase(index) + self.table.erase(index); } /// Erases an element from the table, dropping it in place. @@ -550,7 +554,9 @@ impl RawTable { pub fn erase_entry(&mut self, hash: u64, eq: impl FnMut(&T) -> bool) -> bool { // Avoid `Option::map` because it bloats LLVM IR. if let Some(bucket) = self.find(hash, eq) { - unsafe { self.erase(bucket) }; + unsafe { + self.erase(bucket); + } true } else { false @@ -579,7 +585,7 @@ impl RawTable { /// Marks all table buckets as empty without dropping their contents. #[cfg_attr(feature = "inline-more", inline)] pub fn clear_no_drop(&mut self) { - self.table.clear_no_drop() + self.table.clear_no_drop(); } /// Removes all elements from the table without freeing the backing memory. @@ -593,7 +599,7 @@ impl RawTable { } unsafe fn drop_elements(&mut self) { - if mem::needs_drop::() && self.len() != 0 { + if mem::needs_drop::() && !self.is_empty() { for item in self.iter() { item.drop(); } @@ -624,7 +630,7 @@ impl RawTable { if min_buckets < self.buckets() { // Fast path if the table is empty if self.table.items == 0 { - *self = Self::with_capacity_in(min_size, self.table.alloc.clone()) + *self = Self::with_capacity_in(min_size, self.table.alloc.clone()); } else { // Avoid `Result::unwrap_or_else` because it bloats LLVM IR. if self @@ -676,102 +682,18 @@ impl RawTable { hasher: impl Fn(&T) -> u64, fallibility: Fallibility, ) -> Result<(), TryReserveError> { - // Avoid `Option::ok_or_else` because it bloats LLVM IR. - let new_items = match self.table.items.checked_add(additional) { - Some(new_items) => new_items, - None => return Err(fallibility.capacity_overflow()), - }; - let full_capacity = bucket_mask_to_capacity(self.table.bucket_mask); - if new_items <= full_capacity / 2 { - // Rehash in-place without re-allocating if we have plenty of spare - // capacity that is locked up due to DELETED entries. - self.rehash_in_place(hasher); - Ok(()) - } else { - // Otherwise, conservatively resize to at least the next size up - // to avoid churning deletes into frequent rehashes. - self.resize( - usize::max(new_items, full_capacity + 1), - hasher, - fallibility, - ) - } - } - - /// Rehashes the contents of the table in place (i.e. without changing the - /// allocation). - /// - /// If `hasher` panics then some the table's contents may be lost. - fn rehash_in_place(&mut self, hasher: impl Fn(&T) -> u64) { unsafe { - // If the hash function panics then properly clean up any elements - // that we haven't rehashed yet. We unfortunately can't preserve the - // element since we lost their hash and have no way of recovering it - // without risking another panic. - self.table.prepare_rehash_in_place(); - - let mut guard = guard(&mut self.table, move |self_| { + self.table.reserve_rehash_inner( + additional, + &|table, index| hasher(table.bucket::(index).as_ref()), + fallibility, + TableLayout::new::(), if mem::needs_drop::() { - for i in 0..self_.buckets() { - if *self_.ctrl(i) == DELETED { - self_.set_ctrl(i, EMPTY); - self_.bucket::(i).drop(); - self_.items -= 1; - } - } - } - self_.growth_left = bucket_mask_to_capacity(self_.bucket_mask) - self_.items; - }); - - // At this point, DELETED elements are elements that we haven't - // rehashed yet. Find them and re-insert them at their ideal - // position. - 'outer: for i in 0..guard.buckets() { - if *guard.ctrl(i) != DELETED { - continue; - } - - 'inner: loop { - // Hash the current item - let item = guard.bucket(i); - let hash = hasher(item.as_ref()); - - // Search for a suitable place to put it - let new_i = guard.find_insert_slot(hash); - - // Probing works by scanning through all of the control - // bytes in groups, which may not be aligned to the group - // size. If both the new and old position fall within the - // same unaligned group, then there is no benefit in moving - // it and we can just continue to the next item. - if likely(guard.is_in_same_group(i, new_i, hash)) { - guard.set_ctrl_h2(i, hash); - continue 'outer; - } - - // We are moving the current item to a new position. Write - // our H2 to the control byte of the new position. - let prev_ctrl = guard.replace_ctrl_h2(new_i, hash); - if prev_ctrl == EMPTY { - guard.set_ctrl(i, EMPTY); - // If the target slot is empty, simply move the current - // element into the new slot and clear the old control - // byte. - guard.bucket(new_i).copy_from_nonoverlapping(&item); - continue 'outer; - } else { - // If the target slot is occupied, swap the two elements - // and then continue processing the element that we just - // swapped into the old slot. - debug_assert_eq!(prev_ctrl, DELETED); - mem::swap(guard.bucket(new_i).as_mut(), item.as_mut()); - continue 'inner; - } - } - } - - guard.growth_left = bucket_mask_to_capacity(guard.bucket_mask) - guard.items; - mem::forget(guard); + Some(mem::transmute(ptr::drop_in_place:: as unsafe fn(*mut T))) + } else { + None + }, + ) } } @@ -784,30 +706,12 @@ impl RawTable { fallibility: Fallibility, ) -> Result<(), TryReserveError> { unsafe { - let mut new_table = - self.table - .prepare_resize(TableLayout::new::(), capacity, fallibility)?; - - // Copy all elements to the new table. - for item in self.iter() { - // This may panic. - let hash = hasher(item.as_ref()); - - // We can use a simpler version of insert() here since: - // - there are no DELETED entries. - // - we know there is enough space in the table. - // - all elements are unique. - let (index, _) = new_table.prepare_insert_slot(hash); - new_table.bucket(index).copy_from_nonoverlapping(&item); - } - - // We successfully copied all elements without panicking. Now replace - // self with the new table. The old table will have its memory freed but - // the items will not be dropped (since they have been moved into the - // new table). - mem::swap(&mut self.table, &mut new_table); - - Ok(()) + self.table.resize_inner( + capacity, + &|table, index| hasher(table.bucket::(index).as_ref()), + fallibility, + TableLayout::new::(), + ) } } @@ -872,19 +776,17 @@ impl RawTable { /// This does not check if the given element already exists in the table. #[cfg_attr(feature = "inline-more", inline)] #[cfg(any(feature = "raw", feature = "rustc-internal-api"))] - pub fn insert_no_grow(&mut self, hash: u64, value: T) -> Bucket { - unsafe { - let (index, old_ctrl) = self.table.prepare_insert_slot(hash); - let bucket = self.table.bucket(index); + pub unsafe fn insert_no_grow(&mut self, hash: u64, value: T) -> Bucket { + let (index, old_ctrl) = self.table.prepare_insert_slot(hash); + let bucket = self.table.bucket(index); - // If we are replacing a DELETED entry then we don't need to update - // the load counter. - self.table.growth_left -= special_is_empty(old_ctrl) as usize; + // If we are replacing a DELETED entry then we don't need to update + // the load counter. + self.table.growth_left -= special_is_empty(old_ctrl) as usize; - bucket.write(value); - self.table.items += 1; - bucket - } + bucket.write(value); + self.table.items += 1; + bucket } /// Temporary removes a bucket, applying the given function to the removed @@ -917,14 +819,14 @@ impl RawTable { /// Searches for an element in the table. #[inline] pub fn find(&self, hash: u64, mut eq: impl FnMut(&T) -> bool) -> Option> { - unsafe { - for bucket in self.iter_hash(hash) { - let elm = bucket.as_ref(); - if likely(eq(elm)) { - return Some(bucket); - } - } - None + let result = self.table.find_inner(hash, &mut |index| unsafe { + eq(self.bucket(index).as_ref()) + }); + + // Avoid `Option::map` because it bloats LLVM IR. + match result { + Some(index) => Some(unsafe { self.bucket(index) }), + None => None, } } @@ -950,79 +852,84 @@ impl RawTable { /// Attempts to get mutable references to `N` entries in the table 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 entry. An - /// `Err(UnavailableMutError::Duplicate(i))` in the returned array indicates that a suitable - /// entry exists, but a mutable reference to it already occurs at index `i` in the returned - /// array. + /// Returns an array of length `N` with the results of each query. + /// + /// At most one mutable reference will be returned to any entry. `None` will be returned if any + /// of the hashes are duplicates. `None` will be returned if the hash is not found. /// /// The `eq` argument should be a closure such that `eq(i, k)` returns true if `k` is equal to /// the `i`th key to be looked up. - /// - /// This method is available only if the `nightly` feature is enabled. - #[cfg(feature = "nightly")] - pub fn get_each_mut( + pub fn get_many_mut( &mut self, hashes: [u64; N], - mut eq: impl FnMut(usize, &T) -> bool, - ) -> [Result<&'_ mut T, UnavailableMutError>; N] { - // Collect the requested buckets. - // TODO use `MaybeUninit::uninit_array` here instead once that's stable. - let mut buckets: [MaybeUninit>>; N] = - unsafe { MaybeUninit::uninit().assume_init() }; - for i in 0..N { - buckets[i] = MaybeUninit::new(self.find(hashes[i], |k| eq(i, k))); + eq: impl FnMut(usize, &T) -> bool, + ) -> Option<[&'_ mut T; N]> { + unsafe { + let ptrs = self.get_many_mut_pointers(hashes, eq)?; + + for (i, &cur) in ptrs.iter().enumerate() { + if ptrs[..i].iter().any(|&prev| ptr::eq::(prev, cur)) { + return None; + } + } + // All bucket are distinct from all previous buckets so we're clear to return the result + // of the lookup. + + // TODO use `MaybeUninit::array_assume_init` here instead once that's stable. + Some(mem::transmute_copy(&ptrs)) } - let buckets: [Option>; N] = unsafe { MaybeUninit::array_assume_init(buckets) }; + } + + pub unsafe fn get_many_unchecked_mut( + &mut self, + hashes: [u64; N], + eq: impl FnMut(usize, &T) -> bool, + ) -> Option<[&'_ mut T; N]> { + let ptrs = self.get_many_mut_pointers(hashes, eq)?; + Some(mem::transmute_copy(&ptrs)) + } - // Walk through the buckets, checking for duplicates and building up the output array. + unsafe fn get_many_mut_pointers( + &mut self, + hashes: [u64; N], + mut eq: impl FnMut(usize, &T) -> bool, + ) -> Option<[*mut T; N]> { // TODO use `MaybeUninit::uninit_array` here instead once that's stable. - let mut out: [MaybeUninit>; N] = - unsafe { MaybeUninit::uninit().assume_init() }; - for i in 0..N { - out[i] = MaybeUninit::new( - #[allow(clippy::never_loop)] - 'outer: loop { - for j in 0..i { - match (&buckets[j], &buckets[i]) { - // These two buckets are the same, and we can't safely return a second - // mutable reference to the same entry. - (Some(prev), Some(cur)) if prev.as_ptr() == cur.as_ptr() => { - break 'outer Err(UnavailableMutError::Duplicate(j)); - } - _ => {} - } - } - // This bucket is distinct from all previous buckets (or it doesn't exist), so - // we're clear to return the result of the lookup. - break match &buckets[i] { - None => Err(UnavailableMutError::Absent), - Some(bkt) => unsafe { Ok(bkt.as_mut()) }, - }; - }, - ) + let mut outs: MaybeUninit<[*mut T; N]> = MaybeUninit::uninit(); + let outs_ptr = outs.as_mut_ptr(); + + for (i, &hash) in hashes.iter().enumerate() { + let cur = self.find(hash, |k| eq(i, k))?; + *(*outs_ptr).get_unchecked_mut(i) = cur.as_mut(); } - unsafe { MaybeUninit::array_assume_init(out) } + // TODO use `MaybeUninit::array_assume_init` here instead once that's stable. + Some(outs.assume_init()) } /// Returns the number of elements the map can hold without reallocating. /// /// This number is a lower bound; the table might be able to hold /// more, but is guaranteed to be able to hold at least this many. - #[cfg_attr(feature = "inline-more", inline)] + #[inline] pub fn capacity(&self) -> usize { self.table.items + self.table.growth_left } /// Returns the number of elements in the table. - #[cfg_attr(feature = "inline-more", inline)] + #[inline] pub fn len(&self) -> usize { self.table.items } + /// Returns `true` if the table contains no elements. + #[inline] + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + /// Returns the number of buckets in the table. - #[cfg_attr(feature = "inline-more", inline)] + #[inline] pub fn buckets(&self) -> usize { self.table.bucket_mask + 1 } @@ -1031,7 +938,7 @@ impl RawTable { /// the caller to ensure that the `RawTable` outlives the `RawIter`. /// Because we cannot make the `next` method unsafe on the `RawIter` /// struct, we have to make the `iter` method unsafe. - #[cfg_attr(feature = "inline-more", inline)] + #[inline] pub unsafe fn iter(&self) -> RawIter { let data = Bucket::from_base_index(self.data_end(), 0); RawIter { @@ -1042,12 +949,15 @@ impl RawTable { /// Returns an iterator over occupied buckets that could match a given hash. /// - /// In rare cases, the iterator may return a bucket with a different hash. + /// `RawTable` only stores 7 bits of the hash value, so this iterator may + /// return items that have a hash value different than the one provided. You + /// should always validate the returned values before using them. /// /// It is up to the caller to ensure that the `RawTable` outlives the /// `RawIterHash`. Because we cannot make the `next` method unsafe on the /// `RawIterHash` struct, we have to make the `iter_hash` method unsafe. #[cfg_attr(feature = "inline-more", inline)] + #[cfg(feature = "raw")] pub unsafe fn iter_hash(&self, hash: u64) -> RawIterHash<'_, T, A> { RawIterHash::new(self, hash) } @@ -1121,11 +1031,21 @@ impl RawTable { } } -unsafe impl Send for RawTable where T: Send {} -unsafe impl Sync for RawTable where T: Sync {} +unsafe impl Send for RawTable +where + T: Send, + A: Send, +{ +} +unsafe impl Sync for RawTable +where + T: Sync, + A: Sync, +{ +} impl RawTableInner { - #[cfg_attr(feature = "inline-more", inline)] + #[inline] const fn new_in(alloc: A) -> Self { Self { // Be careful to cast the entire slice to a raw pointer. @@ -1154,6 +1074,15 @@ impl RawTableInner { None => return Err(fallibility.capacity_overflow()), }; + // We need an additional check to ensure that the allocation doesn't + // exceed `isize::MAX`. We can skip this check on 64-bit systems since + // such allocations will never succeed anyways. + // + // This mirrors what Vec does in the standard library. + if mem::size_of::() < 8 && layout.size() > isize::MAX as usize { + return Err(fallibility.capacity_overflow()); + } + let ptr: NonNull = match do_alloc(&alloc, layout) { Ok(block) => block.cast(), Err(_) => return Err(fallibility.alloc_err(layout)), @@ -1221,7 +1150,7 @@ impl RawTableInner { // EMPTY entries. These will unfortunately trigger a // match, but once masked may point to a full bucket that // is already occupied. We detect this situation here and - // perform a second scan starting at the begining of the + // perform a second scan starting at the beginning of the // table. This second scan is guaranteed to find an empty // slot (due to the load factor) before hitting the trailing // control bytes (containing EMPTY). @@ -1240,6 +1169,32 @@ impl RawTableInner { } } + /// Searches for an element in the table. This uses dynamic dispatch to reduce the amount of + /// code generated, but it is eliminated by LLVM optimizations. + #[inline] + fn find_inner(&self, hash: u64, eq: &mut dyn FnMut(usize) -> bool) -> Option { + let h2_hash = h2(hash); + let mut probe_seq = self.probe_seq(hash); + + loop { + let group = unsafe { Group::load(self.ctrl(probe_seq.pos)) }; + + for bit in group.match_byte(h2_hash) { + let index = (probe_seq.pos + bit) & self.bucket_mask; + + if likely(eq(index)) { + return Some(index); + } + } + + if likely(group.match_empty().any_bit_set()) { + return None; + } + + probe_seq.move_next(self.bucket_mask); + } + } + #[allow(clippy::mut_mut)] #[inline] unsafe fn prepare_rehash_in_place(&mut self) { @@ -1263,14 +1218,22 @@ impl RawTableInner { } } - #[cfg_attr(feature = "inline-more", inline)] + #[inline] unsafe fn bucket(&self, index: usize) -> Bucket { debug_assert_ne!(self.bucket_mask, 0); debug_assert!(index < self.buckets()); Bucket::from_base_index(self.data_end(), index) } - #[cfg_attr(feature = "inline-more", inline)] + #[inline] + unsafe fn bucket_ptr(&self, index: usize, size_of: usize) -> *mut u8 { + debug_assert_ne!(self.bucket_mask, 0); + debug_assert!(index < self.buckets()); + let base: *mut u8 = self.data_end().as_ptr(); + base.sub((index + 1) * size_of) + } + + #[inline] unsafe fn data_end(&self) -> NonNull { NonNull::new_unchecked(self.ctrl.as_ptr().cast()) } @@ -1322,7 +1285,7 @@ impl RawTableInner { /// the end of the array. #[inline] unsafe fn set_ctrl_h2(&self, index: usize, hash: u64) { - self.set_ctrl(index, h2(hash)) + self.set_ctrl(index, h2(hash)); } #[inline] @@ -1415,6 +1378,179 @@ impl RawTableInner { })) } + /// Reserves or rehashes to make room for `additional` more elements. + /// + /// This uses dynamic dispatch to reduce the amount of + /// code generated, but it is eliminated by LLVM optimizations when inlined. + #[allow(clippy::inline_always)] + #[inline(always)] + unsafe fn reserve_rehash_inner( + &mut self, + additional: usize, + hasher: &dyn Fn(&mut Self, usize) -> u64, + fallibility: Fallibility, + layout: TableLayout, + drop: Option, + ) -> Result<(), TryReserveError> { + // Avoid `Option::ok_or_else` because it bloats LLVM IR. + let new_items = match self.items.checked_add(additional) { + Some(new_items) => new_items, + None => return Err(fallibility.capacity_overflow()), + }; + let full_capacity = bucket_mask_to_capacity(self.bucket_mask); + if new_items <= full_capacity / 2 { + // Rehash in-place without re-allocating if we have plenty of spare + // capacity that is locked up due to DELETED entries. + self.rehash_in_place(hasher, layout.size, drop); + Ok(()) + } else { + // Otherwise, conservatively resize to at least the next size up + // to avoid churning deletes into frequent rehashes. + self.resize_inner( + usize::max(new_items, full_capacity + 1), + hasher, + fallibility, + layout, + ) + } + } + + /// Allocates a new table of a different size and moves the contents of the + /// current table into it. + /// + /// This uses dynamic dispatch to reduce the amount of + /// code generated, but it is eliminated by LLVM optimizations when inlined. + #[allow(clippy::inline_always)] + #[inline(always)] + unsafe fn resize_inner( + &mut self, + capacity: usize, + hasher: &dyn Fn(&mut Self, usize) -> u64, + fallibility: Fallibility, + layout: TableLayout, + ) -> Result<(), TryReserveError> { + let mut new_table = self.prepare_resize(layout, capacity, fallibility)?; + + // Copy all elements to the new table. + for i in 0..self.buckets() { + if !is_full(*self.ctrl(i)) { + continue; + } + + // This may panic. + let hash = hasher(self, i); + + // We can use a simpler version of insert() here since: + // - there are no DELETED entries. + // - we know there is enough space in the table. + // - all elements are unique. + let (index, _) = new_table.prepare_insert_slot(hash); + + ptr::copy_nonoverlapping( + self.bucket_ptr(i, layout.size), + new_table.bucket_ptr(index, layout.size), + layout.size, + ); + } + + // We successfully copied all elements without panicking. Now replace + // self with the new table. The old table will have its memory freed but + // the items will not be dropped (since they have been moved into the + // new table). + mem::swap(self, &mut new_table); + + Ok(()) + } + + /// Rehashes the contents of the table in place (i.e. without changing the + /// allocation). + /// + /// If `hasher` panics then some the table's contents may be lost. + /// + /// This uses dynamic dispatch to reduce the amount of + /// code generated, but it is eliminated by LLVM optimizations when inlined. + #[allow(clippy::inline_always)] + #[cfg_attr(feature = "inline-more", inline(always))] + #[cfg_attr(not(feature = "inline-more"), inline)] + unsafe fn rehash_in_place( + &mut self, + hasher: &dyn Fn(&mut Self, usize) -> u64, + size_of: usize, + drop: Option, + ) { + // If the hash function panics then properly clean up any elements + // that we haven't rehashed yet. We unfortunately can't preserve the + // element since we lost their hash and have no way of recovering it + // without risking another panic. + self.prepare_rehash_in_place(); + + let mut guard = guard(self, move |self_| { + if let Some(drop) = drop { + for i in 0..self_.buckets() { + if *self_.ctrl(i) == DELETED { + self_.set_ctrl(i, EMPTY); + drop(self_.bucket_ptr(i, size_of)); + self_.items -= 1; + } + } + } + self_.growth_left = bucket_mask_to_capacity(self_.bucket_mask) - self_.items; + }); + + // At this point, DELETED elements are elements that we haven't + // rehashed yet. Find them and re-insert them at their ideal + // position. + 'outer: for i in 0..guard.buckets() { + if *guard.ctrl(i) != DELETED { + continue; + } + + let i_p = guard.bucket_ptr(i, size_of); + + 'inner: loop { + // Hash the current item + let hash = hasher(*guard, i); + + // Search for a suitable place to put it + let new_i = guard.find_insert_slot(hash); + let new_i_p = guard.bucket_ptr(new_i, size_of); + + // Probing works by scanning through all of the control + // bytes in groups, which may not be aligned to the group + // size. If both the new and old position fall within the + // same unaligned group, then there is no benefit in moving + // it and we can just continue to the next item. + if likely(guard.is_in_same_group(i, new_i, hash)) { + guard.set_ctrl_h2(i, hash); + continue 'outer; + } + + // We are moving the current item to a new position. Write + // our H2 to the control byte of the new position. + let prev_ctrl = guard.replace_ctrl_h2(new_i, hash); + if prev_ctrl == EMPTY { + guard.set_ctrl(i, EMPTY); + // If the target slot is empty, simply move the current + // element into the new slot and clear the old control + // byte. + ptr::copy_nonoverlapping(i_p, new_i_p, size_of); + continue 'outer; + } else { + // If the target slot is occupied, swap the two elements + // and then continue processing the element that we just + // swapped into the old slot. + debug_assert_eq!(prev_ctrl, DELETED); + ptr::swap_nonoverlapping(i_p, new_i_p, size_of); + continue 'inner; + } + } + } + + guard.growth_left = bucket_mask_to_capacity(guard.bucket_mask) - guard.items; + + mem::forget(guard); + } + #[inline] unsafe fn free_buckets(&mut self, table_layout: TableLayout) { // Avoid `Option::unwrap_or_else` because it bloats LLVM IR. @@ -1454,7 +1590,7 @@ impl RawTableInner { // // Note that in this context `leading_zeros` refers to the bytes at the // end of a group, while `trailing_zeros` refers to the bytes at the - // begining of a group. + // beginning of a group. let ctrl = if empty_before.leading_zeros() + empty_after.trailing_zeros() >= Group::WIDTH { DELETED } else { @@ -1524,7 +1660,7 @@ impl Clone for RawTable { self.clone_from_spec(source, |self_| { // We need to leave the table in an empty state. - self_.clear_no_drop() + self_.clear_no_drop(); }); } } @@ -1536,8 +1672,8 @@ trait RawTableClone { unsafe fn clone_from_spec(&mut self, source: &Self, on_panic: impl FnMut(&mut Self)); } impl RawTableClone for RawTable { - #[cfg_attr(feature = "inline-more", inline)] default_fn! { + #[cfg_attr(feature = "inline-more", inline)] unsafe fn clone_from_spec(&mut self, source: &Self, on_panic: impl FnMut(&mut Self)) { self.clone_from_impl(source, on_panic); } @@ -1574,7 +1710,7 @@ impl RawTable { // to make sure we drop only the elements that have been // cloned so far. let mut guard = guard((0, &mut *self), |(index, self_)| { - if mem::needs_drop::() && self_.len() != 0 { + if mem::needs_drop::() && !self_.is_empty() { for i in 0..=*index { if is_full(*self_.table.ctrl(i)) { self_.bucket(i).drop(); @@ -1650,7 +1786,7 @@ impl RawTable { } impl Default for RawTable { - #[cfg_attr(feature = "inline-more", inline)] + #[inline] fn default() -> Self { Self::new_in(Default::default()) } @@ -1824,7 +1960,7 @@ impl Iterator for RawIterRange { } } - #[cfg_attr(feature = "inline-more", inline)] + #[inline] fn size_hint(&self) -> (usize, Option) { // We don't have an item count, so just guess based on the range size. ( @@ -1871,7 +2007,7 @@ impl RawIter { /// For the iterator to remain valid, this method must be called once /// for each insert before `next` is called again. /// - /// This method does not guarantee that an insertion of a bucket witha greater + /// This method does not guarantee that an insertion of a bucket with a greater /// index than the last one yielded will be reflected in the iterator. /// /// This method should be called _after_ the given insert is made. @@ -1923,7 +2059,7 @@ impl RawIter { // If it did, we're done. // - Otherwise, update the iterator cached group so that it won't // yield a to-be-removed bucket, or _will_ yield a to-be-added bucket. - // We'll also need ot update the item count accordingly. + // We'll also need to update the item count accordingly. if let Some(index) = self.iter.current_group.lowest_set_bit() { let next_bucket = self.iter.data.next_n(index); if b.as_ptr() > next_bucket.as_ptr() { @@ -2006,7 +2142,7 @@ impl Iterator for RawIter { } } - #[cfg_attr(feature = "inline-more", inline)] + #[inline] fn size_hint(&self) -> (usize, Option) { (self.items, Some(self.items)) } @@ -2030,8 +2166,18 @@ impl RawIntoIter { } } -unsafe impl Send for RawIntoIter where T: Send {} -unsafe impl Sync for RawIntoIter where T: Sync {} +unsafe impl Send for RawIntoIter +where + T: Send, + A: Send, +{ +} +unsafe impl Sync for RawIntoIter +where + T: Sync, + A: Sync, +{ +} #[cfg(feature = "nightly")] unsafe impl<#[may_dangle] T, A: Allocator + Clone> Drop for RawIntoIter { @@ -2072,7 +2218,7 @@ impl Iterator for RawIntoIter { unsafe { Some(self.iter.next()?.read()) } } - #[cfg_attr(feature = "inline-more", inline)] + #[inline] fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } @@ -2103,8 +2249,18 @@ impl RawDrain<'_, T, A> { } } -unsafe impl Send for RawDrain<'_, T, A> where T: Send {} -unsafe impl Sync for RawDrain<'_, T, A> where T: Sync {} +unsafe impl Send for RawDrain<'_, T, A> +where + T: Send, + A: Send, +{ +} +unsafe impl Sync for RawDrain<'_, T, A> +where + T: Sync, + A: Sync, +{ +} impl Drop for RawDrain<'_, T, A> { #[cfg_attr(feature = "inline-more", inline)] @@ -2136,7 +2292,7 @@ impl Iterator for RawDrain<'_, T, A> { } } - #[cfg_attr(feature = "inline-more", inline)] + #[inline] fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } @@ -2147,7 +2303,9 @@ impl FusedIterator for RawDrain<'_, T, A> {} /// Iterator over occupied buckets that could match a given hash. /// -/// In rare cases, the iterator may return a bucket with a different hash. +/// `RawTable` only stores 7 bits of the hash value, so this iterator may return +/// items that have a hash value different than the one provided. You should +/// always validate the returned values before using them. pub struct RawIterHash<'a, T, A: Allocator + Clone = Global> { inner: RawIterHashInner<'a, A>, _marker: PhantomData, @@ -2170,6 +2328,7 @@ struct RawIterHashInner<'a, A: Allocator + Clone> { impl<'a, T, A: Allocator + Clone> RawIterHash<'a, T, A> { #[cfg_attr(feature = "inline-more", inline)] + #[cfg(feature = "raw")] fn new(table: &'a RawTable, hash: u64) -> Self { RawIterHash { inner: RawIterHashInner::new(&table.table, hash), @@ -2179,6 +2338,7 @@ impl<'a, T, A: Allocator + Clone> RawIterHash<'a, T, A> { } impl<'a, A: Allocator + Clone> RawIterHashInner<'a, A> { #[cfg_attr(feature = "inline-more", inline)] + #[cfg(feature = "raw")] fn new(table: &'a RawTableInner, hash: u64) -> Self { unsafe { let h2_hash = h2(hash); @@ -2235,6 +2395,20 @@ impl<'a, A: Allocator + Clone> Iterator for RawIterHashInner<'a, A> { mod test_map { use super::*; + fn rehash_in_place(table: &mut RawTable, hasher: impl Fn(&T) -> u64) { + unsafe { + table.table.rehash_in_place( + &|table, index| hasher(table.bucket::(index).as_ref()), + mem::size_of::(), + if mem::needs_drop::() { + Some(mem::transmute(ptr::drop_in_place:: as unsafe fn(*mut T))) + } else { + None + }, + ); + } + } + #[test] fn rehash() { let mut table = RawTable::new(); @@ -2250,7 +2424,7 @@ mod test_map { assert!(table.find(i + 100, |x| *x == i + 100).is_none()); } - table.rehash_in_place(hasher); + rehash_in_place(&mut table, hasher); for i in 0..100 { unsafe { diff --git a/sgx_tstd/hashbrown/src/raw/sse2.rs b/sgx_tstd/hashbrown/src/raw/sse2.rs index eed968485..a0bf6da80 100644 --- a/sgx_tstd/hashbrown/src/raw/sse2.rs +++ b/sgx_tstd/hashbrown/src/raw/sse2.rs @@ -28,6 +28,7 @@ impl Group { /// value for an empty hash table. /// /// This is guaranteed to be aligned to the group size. + #[inline] #[allow(clippy::items_after_statements)] pub const fn static_empty() -> &'static [u8; Group::WIDTH] { #[repr(C)] diff --git a/sgx_tstd/hashbrown/src/rustc_entry.rs b/sgx_tstd/hashbrown/src/rustc_entry.rs index 1793c4a60..465db4781 100644 --- a/sgx_tstd/hashbrown/src/rustc_entry.rs +++ b/sgx_tstd/hashbrown/src/rustc_entry.rs @@ -574,8 +574,10 @@ impl<'a, K, V, A: Allocator + Clone> RustcVacantEntry<'a, K, V, A> { /// ``` #[cfg_attr(feature = "inline-more", inline)] pub fn insert(self, value: V) -> &'a mut V { - let bucket = self.table.insert_no_grow(self.hash, (self.key, value)); - unsafe { &mut bucket.as_mut().1 } + unsafe { + let bucket = self.table.insert_no_grow(self.hash, (self.key, value)); + &mut bucket.as_mut().1 + } } /// Sets the value of the entry with the RustcVacantEntry's key, @@ -596,7 +598,7 @@ impl<'a, K, V, A: Allocator + Clone> RustcVacantEntry<'a, K, V, A> { /// ``` #[cfg_attr(feature = "inline-more", inline)] pub fn insert_entry(self, value: V) -> RustcOccupiedEntry<'a, K, V, A> { - let bucket = self.table.insert_no_grow(self.hash, (self.key, value)); + let bucket = unsafe { self.table.insert_no_grow(self.hash, (self.key, value)) }; RustcOccupiedEntry { key: None, elem: bucket, diff --git a/sgx_tstd/hashbrown/src/scopeguard.rs b/sgx_tstd/hashbrown/src/scopeguard.rs index 4e9bf045a..ccdc0c511 100644 --- a/sgx_tstd/hashbrown/src/scopeguard.rs +++ b/sgx_tstd/hashbrown/src/scopeguard.rs @@ -44,6 +44,6 @@ where { #[inline] fn drop(&mut self) { - (self.dropfn)(&mut self.value) + (self.dropfn)(&mut self.value); } } diff --git a/sgx_tstd/hashbrown/src/set.rs b/sgx_tstd/hashbrown/src/set.rs index d59183b5c..bb8305483 100644 --- a/sgx_tstd/hashbrown/src/set.rs +++ b/sgx_tstd/hashbrown/src/set.rs @@ -378,7 +378,7 @@ impl HashSet { /// ``` #[cfg_attr(feature = "inline-more", inline)] pub fn clear(&mut self) { - self.map.clear() + self.map.clear(); } } @@ -454,6 +454,12 @@ impl HashSet where A: Allocator + Clone, { + /// Returns a reference to the underlying allocator. + #[inline] + pub fn allocator(&self) -> &A { + self.map.allocator() + } + /// Creates a new empty hash set which will use the given hasher to hash /// keys. /// @@ -553,7 +559,7 @@ where /// ``` #[cfg_attr(feature = "inline-more", inline)] pub fn reserve(&mut self, additional: usize) { - self.map.reserve(additional) + self.map.reserve(additional); } /// Tries to reserve capacity for at least `additional` more elements to be inserted @@ -595,7 +601,7 @@ where /// ``` #[cfg_attr(feature = "inline-more", inline)] pub fn shrink_to_fit(&mut self) { - self.map.shrink_to_fit() + self.map.shrink_to_fit(); } /// Shrinks the capacity of the set with a lower limit. It will drop @@ -621,7 +627,7 @@ where /// ``` #[cfg_attr(feature = "inline-more", inline)] pub fn shrink_to(&mut self, min_capacity: usize) { - self.map.shrink_to(min_capacity) + self.map.shrink_to(min_capacity); } /// Visits the values representing the difference, @@ -985,6 +991,30 @@ where self.map.insert(value, ()).is_none() } + /// Insert a value the set without checking if the value already exists in the set. + /// + /// Returns a reference to the value just inserted. + /// + /// This operation is safe if a value does not exist in the set. + /// + /// However, if a value exists in the set already, the behavior is unspecified: + /// this operation may panic, loop forever, or any following operation with the set + /// may panic, loop forever or return arbitrary result. + /// + /// That said, this operation (and following operations) are guaranteed to + /// not violate memory safety. + /// + /// This operation is faster than regular insert, because it does not perform + /// lookup before insertion. + /// + /// This operation is useful during initial population of the set. + /// For example, when constructing a set from another set, we know + /// that values are unique. + #[cfg_attr(feature = "inline-more", inline)] + pub fn insert_unique_unchecked(&mut self, value: T) -> &T { + self.map.insert_unique_unchecked(value, ()).0 + } + /// Adds a value to the set, replacing the existing value, if any, that is equal to the given /// one. Returns the replaced value. /// @@ -1098,8 +1128,7 @@ where impl fmt::Debug for HashSet where - T: Eq + Hash + fmt::Debug, - S: BuildHasher, + T: fmt::Debug, A: Allocator + Clone, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -1130,6 +1159,27 @@ where } } +// The default hasher is used to match the std implementation signature +#[cfg(feature = "ahash")] +impl From<[T; N]> for HashSet +where + T: Eq + Hash, + A: Default + Allocator + Clone, +{ + /// # Examples + /// + /// ``` + /// use hashbrown::HashSet; + /// + /// let set1 = HashSet::from([1, 2, 3, 4]); + /// let set2: HashSet<_> = [1, 2, 3, 4].into(); + /// assert_eq!(set1, set2); + /// ``` + fn from(arr: [T; N]) -> Self { + arr.into_iter().collect() + } +} + impl Extend for HashSet where T: Eq + Hash, @@ -1162,7 +1212,7 @@ where { #[cfg_attr(feature = "inline-more", inline)] fn extend>(&mut self, iter: I) { - self.extend(iter.into_iter().cloned()); + self.extend(iter.into_iter().copied()); } #[inline] @@ -1963,7 +2013,7 @@ mod test_set { let expected = [3, 5, 11, 77]; for x in a.intersection(&b) { assert!(expected.contains(x)); - i += 1 + i += 1; } assert_eq!(i, expected.len()); } @@ -1986,7 +2036,7 @@ mod test_set { let expected = [1, 5, 11]; for x in a.difference(&b) { assert!(expected.contains(x)); - i += 1 + i += 1; } assert_eq!(i, expected.len()); } @@ -2012,7 +2062,7 @@ mod test_set { let expected = [-2, 1, 5, 11, 14, 22]; for x in a.symmetric_difference(&b) { assert!(expected.contains(x)); - i += 1 + i += 1; } assert_eq!(i, expected.len()); } @@ -2042,7 +2092,7 @@ mod test_set { let expected = [-2, 1, 3, 5, 9, 11, 13, 16, 19, 24]; for x in a.union(&b) { assert!(expected.contains(x)); - i += 1 + i += 1; } assert_eq!(i, expected.len()); } @@ -2068,7 +2118,7 @@ mod test_set { fn test_from_iter() { let xs = [1, 2, 2, 3, 4, 5, 6, 7, 8, 9]; - let set: HashSet<_> = xs.iter().cloned().collect(); + let set: HashSet<_> = xs.iter().copied().collect(); for x in &xs { assert!(set.contains(x)); @@ -2230,7 +2280,7 @@ mod test_set { #[test] fn test_retain() { let xs = [1, 2, 3, 4, 5, 6]; - let mut set: HashSet = xs.iter().cloned().collect(); + let mut set: HashSet = xs.iter().copied().collect(); set.retain(|&k| k % 2 == 0); assert_eq!(set.len(), 3); assert!(set.contains(&2)); @@ -2272,7 +2322,7 @@ mod test_set { const EMPTY_SET: HashSet = HashSet::with_hasher(MyHasher); - let mut set = EMPTY_SET.clone(); + let mut set = EMPTY_SET; set.insert(19); assert!(set.contains(&19)); } diff --git a/sgx_tstd/hashbrown/tests/rayon.rs b/sgx_tstd/hashbrown/tests/rayon.rs index 39b47708d..8c603c5c4 100644 --- a/sgx_tstd/hashbrown/tests/rayon.rs +++ b/sgx_tstd/hashbrown/tests/rayon.rs @@ -269,20 +269,20 @@ fn map_seq_par_equivalence_existing_empty_extend_empty() { let mut map_seq = MAP_EXISTING_EMPTY.clone(); let mut map_par = MAP_EXISTING_EMPTY.clone(); - map_seq.extend(MAP_EXTENSION_EMPTY.iter().cloned()); - map_par.par_extend(MAP_EXTENSION_EMPTY.par_iter().cloned()); + map_seq.extend(MAP_EXTENSION_EMPTY.iter().copied()); + map_par.par_extend(MAP_EXTENSION_EMPTY.par_iter().copied()); assert_eq3!(map_seq, map_par, expected); } #[test] fn map_seq_par_equivalence_existing_empty_extend() { - let expected = MAP_EXTENSION.iter().cloned().collect::>(); + let expected = MAP_EXTENSION.iter().copied().collect::>(); let mut map_seq = MAP_EXISTING_EMPTY.clone(); let mut map_par = MAP_EXISTING_EMPTY.clone(); - map_seq.extend(MAP_EXTENSION.iter().cloned()); - map_par.par_extend(MAP_EXTENSION.par_iter().cloned()); + map_seq.extend(MAP_EXTENSION.iter().copied()); + map_par.par_extend(MAP_EXTENSION.par_iter().copied()); assert_eq3!(map_seq, map_par, expected); } @@ -293,8 +293,8 @@ fn map_seq_par_equivalence_existing_extend_empty() { let mut map_seq = MAP_EXISTING.clone(); let mut map_par = MAP_EXISTING.clone(); - map_seq.extend(MAP_EXTENSION_EMPTY.iter().cloned()); - map_par.par_extend(MAP_EXTENSION_EMPTY.par_iter().cloned()); + map_seq.extend(MAP_EXTENSION_EMPTY.iter().copied()); + map_par.par_extend(MAP_EXTENSION_EMPTY.par_iter().copied()); assert_eq3!(map_seq, map_par, expected); } @@ -305,8 +305,8 @@ fn map_seq_par_equivalence_existing_extend() { let mut map_seq = MAP_EXISTING.clone(); let mut map_par = MAP_EXISTING.clone(); - map_seq.extend(MAP_EXTENSION.iter().cloned()); - map_par.par_extend(MAP_EXTENSION.par_iter().cloned()); + map_seq.extend(MAP_EXTENSION.iter().copied()); + map_par.par_extend(MAP_EXTENSION.par_iter().copied()); assert_eq3!(map_seq, map_par, expected); } @@ -423,20 +423,20 @@ fn set_seq_par_equivalence_existing_empty_extend_empty() { let mut set_seq = SET_EXISTING_EMPTY.clone(); let mut set_par = SET_EXISTING_EMPTY.clone(); - set_seq.extend(SET_EXTENSION_EMPTY.iter().cloned()); - set_par.par_extend(SET_EXTENSION_EMPTY.par_iter().cloned()); + set_seq.extend(SET_EXTENSION_EMPTY.iter().copied()); + set_par.par_extend(SET_EXTENSION_EMPTY.par_iter().copied()); assert_eq3!(set_seq, set_par, expected); } #[test] fn set_seq_par_equivalence_existing_empty_extend() { - let expected = SET_EXTENSION.iter().cloned().collect::>(); + let expected = SET_EXTENSION.iter().copied().collect::>(); let mut set_seq = SET_EXISTING_EMPTY.clone(); let mut set_par = SET_EXISTING_EMPTY.clone(); - set_seq.extend(SET_EXTENSION.iter().cloned()); - set_par.par_extend(SET_EXTENSION.par_iter().cloned()); + set_seq.extend(SET_EXTENSION.iter().copied()); + set_par.par_extend(SET_EXTENSION.par_iter().copied()); assert_eq3!(set_seq, set_par, expected); } @@ -447,8 +447,8 @@ fn set_seq_par_equivalence_existing_extend_empty() { let mut set_seq = SET_EXISTING.clone(); let mut set_par = SET_EXISTING.clone(); - set_seq.extend(SET_EXTENSION_EMPTY.iter().cloned()); - set_par.par_extend(SET_EXTENSION_EMPTY.par_iter().cloned()); + set_seq.extend(SET_EXTENSION_EMPTY.iter().copied()); + set_par.par_extend(SET_EXTENSION_EMPTY.par_iter().copied()); assert_eq3!(set_seq, set_par, expected); } @@ -459,37 +459,37 @@ fn set_seq_par_equivalence_existing_extend() { let mut set_seq = SET_EXISTING.clone(); let mut set_par = SET_EXISTING.clone(); - set_seq.extend(SET_EXTENSION.iter().cloned()); - set_par.par_extend(SET_EXTENSION.par_iter().cloned()); + set_seq.extend(SET_EXTENSION.iter().copied()); + set_par.par_extend(SET_EXTENSION.par_iter().copied()); assert_eq3!(set_seq, set_par, expected); } lazy_static! { - static ref SET_A: HashSet = ['a', 'b', 'c', 'd'].iter().cloned().collect(); - static ref SET_B: HashSet = ['a', 'b', 'e', 'f'].iter().cloned().collect(); - static ref SET_DIFF_AB: HashSet = ['c', 'd'].iter().cloned().collect(); - static ref SET_DIFF_BA: HashSet = ['e', 'f'].iter().cloned().collect(); - static ref SET_SYMM_DIFF_AB: HashSet = ['c', 'd', 'e', 'f'].iter().cloned().collect(); - static ref SET_INTERSECTION_AB: HashSet = ['a', 'b'].iter().cloned().collect(); + static ref SET_A: HashSet = ['a', 'b', 'c', 'd'].iter().copied().collect(); + static ref SET_B: HashSet = ['a', 'b', 'e', 'f'].iter().copied().collect(); + static ref SET_DIFF_AB: HashSet = ['c', 'd'].iter().copied().collect(); + static ref SET_DIFF_BA: HashSet = ['e', 'f'].iter().copied().collect(); + static ref SET_SYMM_DIFF_AB: HashSet = ['c', 'd', 'e', 'f'].iter().copied().collect(); + static ref SET_INTERSECTION_AB: HashSet = ['a', 'b'].iter().copied().collect(); static ref SET_UNION_AB: HashSet = - ['a', 'b', 'c', 'd', 'e', 'f'].iter().cloned().collect(); + ['a', 'b', 'c', 'd', 'e', 'f'].iter().copied().collect(); } #[test] fn set_seq_par_equivalence_difference() { - let diff_ab_seq = SET_A.difference(&*SET_B).cloned().collect::>(); + let diff_ab_seq = SET_A.difference(&*SET_B).copied().collect::>(); let diff_ab_par = SET_A .par_difference(&*SET_B) - .cloned() + .copied() .collect::>(); assert_eq3!(diff_ab_seq, diff_ab_par, *SET_DIFF_AB); - let diff_ba_seq = SET_B.difference(&*SET_A).cloned().collect::>(); + let diff_ba_seq = SET_B.difference(&*SET_A).copied().collect::>(); let diff_ba_par = SET_B .par_difference(&*SET_A) - .cloned() + .copied() .collect::>(); assert_eq3!(diff_ba_seq, diff_ba_par, *SET_DIFF_BA); @@ -499,11 +499,11 @@ fn set_seq_par_equivalence_difference() { fn set_seq_par_equivalence_symmetric_difference() { let symm_diff_ab_seq = SET_A .symmetric_difference(&*SET_B) - .cloned() + .copied() .collect::>(); let symm_diff_ab_par = SET_A .par_symmetric_difference(&*SET_B) - .cloned() + .copied() .collect::>(); assert_eq3!(symm_diff_ab_seq, symm_diff_ab_par, *SET_SYMM_DIFF_AB); @@ -511,10 +511,10 @@ fn set_seq_par_equivalence_symmetric_difference() { #[test] fn set_seq_par_equivalence_intersection() { - let intersection_ab_seq = SET_A.intersection(&*SET_B).cloned().collect::>(); + let intersection_ab_seq = SET_A.intersection(&*SET_B).copied().collect::>(); let intersection_ab_par = SET_A .par_intersection(&*SET_B) - .cloned() + .copied() .collect::>(); assert_eq3!( @@ -526,8 +526,8 @@ fn set_seq_par_equivalence_intersection() { #[test] fn set_seq_par_equivalence_union() { - let union_ab_seq = SET_A.union(&*SET_B).cloned().collect::>(); - let union_ab_par = SET_A.par_union(&*SET_B).cloned().collect::>(); + let union_ab_seq = SET_A.union(&*SET_B).copied().collect::>(); + let union_ab_par = SET_A.par_union(&*SET_B).copied().collect::>(); assert_eq3!(union_ab_seq, union_ab_par, *SET_UNION_AB); } diff --git a/sgx_tstd/hashbrown/tests/set.rs b/sgx_tstd/hashbrown/tests/set.rs index 3fc071705..5ae1ec98e 100644 --- a/sgx_tstd/hashbrown/tests/set.rs +++ b/sgx_tstd/hashbrown/tests/set.rs @@ -2,29 +2,33 @@ use hashbrown::HashSet; use rand::{distributions::Alphanumeric, rngs::SmallRng, Rng, SeedableRng}; +use std::iter; #[test] fn test_hashset_insert_remove() { let mut m: HashSet> = HashSet::new(); - //let num: u32 = 4096; - //let tx: Vec> = (0..num).map(|i| (i..(16 + i)).collect()).collect(); - let seed: [u8; 16] = [ - 130, 220, 246, 217, 111, 124, 221, 189, 190, 234, 121, 93, 67, 95, 100, 43, - ]; + let seed = u64::from_le_bytes(*b"testseed"); - let rng = &mut SmallRng::from_seed(seed); - let tx: Vec> = (0..4096) - .map(|_| (rng.sample_iter(&Alphanumeric).take(32).collect())) - .collect(); + let rng = &mut SmallRng::seed_from_u64(seed); + let tx: Vec> = iter::repeat_with(|| { + rng.sample_iter(&Alphanumeric) + .take(32) + .map(char::from) + .collect() + }) + .take(4096) + .collect(); + // more readable with explicit `true` / `false` + #[allow(clippy::bool_assert_comparison)] for _ in 0..32 { - for i in 0..4096 { - assert_eq!(m.contains(&tx[i].clone()), false); - assert_eq!(m.insert(tx[i].clone()), true); + for x in &tx { + assert_eq!(m.contains(x), false); + assert_eq!(m.insert(x.clone()), true); } - for i in 0..4096 { - println!("removing {} {:?}", i, tx[i]); - assert_eq!(m.remove(&tx[i]), true); + for (i, x) in tx.iter().enumerate() { + println!("removing {} {:?}", i, x); + assert_eq!(m.remove(x), true); } } } diff --git a/sgx_tstd/src/backtrace.rs b/sgx_tstd/src/backtrace.rs index e7c96b85c..a491f5d81 100644 --- a/sgx_tstd/src/backtrace.rs +++ b/sgx_tstd/src/backtrace.rs @@ -83,13 +83,14 @@ // a backtrace or actually symbolizing it. pub use crate::sys_common::backtrace::__rust_begin_short_backtrace; -pub use crate::sys_common::backtrace::PrintFormat; use crate::cell::UnsafeCell; use crate::ffi::c_void; use crate::fmt; +use crate::fs; use crate::enclave; use crate::io; +use crate::panic::{BacktraceStyle, get_backtrace_style, set_backtrace_style}; use crate::path::Path; use crate::sync::Once; use crate::sys::backtrace::{self, BytesOrWideString}; @@ -97,12 +98,8 @@ use crate::sys_common::backtrace::{ lock, output_filename, resolve_frame_unsynchronized, - rust_backtrace_env, - RustBacktrace, - set_enabled, SymbolName, }; -use crate::untrusted::fs; use crate::vec::Vec; /// A captured OS thread stack backtrace. @@ -249,7 +246,16 @@ impl fmt::Debug for BytesOrWide { impl Backtrace { /// Returns whether backtrace captures are enabled fn enabled() -> bool { - matches!(rust_backtrace_env(), RustBacktrace::Print(_)) + match get_backtrace_style() { + Some(style) => { + match style { + BacktraceStyle::Full => true, + BacktraceStyle::Short => true, + BacktraceStyle::Off => false, + } + } + None => false, + } } /// Capture a stack backtrace of the current thread. @@ -424,6 +430,7 @@ impl LazilyResolvedCapture { unsafe impl Sync for LazilyResolvedCapture where Capture: Sync {} impl Capture { + #[allow(clippy::infallible_destructuring_match)] fn resolve(&mut self) { // If we're already resolved, nothing to do! if self.resolved { @@ -460,12 +467,19 @@ impl RawFrame { fn ip(&self) -> *mut c_void { match self { RawFrame::Actual(frame) => frame.ip(), - #[cfg(test)] - RawFrame::Fake => 1 as *mut c_void, } } } +/// Controls how the backtrace should be formatted. +#[derive(Debug, Copy, Clone, Eq, PartialEq)] +pub enum PrintFormat { + /// Show only relevant data from the backtrace. + Short, + /// Show all the frames with absolute path for files. + Full, +} + /// Enable backtrace for dumping call stack on crash. /// /// Enabling backtrace here makes the panic information along with call stack @@ -477,6 +491,10 @@ impl RawFrame { pub fn enable_backtrace>(path: P, format: PrintFormat) -> io::Result<()> { let _ = fs::metadata(&path)?; enclave::set_enclave_path(path)?; - set_enabled(format); + let style = match format { + PrintFormat::Short => BacktraceStyle::Short, + PrintFormat::Full => BacktraceStyle::Full, + }; + set_backtrace_style(style); Ok(()) } diff --git a/sgx_tstd/src/collections/hash/map.rs b/sgx_tstd/src/collections/hash/map.rs index 8b7fd7216..2c5012a40 100644 --- a/sgx_tstd/src/collections/hash/map.rs +++ b/sgx_tstd/src/collections/hash/map.rs @@ -342,10 +342,11 @@ impl HashMap { /// ``` /// use std::collections::HashMap; /// - /// let mut map = HashMap::new(); - /// map.insert("a", 1); - /// map.insert("b", 2); - /// map.insert("c", 3); + /// let map = HashMap::from([ + /// ("a", 1), + /// ("b", 2), + /// ("c", 3), + /// ]); /// /// for key in map.keys() { /// println!("{}", key); @@ -355,6 +356,33 @@ impl HashMap { Keys { inner: self.iter() } } + /// Creates a consuming iterator visiting all the keys in arbitrary order. + /// The map cannot be used after calling this. + /// The iterator element type is `K`. + /// + /// # Examples + /// + /// ``` + /// use std::collections::HashMap; + /// + /// let map = HashMap::from([ + /// ("a", 1), + /// ("b", 2), + /// ("c", 3), + /// ]); + /// + /// let mut vec: Vec<&str> = map.into_keys().collect(); + /// // The `IntoKeys` iterator produces keys in arbitrary order, so the + /// // keys must be sorted to test them against a sorted array. + /// vec.sort_unstable(); + /// assert_eq!(vec, ["a", "b", "c"]); + /// ``` + #[inline] + #[cfg_attr(not(bootstrap), rustc_lint_query_instability)] + pub fn into_keys(self) -> IntoKeys { + IntoKeys { inner: self.into_iter() } + } + /// An iterator visiting all values in arbitrary order. /// The iterator element type is `&'a V`. /// @@ -363,10 +391,11 @@ impl HashMap { /// ``` /// use std::collections::HashMap; /// - /// let mut map = HashMap::new(); - /// map.insert("a", 1); - /// map.insert("b", 2); - /// map.insert("c", 3); + /// let map = HashMap::from([ + /// ("a", 1), + /// ("b", 2), + /// ("c", 3), + /// ]); /// /// for val in map.values() { /// println!("{}", val); @@ -384,11 +413,11 @@ impl HashMap { /// ``` /// use std::collections::HashMap; /// - /// let mut map = HashMap::new(); - /// - /// map.insert("a", 1); - /// map.insert("b", 2); - /// map.insert("c", 3); + /// let mut map = HashMap::from([ + /// ("a", 1), + /// ("b", 2), + /// ("c", 3), + /// ]); /// /// for val in map.values_mut() { /// *val = *val + 10; @@ -402,6 +431,33 @@ impl HashMap { ValuesMut { inner: self.iter_mut() } } + /// Creates a consuming iterator visiting all the values in arbitrary order. + /// The map cannot be used after calling this. + /// The iterator element type is `V`. + /// + /// # Examples + /// + /// ``` + /// use std::collections::HashMap; + /// + /// let map = HashMap::from([ + /// ("a", 1), + /// ("b", 2), + /// ("c", 3), + /// ]); + /// + /// let mut vec: Vec = map.into_values().collect(); + /// // The `IntoValues` iterator produces values in arbitrary order, so + /// // the values must be sorted to test them against a sorted array. + /// vec.sort_unstable(); + /// assert_eq!(vec, [1, 2, 3]); + /// ``` + #[inline] + #[cfg_attr(not(bootstrap), rustc_lint_query_instability)] + pub fn into_values(self) -> IntoValues { + IntoValues { inner: self.into_iter() } + } + /// An iterator visiting all key-value pairs in arbitrary order. /// The iterator element type is `(&'a K, &'a V)`. /// @@ -410,15 +466,17 @@ impl HashMap { /// ``` /// use std::collections::HashMap; /// - /// let mut map = HashMap::new(); - /// map.insert("a", 1); - /// map.insert("b", 2); - /// map.insert("c", 3); + /// let map = HashMap::from([ + /// ("a", 1), + /// ("b", 2), + /// ("c", 3), + /// ]); /// /// for (key, val) in map.iter() { /// println!("key: {} val: {}", key, val); /// } /// ``` + #[cfg_attr(not(bootstrap), rustc_lint_query_instability)] pub fn iter(&self) -> Iter<'_, K, V> { Iter { base: self.base.iter() } } @@ -432,10 +490,11 @@ impl HashMap { /// ``` /// use std::collections::HashMap; /// - /// let mut map = HashMap::new(); - /// map.insert("a", 1); - /// map.insert("b", 2); - /// map.insert("c", 3); + /// let mut map = HashMap::from([ + /// ("a", 1), + /// ("b", 2), + /// ("c", 3), + /// ]); /// /// // Update all values /// for (_, val) in map.iter_mut() { @@ -446,6 +505,7 @@ impl HashMap { /// println!("key: {} val: {}", key, val); /// } /// ``` + #[cfg_attr(not(bootstrap), rustc_lint_query_instability)] pub fn iter_mut(&mut self) -> IterMut<'_, K, V> { IterMut { base: self.base.iter_mut() } } @@ -486,6 +546,10 @@ impl HashMap { /// Clears the map, returning all key-value pairs as an iterator. Keeps the /// allocated memory for reuse. /// + /// 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. + /// /// # Examples /// /// ``` @@ -503,6 +567,7 @@ impl HashMap { /// assert!(a.is_empty()); /// ``` #[inline] + #[cfg_attr(not(bootstrap), rustc_lint_query_instability)] pub fn drain(&mut self) -> Drain<'_, K, V> { Drain { base: self.base.drain() } } @@ -543,6 +608,7 @@ impl HashMap { /// assert_eq!(odds, vec![1, 3, 5, 7]); /// ``` #[inline] + #[cfg_attr(not(bootstrap), rustc_lint_query_instability)] pub fn drain_filter(&mut self, pred: F) -> DrainFilter<'_, K, V, F> where F: FnMut(&K, &mut V) -> bool, @@ -550,6 +616,29 @@ impl HashMap { DrainFilter { base: self.base.drain_filter(pred) } } + /// Retains only the elements specified by the predicate. + /// + /// In other words, remove all pairs `(k, v)` such that `f(&k, &mut v)` returns `false`. + /// The elements are visited in unsorted (and unspecified) order. + /// + /// # Examples + /// + /// ``` + /// use std::collections::HashMap; + /// + /// let mut map: HashMap = (0..8).map(|x| (x, x*10)).collect(); + /// map.retain(|&k, _| k % 2 == 0); + /// assert_eq!(map.len(), 4); + /// ``` + #[inline] + #[cfg_attr(not(bootstrap), rustc_lint_query_instability)] + pub fn retain(&mut self, f: F) + where + F: FnMut(&K, &mut V) -> bool, + { + self.base.retain(f) + } + /// Clears the map, removing all key-value pairs. Keeps the allocated memory /// for reuse. /// @@ -917,78 +1006,6 @@ where { self.base.remove_entry(k) } - - /// Retains only the elements specified by the predicate. - /// - /// In other words, remove all pairs `(k, v)` such that `f(&k, &mut v)` returns `false`. - /// The elements are visited in unsorted (and unspecified) order. - /// - /// # Examples - /// - /// ``` - /// use std::collections::HashMap; - /// - /// let mut map: HashMap = (0..8).map(|x| (x, x*10)).collect(); - /// map.retain(|&k, _| k % 2 == 0); - /// assert_eq!(map.len(), 4); - /// ``` - #[inline] - pub fn retain(&mut self, f: F) - where - F: FnMut(&K, &mut V) -> bool, - { - self.base.retain(f) - } - - /// Creates a consuming iterator visiting all the keys in arbitrary order. - /// The map cannot be used after calling this. - /// The iterator element type is `K`. - /// - /// # Examples - /// - /// ``` - /// use std::collections::HashMap; - /// - /// let mut map = HashMap::new(); - /// map.insert("a", 1); - /// map.insert("b", 2); - /// map.insert("c", 3); - /// - /// let mut vec: Vec<&str> = map.into_keys().collect(); - /// // The `IntoKeys` iterator produces keys in arbitrary order, so the - /// // keys must be sorted to test them against a sorted array. - /// vec.sort_unstable(); - /// assert_eq!(vec, ["a", "b", "c"]); - /// ``` - #[inline] - pub fn into_keys(self) -> IntoKeys { - IntoKeys { inner: self.into_iter() } - } - - /// Creates a consuming iterator visiting all the values in arbitrary order. - /// The map cannot be used after calling this. - /// The iterator element type is `V`. - /// - /// # Examples - /// - /// ``` - /// use std::collections::HashMap; - /// - /// let mut map = HashMap::new(); - /// map.insert("a", 1); - /// map.insert("b", 2); - /// map.insert("c", 3); - /// - /// let mut vec: Vec = map.into_values().collect(); - /// // The `IntoValues` iterator produces values in arbitrary order, so - /// // the values must be sorted to test them against a sorted array. - /// vec.sort_unstable(); - /// assert_eq!(vec, [1, 2, 3]); - /// ``` - #[inline] - pub fn into_values(self) -> IntoValues { - IntoValues { inner: self.into_iter() } - } } impl HashMap @@ -1158,7 +1175,7 @@ where /// assert_eq!(map1, map2); /// ``` fn from(arr: [(K, V); N]) -> Self { - crate::array::IntoIter::new(arr).collect() + Self::from_iter(arr) } } @@ -1174,8 +1191,9 @@ where /// ``` /// use std::collections::HashMap; /// -/// let mut map = HashMap::new(); -/// map.insert("a", 1); +/// let map = HashMap::from([ +/// ("a", 1), +/// ]); /// let iter = map.iter(); /// ``` pub struct Iter<'a, K: 'a, V: 'a> { @@ -1208,8 +1226,9 @@ impl fmt::Debug for Iter<'_, K, V> { /// ``` /// use std::collections::HashMap; /// -/// let mut map = HashMap::new(); -/// map.insert("a", 1); +/// let mut map = HashMap::from([ +/// ("a", 1), +/// ]); /// let iter = map.iter_mut(); /// ``` pub struct IterMut<'a, K: 'a, V: 'a> { @@ -1237,8 +1256,9 @@ impl<'a, K, V> IterMut<'a, K, V> { /// ``` /// use std::collections::HashMap; /// -/// let mut map = HashMap::new(); -/// map.insert("a", 1); +/// let map = HashMap::from([ +/// ("a", 1), +/// ]); /// let iter = map.into_iter(); /// ``` pub struct IntoIter { @@ -1265,8 +1285,9 @@ impl IntoIter { /// ``` /// use std::collections::HashMap; /// -/// let mut map = HashMap::new(); -/// map.insert("a", 1); +/// let map = HashMap::from([ +/// ("a", 1), +/// ]); /// let iter_keys = map.keys(); /// ``` pub struct Keys<'a, K: 'a, V: 'a> { @@ -1299,8 +1320,9 @@ impl fmt::Debug for Keys<'_, K, V> { /// ``` /// use std::collections::HashMap; /// -/// let mut map = HashMap::new(); -/// map.insert("a", 1); +/// let map = HashMap::from([ +/// ("a", 1), +/// ]); /// let iter_values = map.values(); /// ``` pub struct Values<'a, K: 'a, V: 'a> { @@ -1333,8 +1355,9 @@ impl fmt::Debug for Values<'_, K, V> { /// ``` /// use std::collections::HashMap; /// -/// let mut map = HashMap::new(); -/// map.insert("a", 1); +/// let mut map = HashMap::from([ +/// ("a", 1), +/// ]); /// let iter = map.drain(); /// ``` pub struct Drain<'a, K: 'a, V: 'a> { @@ -1362,8 +1385,9 @@ impl<'a, K, V> Drain<'a, K, V> { /// /// use std::collections::HashMap; /// -/// let mut map = HashMap::new(); -/// map.insert("a", 1); +/// let mut map = HashMap::from([ +/// ("a", 1), +/// ]); /// let iter = map.drain_filter(|_k, v| *v % 2 == 0); /// ``` pub struct DrainFilter<'a, K, V, F> @@ -1385,8 +1409,9 @@ where /// ``` /// use std::collections::HashMap; /// -/// let mut map = HashMap::new(); -/// map.insert("a", 1); +/// let mut map = HashMap::from([ +/// ("a", 1), +/// ]); /// let iter_values = map.values_mut(); /// ``` pub struct ValuesMut<'a, K: 'a, V: 'a> { @@ -1405,8 +1430,9 @@ pub struct ValuesMut<'a, K: 'a, V: 'a> { /// ``` /// use std::collections::HashMap; /// -/// let mut map = HashMap::new(); -/// map.insert("a", 1); +/// let map = HashMap::from([ +/// ("a", 1), +/// ]); /// let iter_keys = map.into_keys(); /// ``` pub struct IntoKeys { @@ -1425,8 +1451,9 @@ pub struct IntoKeys { /// ``` /// use std::collections::HashMap; /// -/// let mut map = HashMap::new(); -/// map.insert("a", 1); +/// let map = HashMap::from([ +/// ("a", 1), +/// ]); /// let iter_keys = map.into_values(); /// ``` pub struct IntoValues { @@ -1628,6 +1655,7 @@ impl<'a, K, V, S> RawEntryMut<'a, K, V, S> { /// .or_insert("poneyland", 0); /// assert_eq!(map["poneyland"], 43); /// ``` + #[must_use] #[inline] pub fn and_modify(self, f: F) -> Self where @@ -1912,15 +1940,17 @@ impl IntoIterator for HashMap { /// ``` /// use std::collections::HashMap; /// - /// let mut map = HashMap::new(); - /// map.insert("a", 1); - /// map.insert("b", 2); - /// map.insert("c", 3); + /// let map = HashMap::from([ + /// ("a", 1), + /// ("b", 2), + /// ("c", 3), + /// ]); /// /// // Not possible with .iter() /// let vec: Vec<(&str, i32)> = map.into_iter().collect(); /// ``` #[inline] + #[cfg_attr(not(bootstrap), rustc_lint_query_instability)] fn into_iter(self) -> IntoIter { IntoIter { base: self.base.into_iter() } } @@ -2310,6 +2340,7 @@ impl<'a, K, V> Entry<'a, K, V> { /// .or_insert(42); /// assert_eq!(map["poneyland"], 43); /// ``` + #[must_use] #[inline] pub fn and_modify(self, f: F) -> Self where @@ -2333,12 +2364,12 @@ impl<'a, K, V> Entry<'a, K, V> { /// use std::collections::HashMap; /// /// let mut map: HashMap<&str, String> = HashMap::new(); - /// let entry = map.entry("poneyland").insert("hoho".to_string()); + /// let entry = map.entry("poneyland").insert_entry("hoho".to_string()); /// /// assert_eq!(entry.key(), &"poneyland"); /// ``` #[inline] - pub fn insert(self, value: V) -> OccupiedEntry<'a, K, V> { + pub fn insert_entry(self, value: V) -> OccupiedEntry<'a, K, V> { match self { Occupied(mut entry) => { entry.insert(value); @@ -2664,12 +2695,12 @@ impl<'a, K: 'a, V: 'a> VacantEntry<'a, K, V> { /// let mut map: HashMap<&str, u32> = HashMap::new(); /// /// if let Entry::Vacant(o) = map.entry("poneyland") { - /// o.insert(37); + /// o.insert_entry(37); /// } /// assert_eq!(map["poneyland"], 37); /// ``` #[inline] - fn insert_entry(self, value: V) -> OccupiedEntry<'a, K, V> { + pub fn insert_entry(self, value: V) -> OccupiedEntry<'a, K, V> { let base = self.base.insert_entry(value); OccupiedEntry { base } } diff --git a/sgx_tstd/src/collections/hash/set.rs b/sgx_tstd/src/collections/hash/set.rs index 2eb65771d..b6b62b629 100644 --- a/sgx_tstd/src/collections/hash/set.rs +++ b/sgx_tstd/src/collections/hash/set.rs @@ -195,6 +195,7 @@ impl HashSet { /// } /// ``` #[inline] + #[cfg_attr(not(bootstrap), rustc_lint_query_instability)] pub fn iter(&self) -> Iter<'_, T> { Iter { base: self.base.iter() } } @@ -233,14 +234,19 @@ impl HashSet { self.base.is_empty() } - /// Clears the set, returning all elements in an iterator. + /// Clears the set, returning all elements as an iterator. Keeps the + /// allocated memory for reuse. + /// + /// 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. /// /// # Examples /// /// ``` /// use std::collections::HashSet; /// - /// let mut set: HashSet<_> = [1, 2, 3].iter().cloned().collect(); + /// let mut set = HashSet::from([1, 2, 3]); /// assert!(!set.is_empty()); /// /// // print 1, 2, 3 in an arbitrary order @@ -251,6 +257,7 @@ impl HashSet { /// assert!(set.is_empty()); /// ``` #[inline] + #[cfg_attr(not(bootstrap), rustc_lint_query_instability)] pub fn drain(&mut self) -> Drain<'_, T> { Drain { base: self.base.drain() } } @@ -288,6 +295,7 @@ impl HashSet { /// assert_eq!(odds, vec![1, 3, 5, 7]); /// ``` #[inline] + #[cfg_attr(not(bootstrap), rustc_lint_query_instability)] pub fn drain_filter(&mut self, pred: F) -> DrainFilter<'_, T, F> where F: FnMut(&T) -> bool, @@ -295,6 +303,28 @@ impl HashSet { DrainFilter { base: self.base.drain_filter(pred) } } + /// Retains only the elements specified by the predicate. + /// + /// In other words, remove all elements `e` such that `f(&e)` returns `false`. + /// The elements are visited in unsorted (and unspecified) order. + /// + /// # Examples + /// + /// ``` + /// use std::collections::HashSet; + /// + /// let mut set = HashSet::from([1, 2, 3, 4, 5, 6]); + /// set.retain(|&k| k % 2 == 0); + /// assert_eq!(set.len(), 3); + /// ``` + #[cfg_attr(not(bootstrap), rustc_lint_query_instability)] + pub fn retain(&mut self, f: F) + where + F: FnMut(&T) -> bool, + { + self.base.retain(f) + } + /// Clears the set, removing all values. /// /// # Examples @@ -486,8 +516,8 @@ where /// /// ``` /// use std::collections::HashSet; - /// let a: HashSet<_> = [1, 2, 3].iter().cloned().collect(); - /// let b: HashSet<_> = [4, 2, 3, 4].iter().cloned().collect(); + /// let a = HashSet::from([1, 2, 3]); + /// let b = HashSet::from([4, 2, 3, 4]); /// /// // Can be seen as `a - b`. /// for x in a.difference(&b) { @@ -503,6 +533,7 @@ where /// assert_eq!(diff, [4].iter().collect()); /// ``` #[inline] + #[cfg_attr(not(bootstrap), rustc_lint_query_instability)] pub fn difference<'a>(&'a self, other: &'a HashSet) -> Difference<'a, T, S> { Difference { iter: self.iter(), other } } @@ -514,8 +545,8 @@ where /// /// ``` /// use std::collections::HashSet; - /// let a: HashSet<_> = [1, 2, 3].iter().cloned().collect(); - /// let b: HashSet<_> = [4, 2, 3, 4].iter().cloned().collect(); + /// let a = HashSet::from([1, 2, 3]); + /// let b = HashSet::from([4, 2, 3, 4]); /// /// // Print 1, 4 in arbitrary order. /// for x in a.symmetric_difference(&b) { @@ -529,6 +560,7 @@ where /// assert_eq!(diff1, [1, 4].iter().collect()); /// ``` #[inline] + #[cfg_attr(not(bootstrap), rustc_lint_query_instability)] pub fn symmetric_difference<'a>( &'a self, other: &'a HashSet, @@ -543,8 +575,8 @@ where /// /// ``` /// use std::collections::HashSet; - /// let a: HashSet<_> = [1, 2, 3].iter().cloned().collect(); - /// let b: HashSet<_> = [4, 2, 3, 4].iter().cloned().collect(); + /// let a = HashSet::from([1, 2, 3]); + /// let b = HashSet::from([4, 2, 3, 4]); /// /// // Print 2, 3 in arbitrary order. /// for x in a.intersection(&b) { @@ -555,6 +587,7 @@ where /// assert_eq!(intersection, [2, 3].iter().collect()); /// ``` #[inline] + #[cfg_attr(not(bootstrap), rustc_lint_query_instability)] pub fn intersection<'a>(&'a self, other: &'a HashSet) -> Intersection<'a, T, S> { if self.len() <= other.len() { Intersection { iter: self.iter(), other } @@ -570,8 +603,8 @@ where /// /// ``` /// use std::collections::HashSet; - /// let a: HashSet<_> = [1, 2, 3].iter().cloned().collect(); - /// let b: HashSet<_> = [4, 2, 3, 4].iter().cloned().collect(); + /// let a = HashSet::from([1, 2, 3]); + /// let b = HashSet::from([4, 2, 3, 4]); /// /// // Print 1, 2, 3, 4 in arbitrary order. /// for x in a.union(&b) { @@ -582,6 +615,7 @@ where /// assert_eq!(union, [1, 2, 3, 4].iter().collect()); /// ``` #[inline] + #[cfg_attr(not(bootstrap), rustc_lint_query_instability)] pub fn union<'a>(&'a self, other: &'a HashSet) -> Union<'a, T, S> { if self.len() >= other.len() { Union { iter: self.iter().chain(other.difference(self)) } @@ -601,7 +635,7 @@ where /// ``` /// use std::collections::HashSet; /// - /// let set: HashSet<_> = [1, 2, 3].iter().cloned().collect(); + /// let set = HashSet::from([1, 2, 3]); /// assert_eq!(set.contains(&1), true); /// assert_eq!(set.contains(&4), false); /// ``` @@ -625,7 +659,7 @@ where /// ``` /// use std::collections::HashSet; /// - /// let set: HashSet<_> = [1, 2, 3].iter().cloned().collect(); + /// let set = HashSet::from([1, 2, 3]); /// assert_eq!(set.get(&2), Some(&2)); /// assert_eq!(set.get(&4), None); /// ``` @@ -648,7 +682,7 @@ where /// /// use std::collections::HashSet; /// - /// let mut set: HashSet<_> = [1, 2, 3].iter().cloned().collect(); + /// let mut set = HashSet::from([1, 2, 3]); /// assert_eq!(set.len(), 3); /// assert_eq!(set.get_or_insert(2), &2); /// assert_eq!(set.get_or_insert(100), &100); @@ -732,7 +766,7 @@ where /// ``` /// use std::collections::HashSet; /// - /// let a: HashSet<_> = [1, 2, 3].iter().cloned().collect(); + /// let a = HashSet::from([1, 2, 3]); /// let mut b = HashSet::new(); /// /// assert_eq!(a.is_disjoint(&b), true); @@ -757,7 +791,7 @@ where /// ``` /// use std::collections::HashSet; /// - /// let sup: HashSet<_> = [1, 2, 3].iter().cloned().collect(); + /// let sup = HashSet::from([1, 2, 3]); /// let mut set = HashSet::new(); /// /// assert_eq!(set.is_subset(&sup), true); @@ -778,7 +812,7 @@ where /// ``` /// use std::collections::HashSet; /// - /// let sub: HashSet<_> = [1, 2].iter().cloned().collect(); + /// let sub = HashSet::from([1, 2]); /// let mut set = HashSet::new(); /// /// assert_eq!(set.is_superset(&sub), false); @@ -875,7 +909,7 @@ where /// ``` /// use std::collections::HashSet; /// - /// let mut set: HashSet<_> = [1, 2, 3].iter().cloned().collect(); + /// let mut set = HashSet::from([1, 2, 3]); /// assert_eq!(set.take(&2), Some(2)); /// assert_eq!(set.take(&2), None); /// ``` @@ -887,28 +921,6 @@ where { self.base.take(value) } - - /// Retains only the elements specified by the predicate. - /// - /// In other words, remove all elements `e` such that `f(&e)` returns `false`. - /// The elements are visited in unsorted (and unspecified) order. - /// - /// # Examples - /// - /// ``` - /// use std::collections::HashSet; - /// - /// let xs = [1, 2, 3, 4, 5, 6]; - /// let mut set: HashSet = xs.iter().cloned().collect(); - /// set.retain(|&k| k % 2 == 0); - /// assert_eq!(set.len(), 3); - /// ``` - pub fn retain(&mut self, f: F) - where - F: FnMut(&T) -> bool, - { - self.base.retain(f) - } } impl Clone for HashSet @@ -996,7 +1008,7 @@ where /// assert_eq!(set1, set2); /// ``` fn from(arr: [T; N]) -> Self { - crate::array::IntoIter::new(arr).collect() + Self::from_iter(arr) } } @@ -1067,8 +1079,8 @@ where /// ``` /// use std::collections::HashSet; /// - /// let a: HashSet<_> = vec![1, 2, 3].into_iter().collect(); - /// let b: HashSet<_> = vec![3, 4, 5].into_iter().collect(); + /// let a = HashSet::from([1, 2, 3]); + /// let b = HashSet::from([3, 4, 5]); /// /// let set = &a | &b; /// @@ -1099,8 +1111,8 @@ where /// ``` /// use std::collections::HashSet; /// - /// let a: HashSet<_> = vec![1, 2, 3].into_iter().collect(); - /// let b: HashSet<_> = vec![2, 3, 4].into_iter().collect(); + /// let a = HashSet::from([1, 2, 3]); + /// let b = HashSet::from([2, 3, 4]); /// /// let set = &a & &b; /// @@ -1131,8 +1143,8 @@ where /// ``` /// use std::collections::HashSet; /// - /// let a: HashSet<_> = vec![1, 2, 3].into_iter().collect(); - /// let b: HashSet<_> = vec![3, 4, 5].into_iter().collect(); + /// let a = HashSet::from([1, 2, 3]); + /// let b = HashSet::from([3, 4, 5]); /// /// let set = &a ^ &b; /// @@ -1163,8 +1175,8 @@ where /// ``` /// use std::collections::HashSet; /// - /// let a: HashSet<_> = vec![1, 2, 3].into_iter().collect(); - /// let b: HashSet<_> = vec![3, 4, 5].into_iter().collect(); + /// let a = HashSet::from([1, 2, 3]); + /// let b = HashSet::from([3, 4, 5]); /// /// let set = &a - &b; /// @@ -1193,7 +1205,7 @@ where /// ``` /// use std::collections::HashSet; /// -/// let a: HashSet = vec![1, 2, 3].into_iter().collect(); +/// let a = HashSet::from([1, 2, 3]); /// /// let mut iter = a.iter(); /// ``` @@ -1214,7 +1226,7 @@ pub struct Iter<'a, K: 'a> { /// ``` /// use std::collections::HashSet; /// -/// let a: HashSet = vec![1, 2, 3].into_iter().collect(); +/// let a = HashSet::from([1, 2, 3]); /// /// let mut iter = a.into_iter(); /// ``` @@ -1234,7 +1246,7 @@ pub struct IntoIter { /// ``` /// use std::collections::HashSet; /// -/// let mut a: HashSet = vec![1, 2, 3].into_iter().collect(); +/// let mut a = HashSet::from([1, 2, 3]); /// /// let mut drain = a.drain(); /// ``` @@ -1255,7 +1267,7 @@ pub struct Drain<'a, K: 'a> { /// /// use std::collections::HashSet; /// -/// let mut a: HashSet = vec![1, 2, 3].into_iter().collect(); +/// let mut a = HashSet::from([1, 2, 3]); /// /// let mut drain_filtered = a.drain_filter(|v| v % 2 == 0); /// ``` @@ -1278,8 +1290,8 @@ where /// ``` /// use std::collections::HashSet; /// -/// let a: HashSet = vec![1, 2, 3].into_iter().collect(); -/// let b: HashSet<_> = [4, 2, 3, 4].iter().cloned().collect(); +/// let a = HashSet::from([1, 2, 3]); +/// let b = HashSet::from([4, 2, 3, 4]); /// /// let mut intersection = a.intersection(&b); /// ``` @@ -1304,8 +1316,8 @@ pub struct Intersection<'a, T: 'a, S: 'a> { /// ``` /// use std::collections::HashSet; /// -/// let a: HashSet = vec![1, 2, 3].into_iter().collect(); -/// let b: HashSet<_> = [4, 2, 3, 4].iter().cloned().collect(); +/// let a = HashSet::from([1, 2, 3]); +/// let b = HashSet::from([4, 2, 3, 4]); /// /// let mut difference = a.difference(&b); /// ``` @@ -1330,8 +1342,8 @@ pub struct Difference<'a, T: 'a, S: 'a> { /// ``` /// use std::collections::HashSet; /// -/// let a: HashSet = vec![1, 2, 3].into_iter().collect(); -/// let b: HashSet<_> = [4, 2, 3, 4].iter().cloned().collect(); +/// let a = HashSet::from([1, 2, 3]); +/// let b = HashSet::from([4, 2, 3, 4]); /// /// let mut intersection = a.symmetric_difference(&b); /// ``` @@ -1353,8 +1365,8 @@ pub struct SymmetricDifference<'a, T: 'a, S: 'a> { /// ``` /// use std::collections::HashSet; /// -/// let a: HashSet = vec![1, 2, 3].into_iter().collect(); -/// let b: HashSet<_> = [4, 2, 3, 4].iter().cloned().collect(); +/// let a = HashSet::from([1, 2, 3]); +/// let b = HashSet::from([4, 2, 3, 4]); /// /// let mut union_iter = a.union(&b); /// ``` @@ -1369,6 +1381,7 @@ impl<'a, T, S> IntoIterator for &'a HashSet { type IntoIter = Iter<'a, T>; #[inline] + #[cfg_attr(not(bootstrap), rustc_lint_query_instability)] fn into_iter(self) -> Iter<'a, T> { self.iter() } @@ -1399,6 +1412,7 @@ impl IntoIterator for HashSet { /// } /// ``` #[inline] + #[cfg_attr(not(bootstrap), rustc_lint_query_instability)] fn into_iter(self) -> IntoIter { IntoIter { base: self.base.into_iter() } } diff --git a/sgx_tstd/src/collections/mod.rs b/sgx_tstd/src/collections/mod.rs index aca02b248..5b2dcbd15 100644 --- a/sgx_tstd/src/collections/mod.rs +++ b/sgx_tstd/src/collections/mod.rs @@ -249,7 +249,7 @@ //! ``` //! use std::collections::VecDeque; //! -//! let vec = vec![1, 2, 3, 4]; +//! let vec = [1, 2, 3, 4]; //! let buf: VecDeque<_> = vec.into_iter().collect(); //! ``` //! @@ -285,7 +285,7 @@ //! not. Normally, this would require a `find` followed by an `insert`, //! effectively duplicating the search effort on each insertion. //! -//! When a user calls `map.entry(&key)`, the map will search for the key and +//! When a user calls `map.entry(key)`, the map will search for the key and //! then yield a variant of the `Entry` enum. //! //! If a `Vacant(entry)` is yielded, then the key *was not* found. In this case diff --git a/sgx_tstd/src/env.rs b/sgx_tstd/src/env.rs index 1cd21da94..cae3405cc 100644 --- a/sgx_tstd/src/env.rs +++ b/sgx_tstd/src/env.rs @@ -35,6 +35,11 @@ use crate::sys::os as os_imp; /// Returns the current working directory as a [`PathBuf`]. /// +/// # Platform-specific behavior +/// +/// This function currently corresponds to the `getcwd` function on Unix +/// and the `GetCurrentDirectoryW` function on Windows. +/// /// # Errors /// /// Returns an [`Err`] if the current working directory value is invalid. @@ -60,6 +65,11 @@ pub fn current_dir() -> io::Result { /// Changes the current working directory to the specified path. /// +/// # Platform-specific behavior +/// +/// This function currently corresponds to the `chdir` function on Unix +/// and the `SetCurrentDirectoryW` function on Windows. +/// /// Returns an [`Err`] if the operation fails. /// /// # Examples @@ -562,28 +572,25 @@ pub fn home_dir() -> Option { /// may result in "insecure temporary file" security vulnerabilities. Consider /// using a crate that securely creates temporary files or directories. /// -/// # Unix +/// # Platform-specific behavior /// -/// Returns the value of the `TMPDIR` environment variable if it is +/// 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 /// 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] / +/// [`GetTempPath`][GetTempPath], which this function uses internally. +/// Note that, this [may change in the future][changes]. /// -/// # Windows -/// -/// Returns the value of, in order, the `TMP`, `TEMP`, -/// `USERPROFILE` environment variable if any are set and not the empty -/// string. Otherwise, `temp_dir` returns the path of the Windows directory. -/// This behavior is identical to that of [`GetTempPath`][msdn], which this -/// function uses internally. -/// -/// [msdn]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-gettemppatha +/// [changes]: io#platform-specific-behavior +/// [GetTempPath2]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-gettemppath2a +/// [GetTempPath]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-gettemppatha /// /// ```no_run /// use std::env; /// /// fn main() { -/// let mut dir = env::temp_dir(); +/// let dir = env::temp_dir(); /// println!("Temporary directory: {}", dir.display()); /// } /// ``` diff --git a/sgx_tstd/src/error.rs b/sgx_tstd/src/error.rs index 91cc72c7d..d795fc9a1 100644 --- a/sgx_tstd/src/error.rs +++ b/sgx_tstd/src/error.rs @@ -39,11 +39,14 @@ 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 sgx_types::sgx_status_t; @@ -76,7 +79,7 @@ pub trait Error: Debug + Display { /// /// #[derive(Debug)] /// struct SuperError { - /// side: SuperErrorSideKick, + /// source: SuperErrorSideKick, /// } /// /// impl fmt::Display for SuperError { @@ -87,7 +90,7 @@ pub trait Error: Debug + Display { /// /// impl Error for SuperError { /// fn source(&self) -> Option<&(dyn Error + 'static)> { - /// Some(&self.side) + /// Some(&self.source) /// } /// } /// @@ -103,7 +106,7 @@ pub trait Error: Debug + Display { /// impl Error for SuperErrorSideKick {} /// /// fn get_super_error() -> Result<(), SuperError> { - /// Err(SuperError { side: SuperErrorSideKick }) + /// Err(SuperError { source: SuperErrorSideKick }) /// } /// /// fn main() { @@ -452,6 +455,8 @@ impl Error for char::DecodeUtf16Error { } } +impl Error for char::TryFromCharError {} + impl<'a, K: Debug + Ord, V: Debug> Error for crate::collections::btree_map::OccupiedError<'a, K, V> { @@ -570,24 +575,24 @@ impl Error for char::ParseCharError { impl Error for alloc_crate::collections::TryReserveError {} -impl Error for core::time::FromSecsError {} +impl Error for time::FromFloatSecsError {} // Copied from `any.rs`. impl dyn Error + 'static { - /// Returns `true` if the boxed type is the same as `T` + /// Returns `true` if the inner type is the same as `T`. #[inline] pub fn is(&self) -> bool { // Get `TypeId` of the type this function is instantiated with. let t = TypeId::of::(); - // Get `TypeId` of the type in the trait object. - let boxed = self.type_id(private::Internal); + // Get `TypeId` of the type in the trait object (`self`). + let concrete = self.type_id(private::Internal); // Compare both `TypeId`s on equality. - t == boxed + t == concrete } - /// Returns some reference to the boxed value if it is of type `T`, or + /// Returns some reference to the inner value if it is of type `T`, or /// `None` if it isn't. #[inline] pub fn downcast_ref(&self) -> Option<&T> { @@ -598,7 +603,7 @@ impl dyn Error + 'static { } } - /// Returns some mutable reference to the boxed value if it is of type `T`, or + /// 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(&mut self) -> Option<&mut T> { @@ -763,3 +768,637 @@ impl dyn Error + Send + Sync { }) } } + +/// 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` only requires that the wrapped error implements `Error`. It doesn't require that the +/// wrapped error be `Send`, `Sync`, or `'static`. +/// +/// # Examples +/// +/// ```rust +/// #![feature(error_reporter)] +/// use std::error::{Error, Report}; +/// 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: {}", Report::new(e)), +/// _ => println!("No error"), +/// } +/// } +/// ``` +/// +/// This example produces the following output: +/// +/// ```console +/// Error: SuperError is here!: SuperErrorSideKick is here! +/// ``` +/// +/// ## Output consistency +/// +/// Report prints the same output via `Display` and `Debug`, so it works well with +/// [`Result::unwrap`]/[`Result::expect`] which print their `Err` variant via `Debug`: +/// +/// ```should_panic +/// #![feature(error_reporter)] +/// use std::error::Report; +/// # 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 }) +/// # } +/// +/// get_super_error().map_err(Report::new).unwrap(); +/// ``` +/// +/// This example produces the following output: +/// +/// ```console +/// thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: SuperError is here!: SuperErrorSideKick is here!', src/error.rs:34:40 +/// note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace +/// ``` +/// +/// ## Return from `main` +/// +/// `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`. +/// +/// ```should_panic +/// #![feature(error_reporter)] +/// use std::error::Report; +/// # 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() -> Result<(), Report> { +/// get_super_error()?; +/// Ok(()) +/// } +/// ``` +/// +/// This example produces the following output: +/// +/// ```console +/// Error: SuperError is here!: SuperErrorSideKick is here! +/// ``` +/// +/// **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 +/// you will need to manually convert and enable those flags. +/// +/// ```should_panic +/// #![feature(error_reporter)] +/// use std::error::Report; +/// # 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() -> Result<(), Report> { +/// get_super_error() +/// .map_err(Report::from) +/// .map_err(|r| r.pretty(true).show_backtrace(true))?; +/// Ok(()) +/// } +/// ``` +/// +/// This example produces the following output: +/// +/// ```console +/// Error: SuperError is here! +/// +/// Caused by: +/// SuperErrorSideKick is here! +/// ``` +#[cfg(feature = "backtrace")] +pub struct Report> { + /// The error being reported. + error: E, + /// Whether a backtrace should be included as part of the report. + show_backtrace: bool, + /// Whether the report should be pretty-printed. + pretty: bool, +} + +#[cfg(feature = "backtrace")] +impl Report +where + Report: From, +{ + /// Create a new `Report` from an input error. + pub fn new(error: E) -> Report { + Self::from(error) + } +} + +#[cfg(feature = "backtrace")] +impl Report { + /// Enable pretty-printing the report across multiple lines. + /// + /// # Examples + /// + /// ```rust + /// #![feature(error_reporter)] + /// use std::error::Report; + /// # 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 {} + /// + /// let error = SuperError { source: SuperErrorSideKick }; + /// let report = Report::new(error).pretty(true); + /// eprintln!("Error: {:?}", report); + /// ``` + /// + /// This example produces the following output: + /// + /// ```console + /// Error: SuperError is here! + /// + /// Caused by: + /// SuperErrorSideKick is here! + /// ``` + /// + /// When there are multiple source errors the causes will be numbered in order of iteration + /// starting from the outermost error. + /// + /// ```rust + /// #![feature(error_reporter)] + /// use std::error::Report; + /// # 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 { + /// # source: SuperErrorSideKickSideKick, + /// # } + /// # impl fmt::Display for SuperErrorSideKick { + /// # fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + /// # write!(f, "SuperErrorSideKick is here!") + /// # } + /// # } + /// # impl Error for SuperErrorSideKick { + /// # fn source(&self) -> Option<&(dyn Error + 'static)> { + /// # Some(&self.source) + /// # } + /// # } + /// # #[derive(Debug)] + /// # struct SuperErrorSideKickSideKick; + /// # impl fmt::Display for SuperErrorSideKickSideKick { + /// # fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + /// # write!(f, "SuperErrorSideKickSideKick is here!") + /// # } + /// # } + /// # impl Error for SuperErrorSideKickSideKick { } + /// + /// let source = SuperErrorSideKickSideKick; + /// let source = SuperErrorSideKick { source }; + /// let error = SuperError { source }; + /// let report = Report::new(error).pretty(true); + /// eprintln!("Error: {:?}", report); + /// ``` + /// + /// This example produces the following output: + /// + /// ```console + /// Error: SuperError is here! + /// + /// Caused by: + /// 0: SuperErrorSideKick is here! + /// 1: SuperErrorSideKickSideKick is here! + /// ``` + pub fn pretty(mut self, pretty: bool) -> Self { + self.pretty = pretty; + self + } + + /// Display backtrace if available when using pretty output format. + /// + /// # Examples + /// + /// **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`. + /// + /// ```rust + /// #![feature(error_reporter)] + /// #![feature(backtrace)] + /// # use std::error::Error; + /// # use std::fmt; + /// use std::error::Report; + /// use std::backtrace::Backtrace; + /// + /// # #[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 { + /// backtrace: Backtrace, + /// } + /// + /// impl SuperErrorSideKick { + /// fn new() -> SuperErrorSideKick { + /// SuperErrorSideKick { backtrace: Backtrace::force_capture() } + /// } + /// } + /// + /// impl Error for SuperErrorSideKick { + /// fn backtrace(&self) -> Option<&Backtrace> { + /// Some(&self.backtrace) + /// } + /// } + /// + /// // The rest of the example is unchanged ... + /// # impl fmt::Display for SuperErrorSideKick { + /// # fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + /// # write!(f, "SuperErrorSideKick is here!") + /// # } + /// # } + /// + /// let source = SuperErrorSideKick::new(); + /// let error = SuperError { source }; + /// let report = Report::new(error).pretty(true).show_backtrace(true); + /// eprintln!("Error: {:?}", report); + /// ``` + /// + /// This example produces something similar to the following output: + /// + /// ```console + /// Error: SuperError is here! + /// + /// Caused by: + /// SuperErrorSideKick is here! + /// + /// Stack backtrace: + /// 0: rust_out::main::_doctest_main_src_error_rs_1158_0::SuperErrorSideKick::new + /// 1: rust_out::main::_doctest_main_src_error_rs_1158_0 + /// 2: rust_out::main + /// 3: core::ops::function::FnOnce::call_once + /// 4: std::sys_common::backtrace::__rust_begin_short_backtrace + /// 5: std::rt::lang_start::{{closure}} + /// 6: std::panicking::try + /// 7: std::rt::lang_start_internal + /// 8: std::rt::lang_start + /// 9: main + /// 10: __libc_start_main + /// 11: _start + /// ``` + pub fn show_backtrace(mut self, show_backtrace: bool) -> Self { + self.show_backtrace = show_backtrace; + self + } +} + +#[cfg(feature = "backtrace")] +impl Report +where + E: 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(); + 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(::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> { + 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(::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 From for Report +where + E: Error, +{ + fn from(error: E) -> Self { + Report { error, show_backtrace: false, pretty: false } + } +} + +#[cfg(feature = "backtrace")] +impl<'a, E> From for Report> +where + E: Error + 'a, +{ + fn from(error: E) -> Self { + let error = box error; + Report { error, show_backtrace: false, pretty: false } + } +} + +#[cfg(feature = "backtrace")] +impl fmt::Display for Report +where + E: Error, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + if self.pretty { self.fmt_multiline(f) } else { self.fmt_singleline(f) } + } +} + +#[cfg(feature = "backtrace")] +impl fmt::Display for Report> { + 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 fmt::Debug for Report +where + Report: fmt::Display, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(self, f) + } +} + +/// Wrapper type for indenting the inner source. +#[cfg(feature = "backtrace")] +struct Indented<'a, D> { + inner: &'a mut D, +} + +#[cfg(feature = "backtrace")] +impl Write for Indented<'_, T> +where + T: Write, +{ + fn write_str(&mut self, s: &str) -> fmt::Result { + for (i, line) in s.split('\n').enumerate() { + if i > 0 { + self.inner.write_char('\n')?; + self.inner.write_str(" ")?; + } + + self.inner.write_str(line)?; + } + + Ok(()) + } +} diff --git a/sgx_tstd/src/ffi/c_str.rs b/sgx_tstd/src/ffi/c_str.rs index 1e542cea7..6ecdabd1b 100644 --- a/sgx_tstd/src/ffi/c_str.rs +++ b/sgx_tstd/src/ffi/c_str.rs @@ -30,7 +30,7 @@ impl Error for NulError { impl From for io::Error { /// Converts a [`NulError`] into a [`io::Error`]. fn from(_: NulError) -> io::Error { - io::Error::new_const(io::ErrorKind::InvalidInput, &"data provided contains a nul byte") + io::const_io_error!(io::ErrorKind::InvalidInput, "data provided contains a nul byte") } } diff --git a/sgx_tstd/src/ffi/mod.rs b/sgx_tstd/src/ffi/mod.rs index b93c5f4bd..1c6152afd 100644 --- a/sgx_tstd/src/ffi/mod.rs +++ b/sgx_tstd/src/ffi/mod.rs @@ -98,9 +98,9 @@ //! [`OsStr`] and Rust strings work similarly to those for [`CString`] //! and [`CStr`]. //! -//! * [`OsString`] represents an owned string in whatever -//! representation the operating system prefers. In the Rust standard -//! library, various APIs that transfer strings to/from the operating +//! * [`OsString`] losslessly represents an owned platform string. However, this +//! representation is not necessarily in a form native to the platform. +//! In the Rust standard library, various APIs that transfer strings to/from the operating //! system use [`OsString`] instead of plain strings. For example, //! [`env::var_os()`] is used to query environment variables; it //! returns an [Option]<[OsString]>. If the environment variable @@ -109,9 +109,9 @@ //! your code can detect errors in case the environment variable did //! not in fact contain valid Unicode data. //! -//! * [`OsStr`] represents a borrowed reference to a string in a -//! format that can be passed to the operating system. It can be -//! converted into a UTF-8 Rust string slice in a similar way to +//! * [`OsStr`] losslessly represents a borrowed reference to a platform string. +//! However, this representation is not necessarily in a form native to the platform. +//! It can be converted into a UTF-8 Rust string slice in a similar way to //! [`OsString`]. //! //! # Conversions @@ -130,16 +130,19 @@ //! //! ## On Windows //! +//! An [`OsStr`] can be losslessly converted to a native Windows string. And +//! a native Windows string can be losslessly converted to an [`OsString`]. +//! //! On Windows, [`OsStr`] implements the //! std::os::windows::ffi::[OsStrExt][windows.OsStrExt] trait, //! which provides an [`encode_wide`] method. This provides an -//! iterator that can be [`collect`]ed into a vector of [`u16`]. +//! iterator that can be [`collect`]ed into a vector of [`u16`]. After a nul +//! characters is appended, this is the same as a native Windows string. //! //! Additionally, on Windows [`OsString`] implements the //! std::os::windows:ffi::[OsStringExt][windows.OsStringExt] -//! trait, which provides a [`from_wide`] method. The result of this -//! method is an [`OsString`] which can be round-tripped to a Windows -//! string losslessly. +//! trait, which provides a [`from_wide`] method to convert a native Windows +//! string (without the terminating nul character) to an [`OsString`]. //! //! [Unicode scalar value]: https://www.unicode.org/glossary/#unicode_scalar_value //! [Unicode code point]: https://www.unicode.org/glossary/#code_point diff --git a/sgx_tstd/src/ffi/os_str.rs b/sgx_tstd/src/ffi/os_str.rs index e11c6aa50..8dc3d034e 100644 --- a/sgx_tstd/src/ffi/os_str.rs +++ b/sgx_tstd/src/ffi/os_str.rs @@ -19,6 +19,7 @@ use crate::borrow::{Borrow, Cow}; use crate::cmp; +use crate::collections::TryReserveError; use crate::fmt; use crate::hash::{Hash, Hasher}; use crate::iter::{Extend, FromIterator}; @@ -269,6 +270,42 @@ impl OsString { self.inner.reserve(additional) } + /// Tries to reserve capacity for at least `additional` more length units + /// in the given `OsString`. The string may reserve more space to 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. + /// + /// # Errors + /// + /// If the capacity overflows, or the allocator reports a failure, then an error + /// is returned. + /// + /// # Examples + /// + /// ``` + /// #![feature(try_reserve_2)] + /// use std::ffi::{OsStr, OsString}; + /// use std::collections::TryReserveError; + /// + /// fn process_data(data: &str) -> Result { + /// let mut s = OsString::new(); + /// + /// // Pre-reserve the memory, exiting if we can't + /// s.try_reserve(OsStr::new(data).len())?; + /// + /// // Now we know this can't OOM in the middle of our complex work + /// s.push(data); + /// + /// Ok(s) + /// } + /// # process_data("123").expect("why is the test harness OOMing on 3 bytes?"); + /// ``` + #[inline] + pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { + self.inner.try_reserve(additional) + } + /// Reserves the minimum capacity for exactly `additional` more capacity to /// be inserted in the given `OsString`. Does nothing if the capacity is /// already sufficient. @@ -293,6 +330,48 @@ impl OsString { self.inner.reserve_exact(additional) } + /// Tries to reserve the minimum capacity for exactly `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(())`. + /// Does nothing if the capacity is already sufficient. + /// + /// Note that the allocator may give the `OsString` more space than it + /// requests. Therefore, capacity can not be relied upon to be precisely + /// minimal. Prefer [`try_reserve`] if future insertions are expected. + /// + /// [`try_reserve`]: OsString::try_reserve + /// + /// # Errors + /// + /// If the capacity overflows, or the allocator reports a failure, then an error + /// is returned. + /// + /// # Examples + /// + /// ``` + /// #![feature(try_reserve_2)] + /// use std::ffi::{OsStr, OsString}; + /// use std::collections::TryReserveError; + /// + /// fn process_data(data: &str) -> Result { + /// let mut s = OsString::new(); + /// + /// // Pre-reserve the memory, exiting if we can't + /// s.try_reserve_exact(OsStr::new(data).len())?; + /// + /// // Now we know this can't OOM in the middle of our complex work + /// s.push(data); + /// + /// Ok(s) + /// } + /// # process_data("123").expect("why is the test harness OOMing on 3 bytes?"); + /// ``` + #[inline] + pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> { + self.inner.try_reserve_exact(additional) + } + /// Shrinks the capacity of the `OsString` to match its length. /// /// # Examples @@ -369,6 +448,8 @@ impl From for OsString { } impl> From<&T> for OsString { + /// Copies any value implementing [AsRef]<[OsStr]> + /// into a newly allocated [`OsString`]. fn from(s: &T) -> OsString { s.as_ref().to_os_string() } @@ -828,6 +909,7 @@ impl OsStr { } impl From<&OsStr> for Box { + /// Copies the string into a newly allocated [Box]<[OsStr]>. #[inline] fn from(s: &OsStr) -> Box { let rw = Box::into_raw(s.inner.into_box()) as *mut OsStr; @@ -836,6 +918,8 @@ impl From<&OsStr> for Box { } impl From> for Box { + /// Converts a `Cow<'a, OsStr>` into a [Box]<[OsStr]>, + /// by copying the contents if they are borrowed. #[inline] fn from(cow: Cow<'_, OsStr>) -> Box { match cow { @@ -870,7 +954,8 @@ impl Clone for Box { } impl From for Arc { - /// Converts an [`OsString`] into an [Arc]<[OsStr]> without copying or allocating. + /// Converts an [`OsString`] into an [Arc]<[OsStr]> by moving the [`OsString`] + /// data into a new [`Arc`] buffer. #[inline] fn from(s: OsString) -> Arc { let arc = s.inner.into_arc(); @@ -879,6 +964,7 @@ impl From for Arc { } impl From<&OsStr> for Arc { + /// Copies the string into a newly allocated [Arc]<[OsStr]>. #[inline] fn from(s: &OsStr) -> Arc { let arc = s.inner.into_arc(); @@ -887,7 +973,8 @@ impl From<&OsStr> for Arc { } impl From for Rc { - /// Converts an [`OsString`] into an [Rc]<[OsStr]> without copying or allocating. + /// Converts an [`OsString`] into an [Rc]<[OsStr]> by moving the [`OsString`] + /// data into a new [`Rc`] buffer. #[inline] fn from(s: OsString) -> Rc { let rc = s.inner.into_rc(); @@ -896,6 +983,7 @@ impl From for Rc { } impl From<&OsStr> for Rc { + /// Copies the string into a newly allocated [Rc]<[OsStr]>. #[inline] fn from(s: &OsStr) -> Rc { let rc = s.inner.into_rc(); @@ -904,6 +992,7 @@ impl From<&OsStr> for Rc { } impl<'a> From for Cow<'a, OsStr> { + /// Moves the string into a [`Cow::Owned`]. #[inline] fn from(s: OsString) -> Cow<'a, OsStr> { Cow::Owned(s) @@ -911,6 +1000,7 @@ impl<'a> From for Cow<'a, OsStr> { } impl<'a> From<&'a OsStr> for Cow<'a, OsStr> { + /// Converts the string reference into a [`Cow::Borrowed`]. #[inline] fn from(s: &'a OsStr) -> Cow<'a, OsStr> { Cow::Borrowed(s) @@ -918,6 +1008,7 @@ impl<'a> From<&'a OsStr> for Cow<'a, OsStr> { } impl<'a> From<&'a OsString> for Cow<'a, OsStr> { + /// Converts the string reference into a [`Cow::Borrowed`]. #[inline] fn from(s: &'a OsString) -> Cow<'a, OsStr> { Cow::Borrowed(s.as_os_str()) @@ -925,6 +1016,8 @@ impl<'a> From<&'a OsString> for Cow<'a, OsStr> { } impl<'a> From> for OsString { + /// Converts a `Cow<'a, OsStr>` into an [`OsString`], + /// by copying the contents if they are borrowed. #[inline] fn from(s: Cow<'a, OsStr>) -> Self { s.into_owned() diff --git a/sgx_tstd/src/fs.rs b/sgx_tstd/src/fs.rs index 1f467fcf2..cbac797c5 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, Initializer, IoSlice, IoSliceMut, Read, Seek, SeekFrom, Write}; +use crate::io::{self, IoSlice, IoSliceMut, Read, ReadBuf, Seek, SeekFrom, Write}; use crate::path::{Path, PathBuf}; use crate::sys::fs as fs_imp; use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner}; @@ -96,6 +96,7 @@ use crate::untrusted::path::PathEx; /// /// [`BufReader`]: io::BufReader /// [`sync_all`]: File::sync_all +#[cfg_attr(not(test), rustc_diagnostic_item = "File")] pub struct File { inner: fs_imp::File, } @@ -351,9 +352,10 @@ impl File { /// open or create a file with specific options if `open()` or `create()` /// are not appropriate. /// - /// It is equivalent to `OpenOptions::new()` but allows you to write more - /// readable code. Instead of `OpenOptions::new().read(true).open("foo.txt")` - /// you can write `File::with_options().read(true).open("foo.txt")`. This + /// It is equivalent to `OpenOptions::new()`, but allows you to write more + /// readable code. Instead of + /// `OpenOptions::new().append(true).open("example.log")`, + /// you can write `File::options().append(true).open("example.log")`. This /// also avoids the need to import `OpenOptions`. /// /// See the [`OpenOptions::new`] function for more details. @@ -361,16 +363,15 @@ impl File { /// # Examples /// /// ```no_run - /// #![feature(with_options)] /// use std::fs::File; /// /// fn main() -> std::io::Result<()> { - /// let mut f = File::with_options().read(true).open("foo.txt")?; + /// let mut f = File::options().append(true).open("example.log")?; /// Ok(()) /// } /// ``` #[must_use] - pub fn with_options() -> OpenOptions { + pub fn options() -> OpenOptions { OpenOptions::new() } @@ -610,15 +611,13 @@ impl Read for File { self.inner.read_vectored(bufs) } - #[inline] - fn is_read_vectored(&self) -> bool { - self.inner.is_read_vectored() + fn read_buf(&mut self, buf: &mut ReadBuf<'_>) -> io::Result<()> { + self.inner.read_buf(buf) } #[inline] - unsafe fn initializer(&self) -> Initializer { - // SAFETY: Read is guaranteed to work on uninitialized memory - unsafe { Initializer::nop() } + fn is_read_vectored(&self) -> bool { + self.inner.is_read_vectored() } // Reserves space in the buffer based on the file size when available. @@ -663,6 +662,10 @@ 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_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result { self.inner.read_vectored(bufs) } @@ -672,12 +675,6 @@ impl Read for &File { self.inner.is_read_vectored() } - #[inline] - unsafe fn initializer(&self) -> Initializer { - // SAFETY: Read is guaranteed to work on uninitialized memory - unsafe { Initializer::nop() } - } - // Reserves space in the buffer based on the file size when available. fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { buf.reserve(buffer_capacity_required(self)); @@ -1021,14 +1018,13 @@ impl Metadata { /// #[cfg_attr(unix, doc = "```no_run")] #[cfg_attr(not(unix), doc = "```ignore")] - /// #![feature(is_symlink)] /// use std::fs; /// use std::path::Path; /// use std::os::unix::fs::symlink; /// /// fn main() -> std::io::Result<()> { /// let link_path = Path::new("link"); - /// symlink("/origin_does_not_exists/", link_path)?; + /// symlink("/origin_does_not_exist/", link_path)?; /// /// let metadata = fs::symlink_metadata(link_path)?; /// @@ -1985,13 +1981,17 @@ pub fn remove_dir>(path: P) -> io::Result<()> { /// /// # Platform-specific behavior /// -/// This function currently corresponds to `opendir`, `lstat`, `rm` and `rmdir` functions on Unix -/// and the `FindFirstFile`, `GetFileAttributesEx`, `DeleteFile`, and `RemoveDirectory` functions -/// on Windows. -/// Note that, this [may change in the future][changes]. +/// This function currently corresponds to `openat`, `fdopendir`, `unlinkat` and `lstat` functions +/// on Unix (except for macOS before version 10.10 and REDOX) and the `CreateFileW`, +/// `GetFileInformationByHandleEx`, `SetFileInformationByHandle`, and `NtCreateFile` functions on +/// Windows. Note that, this [may change in the future][changes]. /// /// [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. +/// /// # Errors /// /// See [`fs::remove_file`] and [`fs::remove_dir`]. @@ -2009,7 +2009,6 @@ pub fn remove_dir>(path: P) -> io::Result<()> { /// Ok(()) /// } /// ``` -#[doc(alias = "delete")] pub fn remove_dir_all>(path: P) -> io::Result<()> { fs_imp::remove_dir_all(path.as_ref()) } @@ -2197,9 +2196,9 @@ impl DirBuilder { match path.parent() { Some(p) => self.create_dir_all(p)?, None => { - return Err(io::Error::new_const( + return Err(io::const_io_error!( io::ErrorKind::Uncategorized, - &"failed to create whole tree", + "failed to create whole tree", )); } } @@ -2222,7 +2221,7 @@ impl AsInnerMut for DirBuilder { /// This function will traverse symbolic links to query information about the /// destination file. In case of broken symbolic links this will return `Ok(false)`. /// -/// As opposed to the `exists()` method, this one doesn't silently ignore errors +/// As opposed to the [`Path::exists`] method, this one doesn't silently ignore errors /// unrelated to the path not existing. (E.g. it will return `Err(_)` in case of permission /// denied on some of the parent directories.) /// @@ -2235,6 +2234,8 @@ impl AsInnerMut for DirBuilder { /// assert!(!fs::try_exists("does_not_exist.txt").expect("Can't check existence of file does_not_exist.txt")); /// assert!(fs::try_exists("/root/secret_file.txt").is_err()); /// ``` +/// +/// [`Path::exists`]: crate::path::Path::exists // FIXME: stabilization should modify documentation of `exists()` to recommend this method // instead. #[inline] diff --git a/sgx_tstd/src/io/buffered/bufreader.rs b/sgx_tstd/src/io/buffered/bufreader.rs index 1f0e5fb5a..cd0795fb2 100644 --- a/sgx_tstd/src/io/buffered/bufreader.rs +++ b/sgx_tstd/src/io/buffered/bufreader.rs @@ -18,8 +18,9 @@ use crate::cmp; use crate::fmt; use crate::io::{ - self, BufRead, Initializer, IoSliceMut, Read, Seek, SeekFrom, SizeHint, DEFAULT_BUF_SIZE, + self, BufRead, IoSliceMut, Read, ReadBuf, Seek, SeekFrom, SizeHint, DEFAULT_BUF_SIZE, }; +use crate::mem::MaybeUninit; /// The `BufReader` struct adds buffering to any reader. /// @@ -63,9 +64,10 @@ use crate::io::{ /// ``` pub struct BufReader { inner: R, - buf: Box<[u8]>, + buf: Box<[MaybeUninit]>, pos: usize, cap: usize, + init: usize, } impl BufReader { @@ -105,11 +107,8 @@ impl BufReader { /// } /// ``` pub fn with_capacity(capacity: usize, inner: R) -> BufReader { - unsafe { - let mut buf = Box::new_uninit_slice(capacity).assume_init(); - inner.initializer().initialize(&mut buf); - BufReader { inner, buf, pos: 0, cap: 0 } - } + let buf = Box::new_uninit_slice(capacity); + BufReader { inner, buf, pos: 0, cap: 0, init: 0 } } } @@ -182,7 +181,8 @@ impl BufReader { /// } /// ``` pub fn buffer(&self) -> &[u8] { - &self.buf[self.pos..self.cap] + // 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]) } } /// Returns the number of bytes the internal buffer can hold at once. @@ -243,6 +243,7 @@ impl BufReader { /// 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)] pub fn seek_relative(&mut self, offset: i64) -> io::Result<()> { let pos = self.pos as u64; if offset < 0 { @@ -278,6 +279,25 @@ impl Read for BufReader { Ok(nread) } + fn read_buf(&mut self, buf: &mut ReadBuf<'_>) -> 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() { + self.discard_buffer(); + return self.inner.read_buf(buf); + } + + let prev = buf.filled_len(); + + let mut rem = self.fill_buf()?; + rem.read_buf(buf)?; + + self.consume(buf.filled_len() - prev); //slice impl of read_buf known to never unfill buf + + Ok(()) + } + // Small read_exacts from a BufReader are extremely common when used with a deserializer. // The default implementation calls read in a loop, which results in surprisingly poor code // generation for the common path where the buffer has enough bytes to fill the passed-in @@ -310,16 +330,11 @@ impl Read for BufReader { self.inner.is_read_vectored() } - // we can't skip unconditionally because of the large buffer case in read. - unsafe fn initializer(&self) -> Initializer { - self.inner.initializer() - } - // 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) -> io::Result { let nread = self.cap - self.pos; - buf.extend_from_slice(&self.buf[self.pos..self.cap]); + buf.extend_from_slice(self.buffer()); self.discard_buffer(); Ok(nread + self.inner.read_to_end(buf)?) } @@ -350,9 +365,9 @@ impl Read for BufReader { let mut bytes = Vec::new(); self.read_to_end(&mut bytes)?; let string = crate::str::from_utf8(&bytes).map_err(|_| { - io::Error::new_const( + io::const_io_error!( io::ErrorKind::InvalidData, - &"stream did not contain valid UTF-8", + "stream did not contain valid UTF-8", ) })?; *buf += string; @@ -369,10 +384,23 @@ impl BufRead for BufReader { // to tell the compiler that the pos..cap slice is always valid. if self.pos >= self.cap { debug_assert!(self.pos == self.cap); - self.cap = self.inner.read(&mut self.buf)?; + + 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.buf[self.pos..self.cap]) + Ok(self.buffer()) } fn consume(&mut self, amt: usize) { diff --git a/sgx_tstd/src/io/buffered/bufwriter.rs b/sgx_tstd/src/io/buffered/bufwriter.rs index c9805f8b2..3897735ea 100644 --- a/sgx_tstd/src/io/buffered/bufwriter.rs +++ b/sgx_tstd/src/io/buffered/bufwriter.rs @@ -18,7 +18,7 @@ use crate::error; use crate::fmt; use crate::io::{ - self, Error, ErrorKind, IntoInnerError, IoSlice, Seek, SeekFrom, Write, DEFAULT_BUF_SIZE, + self, ErrorKind, IntoInnerError, IoSlice, Seek, SeekFrom, Write, DEFAULT_BUF_SIZE, }; use crate::mem; use crate::ptr; @@ -182,9 +182,9 @@ impl BufWriter { match r { Ok(0) => { - return Err(Error::new_const( + return Err(io::const_io_error!( ErrorKind::WriteZero, - &"failed to write the buffered data", + "failed to write the buffered data", )); } Ok(n) => guard.consume(n), diff --git a/sgx_tstd/src/io/buffered/mod.rs b/sgx_tstd/src/io/buffered/mod.rs index c01cb1c6d..f854b5309 100644 --- a/sgx_tstd/src/io/buffered/mod.rs +++ b/sgx_tstd/src/io/buffered/mod.rs @@ -26,12 +26,11 @@ use crate::error; use crate::fmt; use crate::io::Error; -pub use bufreader::BufReader; -pub use bufwriter::BufWriter; -pub use bufwriter::WriterPanicked; -pub use linewriter::LineWriter; +pub use self::{bufreader::BufReader, bufwriter::BufWriter, linewriter::LineWriter}; use linewritershim::LineWriterShim; +pub use bufwriter::WriterPanicked; + /// An error returned by [`BufWriter::into_inner`] which combines an error that /// happened while writing out the buffer, and the buffered writer object /// which may be used to recover from the condition. diff --git a/sgx_tstd/src/io/copy.rs b/sgx_tstd/src/io/copy.rs index f3f0a93a9..b5aa5f43e 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, Result, Write, DEFAULT_BUF_SIZE}; +use super::{BufWriter, ErrorKind, Read, ReadBuf, Result, Write, DEFAULT_BUF_SIZE}; use crate::mem::MaybeUninit; /// Copies the entire contents of a reader into a writer. @@ -57,6 +57,16 @@ use crate::mem::MaybeUninit; /// } /// ``` pub fn copy(reader: &mut R, writer: &mut W) -> Result +where + R: Read, + W: Write, +{ + generic_copy(reader, writer) +} + +/// The userspace read-write-loop implementation of `io::copy` that is used when +/// OS-specific specializations for copy offloading are not available or not applicable. +pub(crate) fn generic_copy(reader: &mut R, writer: &mut W) -> Result where R: Read, W: Write, @@ -82,33 +92,30 @@ impl BufferedCopySpec for BufWriter { return stack_buffer_copy(reader, writer); } - // FIXME: #42788 - // - // - This creates a (mut) reference to a slice of - // _uninitialized_ integers, which is **undefined behavior** - // - // - Only the standard library gets to soundly "ignore" this, - // based on its privileged knowledge of unstable rustc - // internals; - unsafe { - let spare_cap = writer.buffer_mut().spare_capacity_mut(); - reader.initializer().initialize(MaybeUninit::slice_assume_init_mut(spare_cap)); - } - let mut len = 0; + let mut init = 0; loop { let buf = writer.buffer_mut(); - let spare_cap = buf.spare_capacity_mut(); - - if spare_cap.len() >= DEFAULT_BUF_SIZE { - match reader.read(unsafe { MaybeUninit::slice_assume_init_mut(spare_cap) }) { - Ok(0) => return Ok(len), // EOF reached - Ok(bytes_read) => { - assert!(bytes_read <= spare_cap.len()); - // SAFETY: The initializer contract guarantees that either it or `read` - // will have initialized these bytes. And we just checked that the number - // of bytes is within the buffer capacity. + let mut read_buf = ReadBuf::uninit(buf.spare_capacity_mut()); + + // SAFETY: init is either 0 or the initialized_len of the previous iteration + unsafe { + read_buf.assume_init(init); + } + + if read_buf.capacity() >= DEFAULT_BUF_SIZE { + match reader.read_buf(&mut read_buf) { + Ok(()) => { + let bytes_read = read_buf.filled_len(); + + if bytes_read == 0 { + return Ok(len); + } + + init = read_buf.initialized_len() - bytes_read; + + // SAFETY: ReadBuf 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 @@ -129,28 +136,26 @@ fn stack_buffer_copy( reader: &mut R, writer: &mut W, ) -> Result { - let mut buf = MaybeUninit::<[u8; DEFAULT_BUF_SIZE]>::uninit(); - // FIXME: #42788 - // - // - This creates a (mut) reference to a slice of - // _uninitialized_ integers, which is **undefined behavior** - // - // - Only the standard library gets to soundly "ignore" this, - // based on its privileged knowledge of unstable rustc - // internals; - unsafe { - reader.initializer().initialize(buf.assume_init_mut()); - } + let mut buf = [MaybeUninit::uninit(); DEFAULT_BUF_SIZE]; + let mut buf = ReadBuf::uninit(&mut buf); + + let mut len = 0; - let mut written = 0; loop { - let len = match reader.read(unsafe { buf.assume_init_mut() }) { - Ok(0) => return Ok(written), - Ok(len) => len, - Err(ref e) if e.kind() == ErrorKind::Interrupted => continue, + match reader.read_buf(&mut buf) { + Ok(()) => {} + Err(e) if e.kind() == ErrorKind::Interrupted => continue, Err(e) => return Err(e), }; - writer.write_all(unsafe { &buf.assume_init_ref()[..len] })?; - written += len as u64; + + if buf.filled().is_empty() { + break; + } + + len += buf.filled().len() as u64; + writer.write_all(buf.filled())?; + buf.clear(); } + + Ok(len) } diff --git a/sgx_tstd/src/io/cursor.rs b/sgx_tstd/src/io/cursor.rs index 01ef7bbf1..be40a3217 100644 --- a/sgx_tstd/src/io/cursor.rs +++ b/sgx_tstd/src/io/cursor.rs @@ -18,7 +18,7 @@ use crate::io::prelude::*; use crate::cmp; -use crate::io::{self, Error, ErrorKind, Initializer, IoSlice, IoSliceMut, SeekFrom}; +use crate::io::{self, ErrorKind, IoSlice, IoSliceMut, ReadBuf, SeekFrom}; use core::convert::TryInto; @@ -297,9 +297,9 @@ where self.pos = n; Ok(self.pos) } - None => Err(Error::new_const( + None => Err(io::const_io_error!( ErrorKind::InvalidInput, - &"invalid seek to a negative or overflowing position", + "invalid seek to a negative or overflowing position", )), } } @@ -323,6 +323,16 @@ where Ok(n) } + fn read_buf(&mut self, buf: &mut ReadBuf<'_>) -> io::Result<()> { + let prev_filled = buf.filled_len(); + + Read::read_buf(&mut self.fill_buf()?, buf)?; + + self.pos += (buf.filled_len() - prev_filled) as u64; + + Ok(()) + } + fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result { let mut nread = 0; for buf in bufs { @@ -345,11 +355,6 @@ where self.pos += n as u64; Ok(()) } - - #[inline] - unsafe fn initializer(&self) -> Initializer { - Initializer::nop() - } } impl BufRead for Cursor @@ -393,9 +398,9 @@ fn slice_write_vectored( // Resizing write implementation fn vec_write(pos_mut: &mut u64, vec: &mut Vec, buf: &[u8]) -> io::Result { let pos: usize = (*pos_mut).try_into().map_err(|_| { - Error::new_const( + io::const_io_error!( ErrorKind::InvalidInput, - &"cursor position exceeds maximum possible vector length", + "cursor position exceeds maximum possible vector length", ) })?; // Make sure the internal buffer is as least as big as where we diff --git a/sgx_tstd/src/io/error.rs b/sgx_tstd/src/io/error.rs index 11b7c0b4a..6de63fbb4 100644 --- a/sgx_tstd/src/io/error.rs +++ b/sgx_tstd/src/io/error.rs @@ -15,6 +15,9 @@ // specific language governing permissions and limitations // under the License.. +mod repr_unpacked; +use repr_unpacked::Repr; + use crate::convert::From; use crate::error; use crate::fmt; @@ -79,16 +82,59 @@ impl fmt::Debug for Error { } } -enum Repr { +// Only derive debug in tests, to make sure it +// doesn't accidentally get printed. +#[cfg_attr(feature = "unit_test", derive(Debug))] +enum ErrorData { Os(i32), Simple(ErrorKind), - // &str is a fat pointer, but &&str is a thin pointer. - SimpleMessage(ErrorKind, &'static &'static str), - Custom(Box), + SimpleMessage(&'static SimpleMessage), + Custom(C), SgxStatus(sgx_status_t), } +// `#[repr(align(4))]` is probably redundant, it should have that value or +// higher already. We include it just because repr_bitpacked.rs's encoding +// requires an alignment >= 4 (note that `#[repr(align)]` will not reduce the +// alignment required by the struct, only increase it). +// +// If we add more variants to ErrorData, this can be increased to 8, but it +// should probably be behind `#[cfg_attr(target_pointer_width = "64", ...)]` or +// whatever cfg we're using to enable the `repr_bitpacked` code, since only the +// that version needs the alignment, and 8 is higher than the alignment we'll +// have on 32 bit platforms. +// +// (For the sake of being explicit: the alignment requirement here only matters +// if `error/repr_bitpacked.rs` is in use — for the unpacked repr it doesn't +// matter at all) +#[repr(align(4))] +#[derive(Debug)] +pub(crate) struct SimpleMessage { + kind: ErrorKind, + message: &'static str, +} + +impl SimpleMessage { + pub(crate) const fn new(kind: ErrorKind, message: &'static str) -> Self { + Self { kind, message } + } +} + +/// Create and return an `io::Error` for a given `ErrorKind` and constant +/// message. This doesn't allocate. +pub(crate) macro const_io_error($kind:expr, $message:expr $(,)?) { + $crate::io::error::Error::from_static_message({ + const MESSAGE_DATA: $crate::io::error::SimpleMessage = + $crate::io::error::SimpleMessage::new($kind, $message); + &MESSAGE_DATA + }) +} + +// As with `SimpleMessage`: `#[repr(align(4))]` here is just because +// repr_bitpacked's encoding requires it. In practice it almost certainly be +// already be this high or higher. #[derive(Debug)] +#[repr(align(4))] struct Custom { kind: ErrorKind, error: Box, @@ -223,11 +269,10 @@ pub enum ErrorKind { /// /// The filesystem does not support making so many hardlinks to the same file. TooManyLinks, - /// Filename too long. + /// A filename was invalid. /// - /// The limit might be from the underlying filesystem or API, or an administratively imposed - /// resource limit. - FilenameTooLong, + /// This error can also cause if it exceeded the filename length limit. + InvalidFilename, /// Program argument list too long. /// /// When trying to run an external program, a system or process limit on the size of the @@ -304,12 +349,12 @@ impl ErrorKind { DirectoryNotEmpty => "directory not empty", ExecutableFileBusy => "executable file busy", FileTooLarge => "file too large", - FilenameTooLong => "filename too long", FilesystemLoop => "filesystem loop or indirection limit (e.g. symlink loop)", FilesystemQuotaExceeded => "filesystem quota exceeded", HostUnreachable => "host unreachable", Interrupted => "operation interrupted", InvalidData => "invalid data", + InvalidFilename => "invalid filename", InvalidInput => "invalid input parameter", IsADirectory => "is a directory", NetworkDown => "network down", @@ -332,17 +377,32 @@ impl ErrorKind { Unsupported => "unsupported", WouldBlock => "operation would block", WriteZero => "write zero", - ErrorKind::SgxError => "Sgx error status", + SgxError => "Sgx error status", } } } +impl fmt::Display for ErrorKind { + /// Shows a human-readable description of the `ErrorKind`. + /// + /// This is similar to `impl Display for Error`, but doesn't require first converting to Error. + /// + /// # Examples + /// ``` + /// use std::io::ErrorKind; + /// assert_eq!("entity not found", ErrorKind::NotFound.to_string()); + /// ``` + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt.write_str(self.as_str()) + } +} + /// Intended for use for errors not exposed to the user, where allocating onto /// the heap (for normal construction via Error::new) is too costly. impl From for Error { /// Converts an [`ErrorKind`] into an [`Error`]. /// - /// This conversion allocates a new error with a simple representation of error kind. + /// This conversion creates a new error with a simple representation of error kind. /// /// # Examples /// @@ -355,14 +415,14 @@ impl From for Error { /// ``` #[inline] fn from(kind: ErrorKind) -> Error { - Error { repr: Repr::Simple(kind) } + Error { repr: Repr::new_simple(kind) } } } impl From for Error { #[inline] fn from(status: sgx_status_t) -> Error { - Error { repr: Repr::SgxStatus(status) } + Error { repr: Repr::new_sgx(status) } } } @@ -374,6 +434,9 @@ impl Error { /// originate from the OS itself. The `error` argument is an arbitrary /// payload which will be contained in this [`Error`]. /// + /// If no extra payload is required, use the `From` conversion from + /// `ErrorKind`. + /// /// # Examples /// /// ``` @@ -384,6 +447,9 @@ impl Error { /// /// // errors can also be created from other errors /// let custom_error2 = Error::new(ErrorKind::Interrupted, custom_error); + /// + /// // creating an error without payload + /// let eof_error = Error::from(ErrorKind::UnexpectedEof); /// ``` pub fn new(kind: ErrorKind, error: E) -> Error where @@ -392,21 +458,49 @@ impl Error { Self::_new(kind, error.into()) } + /// Creates a new I/O error from an arbitrary error payload. + /// + /// This function is used to generically create I/O errors which do not + /// originate from the OS itself. It is a shortcut for [`Error::new`] + /// with [`ErrorKind::Other`]. + /// + /// # Examples + /// + /// ``` + /// #![feature(io_error_other)] + /// + /// use std::io::Error; + /// + /// // errors can be created from strings + /// let custom_error = Error::other("oh no!"); + /// + /// // errors can also be created from other errors + /// let custom_error2 = Error::other(custom_error); + /// ``` + pub fn other(error: E) -> Error + where + E: Into>, + { + Self::_new(ErrorKind::Other, error.into()) + } + fn _new(kind: ErrorKind, error: Box) -> Error { - Error { repr: Repr::Custom(Box::new(Custom { kind, error })) } + Error { repr: Repr::new_custom(Box::new(Custom { kind, error })) } } - /// Creates a new I/O error from a known kind of error as well as a - /// constant message. + /// Creates a new I/O error from a known kind of error as well as a constant + /// message. /// /// This function does not allocate. /// - /// This function should maybe change to - /// `new_const(kind: ErrorKind)` - /// in the future, when const generics allow that. + /// You should not use this directly, and instead use the `const_io_error!` + /// macro: `io::const_io_error!(ErrorKind::Something, "some_message")`. + /// + /// This function should maybe change to `from_static_message(kind: ErrorKind)` in the future, when const generics allow that. #[inline] - pub(crate) const fn new_const(kind: ErrorKind, message: &'static &'static str) -> Error { - Self { repr: Repr::SimpleMessage(kind, message) } + pub(crate) const fn from_static_message(msg: &'static SimpleMessage) -> Error { + Self { repr: Repr::new_simple_message(msg) } } /// Returns an error representing the last OS error which occurred. @@ -415,12 +509,18 @@ impl Error { /// `GetLastError` on Windows) and will return a corresponding instance of /// [`Error`] for the error code. /// + /// This should be called immediately after a call to a platform function, + /// otherwise the state of the error value is indeterminate. In particular, + /// other standard library functions may call platform functions that may + /// (or may not) reset the error value even if they succeed. + /// /// # Examples /// /// ``` /// use std::io::Error; /// - /// println!("last OS error: {:?}", Error::last_os_error()); + /// let os_error = Error::last_os_error(); + /// println!("last OS error: {:?}", os_error); /// ``` #[must_use] #[inline] @@ -456,7 +556,7 @@ impl Error { #[must_use] #[inline] pub fn from_raw_os_error(code: i32) -> Error { - Error { repr: Repr::Os(code) } + Error { repr: Repr::new_os(code) } } /// Returns the OS error that this error represents (if any). @@ -491,18 +591,18 @@ impl Error { #[must_use] #[inline] pub fn raw_os_error(&self) -> Option { - match self.repr { - Repr::Os(i) => Some(i), - Repr::Custom(..) => None, - Repr::Simple(..) => None, - Repr::SimpleMessage(..) => None, - Repr::SgxStatus(..) => None, + match self.repr.data() { + ErrorData::Os(i) => Some(i), + ErrorData::Custom(..) => None, + ErrorData::Simple(..) => None, + ErrorData::SimpleMessage(..) => None, + ErrorData::SgxStatus(..) => None, } } /// Creates a new instance of an `Error` from a particular SGX error status. pub fn from_sgx_error(status: sgx_status_t) -> Error { - Error { repr: Repr::SgxStatus(status) } + Error { repr: Repr::new_sgx(status) } } /// Returns the SGX error that this error represents (if any). @@ -511,12 +611,12 @@ impl Error { /// then this function will return `Some`, otherwise /// it will return `None`. pub fn raw_sgx_error(&self) -> Option { - match self.repr { - Repr::Os(..) => None, - Repr::Custom(..) => None, - Repr::Simple(..) => None, - Repr::SimpleMessage(..) => None, - Repr::SgxStatus(status) => Some(status), + match self.repr.data() { + ErrorData::Os(..) => None, + ErrorData::Custom(..) => None, + ErrorData::Simple(..) => None, + ErrorData::SimpleMessage(..) => None, + ErrorData::SgxStatus(status) => Some(status), } } @@ -550,12 +650,12 @@ impl Error { #[must_use] #[inline] pub fn get_ref(&self) -> Option<&(dyn error::Error + Send + Sync + 'static)> { - match self.repr { - Repr::Os(..) => None, - Repr::Simple(..) => None, - Repr::SimpleMessage(..) => None, - Repr::Custom(ref c) => Some(&*c.error), - Repr::SgxStatus(ref s) => Some(s), + match self.repr.data() { + ErrorData::Os(..) => None, + ErrorData::Simple(..) => None, + ErrorData::SimpleMessage(..) => None, + ErrorData::Custom(c) => Some(&*c.error), + ErrorData::SgxStatus(..) => None, } } @@ -624,12 +724,12 @@ impl Error { #[must_use] #[inline] pub fn get_mut(&mut self) -> Option<&mut (dyn error::Error + Send + Sync + 'static)> { - match self.repr { - Repr::Os(..) => None, - Repr::Simple(..) => None, - Repr::SimpleMessage(..) => None, - Repr::Custom(ref mut c) => Some(&mut *c.error), - Repr::SgxStatus(ref mut s) => Some(s), + match self.repr.data_mut() { + ErrorData::Os(..) => None, + ErrorData::Simple(..) => None, + ErrorData::SimpleMessage(..) => None, + ErrorData::Custom(c) => Some(&mut *c.error), + ErrorData::SgxStatus(..) => None, } } @@ -663,12 +763,12 @@ impl Error { #[must_use = "`self` will be dropped if the result is not used"] #[inline] pub fn into_inner(self) -> Option> { - match self.repr { - Repr::Os(..) => None, - Repr::Simple(..) => None, - Repr::SimpleMessage(..) => None, - Repr::Custom(c) => Some(c.error), - Repr::SgxStatus(s) => Some(Box::new(s)), + match self.repr.into_data() { + ErrorData::Os(..) => None, + ErrorData::Simple(..) => None, + ErrorData::SimpleMessage(..) => None, + ErrorData::Custom(c) => Some(c.error), + ErrorData::SgxStatus(s) => Some(Box::new(s)), } } @@ -693,31 +793,33 @@ impl Error { #[must_use] #[inline] pub fn kind(&self) -> ErrorKind { - match self.repr { - Repr::Os(code) => sys::decode_error_kind(code), - Repr::Custom(ref c) => c.kind, - Repr::Simple(kind) => kind, - Repr::SimpleMessage(kind, _) => kind, - Repr::SgxStatus(..) => ErrorKind::SgxError, + match self.repr.data() { + ErrorData::Os(code) => sys::decode_error_kind(code), + ErrorData::Custom(c) => c.kind, + ErrorData::Simple(kind) => kind, + ErrorData::SimpleMessage(m) => m.kind, + ErrorData::SgxStatus(..) => ErrorKind::SgxError, } } } impl fmt::Debug for Repr { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - match *self { - Repr::Os(code) => fmt + match self.data() { + ErrorData::Os(code) => fmt .debug_struct("Os") .field("code", &code) .field("kind", &sys::decode_error_kind(code)) .field("message", &sys::os::error_string(code)) .finish(), - Repr::Custom(ref c) => fmt::Debug::fmt(&c, fmt), - Repr::Simple(kind) => fmt.debug_tuple("Kind").field(&kind).finish(), - Repr::SimpleMessage(kind, &message) => { - fmt.debug_struct("Error").field("kind", &kind).field("message", &message).finish() - } - Repr::SgxStatus(status) => fmt + ErrorData::Custom(c) => fmt::Debug::fmt(&c, fmt), + ErrorData::Simple(kind) => fmt.debug_tuple("Kind").field(&kind).finish(), + ErrorData::SimpleMessage(msg) => fmt + .debug_struct("Error") + .field("kind", &msg.kind) + .field("message", &msg.message) + .finish(), + ErrorData::SgxStatus(status) => fmt .debug_struct("Sgx") .field("code", &status) .field("message", &status.__description()) @@ -728,15 +830,15 @@ impl fmt::Debug for Repr { impl fmt::Display for Error { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.repr { - Repr::Os(code) => { + match self.repr.data() { + ErrorData::Os(code) => { let detail = sys::os::error_string(code); write!(fmt, "{} (os error {})", detail, code) } - Repr::Custom(ref c) => c.error.fmt(fmt), - Repr::Simple(kind) => write!(fmt, "{}", kind.as_str()), - Repr::SimpleMessage(_, &msg) => msg.fmt(fmt), - Repr::SgxStatus(status) => { + ErrorData::Custom(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) } @@ -747,32 +849,32 @@ impl fmt::Display for Error { impl error::Error for Error { #[allow(deprecated, deprecated_in_future)] fn description(&self) -> &str { - match self.repr { - Repr::Os(..) | Repr::Simple(..) => self.kind().as_str(), - Repr::SimpleMessage(_, &msg) => msg, - Repr::Custom(ref c) => c.error.description(), - Repr::SgxStatus(ref s) => s.description(), + match self.repr.data() { + ErrorData::Os(..) | ErrorData::Simple(..) => self.kind().as_str(), + ErrorData::SimpleMessage(msg) => msg.message, + ErrorData::Custom(c) => c.error.description(), + ErrorData::SgxStatus(ref s) => s.__description(), } } #[allow(deprecated)] fn cause(&self) -> Option<&dyn error::Error> { - match self.repr { - Repr::Os(..) => None, - Repr::Simple(..) => None, - Repr::SimpleMessage(..) => None, - Repr::Custom(ref c) => c.error.cause(), - Repr::SgxStatus(ref s) => Some(s), + match self.repr.data() { + ErrorData::Os(..) => None, + ErrorData::Simple(..) => None, + ErrorData::SimpleMessage(..) => None, + ErrorData::Custom(c) => c.error.cause(), + ErrorData::SgxStatus(..) => None, } } fn source(&self) -> Option<&(dyn error::Error + 'static)> { - match self.repr { - Repr::Os(..) => None, - Repr::Simple(..) => None, - Repr::SimpleMessage(..) => None, - Repr::Custom(ref c) => c.error.source(), - Repr::SgxStatus(ref s) => Some(s), + match self.repr.data() { + ErrorData::Os(..) => None, + ErrorData::Simple(..) => None, + ErrorData::SimpleMessage(..) => None, + ErrorData::Custom(c) => c.error.source(), + ErrorData::SgxStatus(..) => None, } } } diff --git a/sgx_tstd/src/io/error/repr_unpacked.rs b/sgx_tstd/src/io/error/repr_unpacked.rs new file mode 100644 index 000000000..f1713077d --- /dev/null +++ b/sgx_tstd/src/io/error/repr_unpacked.rs @@ -0,0 +1,58 @@ +//! This is a fairly simple unpacked error representation that's used on +//! non-64bit targets, where the packed 64 bit representation wouldn't work, and +//! would have no benefit. + +use super::{Custom, ErrorData, ErrorKind, SimpleMessage}; +use alloc_crate::boxed::Box; + +use sgx_types::sgx_status_t; + +type Inner = ErrorData>; + +pub(super) struct Repr(Inner); + +impl Repr { + pub(super) fn new_custom(b: Box) -> Self { + Self(Inner::Custom(b)) + } + #[inline] + pub(super) fn new_os(code: i32) -> Self { + Self(Inner::Os(code)) + } + #[inline] + pub(super) fn new_simple(kind: ErrorKind) -> Self { + Self(Inner::Simple(kind)) + } + #[inline] + pub(super) const fn new_simple_message(m: &'static SimpleMessage) -> Self { + Self(Inner::SimpleMessage(m)) + } + #[inline] + pub(super) const fn new_sgx(status: sgx_status_t) -> Self { + Self(Inner::SgxStatus(status)) + } + #[inline] + pub(super) fn into_data(self) -> ErrorData> { + self.0 + } + #[inline] + pub(super) fn data(&self) -> ErrorData<&Custom> { + match &self.0 { + 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::SgxStatus(s) => ErrorData::SgxStatus(*s), + } + } + #[inline] + pub(super) fn data_mut(&mut self) -> ErrorData<&mut Custom> { + match &mut self.0 { + Inner::Os(c) => ErrorData::Os(*c), + Inner::Simple(k) => ErrorData::Simple(*k), + Inner::SimpleMessage(m) => ErrorData::SimpleMessage(*m), + Inner::Custom(m) => ErrorData::Custom(&mut *m), + Inner::SgxStatus(s) => ErrorData::SgxStatus(*s), + } + } +} diff --git a/sgx_tstd/src/io/impls.rs b/sgx_tstd/src/io/impls.rs index f30b86841..2a8ebc6d5 100644 --- a/sgx_tstd/src/io/impls.rs +++ b/sgx_tstd/src/io/impls.rs @@ -19,7 +19,7 @@ use crate::alloc::Allocator; use crate::cmp; use crate::fmt; use crate::io::{ - self, BufRead, Error, ErrorKind, Initializer, IoSlice, IoSliceMut, Read, Seek, SeekFrom, Write, + self, BufRead, ErrorKind, IoSlice, IoSliceMut, Read, ReadBuf, Seek, SeekFrom, Write, }; use crate::mem; @@ -32,6 +32,11 @@ impl Read for &mut R { (**self).read(buf) } + #[inline] + fn read_buf(&mut self, buf: &mut ReadBuf<'_>) -> io::Result<()> { + (**self).read_buf(buf) + } + #[inline] fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result { (**self).read_vectored(bufs) @@ -42,11 +47,6 @@ impl Read for &mut R { (**self).is_read_vectored() } - #[inline] - unsafe fn initializer(&self) -> Initializer { - (**self).initializer() - } - #[inline] fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { (**self).read_to_end(buf) @@ -135,6 +135,11 @@ impl Read for Box { (**self).read(buf) } + #[inline] + fn read_buf(&mut self, buf: &mut ReadBuf<'_>) -> io::Result<()> { + (**self).read_buf(buf) + } + #[inline] fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result { (**self).read_vectored(bufs) @@ -145,11 +150,6 @@ impl Read for Box { (**self).is_read_vectored() } - #[inline] - unsafe fn initializer(&self) -> Initializer { - (**self).initializer() - } - #[inline] fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { (**self).read_to_end(buf) @@ -258,6 +258,17 @@ impl Read for &[u8] { Ok(amt) } + #[inline] + fn read_buf(&mut self, buf: &mut ReadBuf<'_>) -> io::Result<()> { + let amt = cmp::min(buf.remaining(), self.len()); + let (a, b) = self.split_at(amt); + + buf.append(a); + + *self = b; + Ok(()) + } + #[inline] fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result { let mut nread = 0; @@ -276,15 +287,13 @@ impl Read for &[u8] { true } - #[inline] - unsafe fn initializer(&self) -> Initializer { - Initializer::nop() - } - #[inline] fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> { if buf.len() > self.len() { - return Err(Error::new_const(ErrorKind::UnexpectedEof, &"failed to fill whole buffer")); + return Err(io::const_io_error!( + ErrorKind::UnexpectedEof, + "failed to fill whole buffer" + )); } let (a, b) = self.split_at(buf.len()); @@ -332,6 +341,7 @@ impl BufRead for &[u8] { /// return short writes: ultimately, `Ok(0)`; in this situation, `write_all` returns an error of /// kind `ErrorKind::WriteZero`. impl Write for &mut [u8] { + #[allow(clippy::mem_replace_with_default)] #[inline] fn write(&mut self, data: &[u8]) -> io::Result { let amt = cmp::min(data.len(), self.len()); @@ -364,7 +374,7 @@ impl Write for &mut [u8] { if self.write(data)? == data.len() { Ok(()) } else { - Err(Error::new_const(ErrorKind::WriteZero, &"failed to write whole buffer")) + Err(io::const_io_error!(ErrorKind::WriteZero, "failed to write whole buffer")) } } diff --git a/sgx_tstd/src/io/mod.rs b/sgx_tstd/src/io/mod.rs index 8ca7acf15..2497f3dbd 100644 --- a/sgx_tstd/src/io/mod.rs +++ b/sgx_tstd/src/io/mod.rs @@ -268,25 +268,30 @@ use crate::convert::TryInto; use crate::fmt; use crate::mem::replace; use crate::ops::{Deref, DerefMut}; -use crate::ptr; use crate::slice; use crate::str; use crate::sys; use crate::sys_common::memchr; -pub use self::buffered::IntoInnerError; + pub use self::buffered::WriterPanicked; -pub use self::buffered::{BufReader, BufWriter, LineWriter}; -pub use self::copy::copy; -pub use self::cursor::Cursor; -pub use self::error::{Error, ErrorKind, Result}; + #[cfg(feature = "stdio")] -pub use self::stdio::{stderr, stdin, stdout, Stderr, Stdin, Stdout}; +pub use self::stdio::{_eprint, _print}; #[cfg(feature = "stdio")] -pub use self::stdio::{StderrLock, StdinLock, StdoutLock}; +pub use self::stdio::{stderr_locked, stdin_locked, stdout_locked}; #[cfg(feature = "stdio")] -pub use self::stdio::{_eprint, _print}; -pub use self::util::{empty, repeat, sink, Empty, Repeat, Sink}; +pub use self::stdio::{stderr, stdin, stdout, Stderr, StderrLock, Stdin, StdinLock, Stdout, StdoutLock}; +pub use self::{ + buffered::{BufReader, BufWriter, IntoInnerError, LineWriter}, + copy::copy, + cursor::Cursor, + error::{Error, ErrorKind, Result}, + util::{empty, repeat, sink, Empty, Repeat, Sink}, +}; + +pub use self::readbuf::ReadBuf; +pub(crate) use error::const_io_error; mod buffered; pub(crate) mod copy; @@ -294,12 +299,14 @@ mod cursor; mod error; mod impls; pub mod prelude; +mod readbuf; #[cfg(feature = "stdio")] mod stdio; mod util; const DEFAULT_BUF_SIZE: usize = crate::sys_common::io::DEFAULT_BUF_SIZE; +#[cfg(feature = "stdio")] pub(crate) use stdio::cleanup; struct Guard<'a> { @@ -342,7 +349,10 @@ where let ret = f(g.buf); if str::from_utf8(&g.buf[g.len..]).is_err() { ret.and_then(|_| { - Err(Error::new_const(ErrorKind::InvalidData, &"stream did not contain valid UTF-8")) + Err(error::const_io_error!( + ErrorKind::InvalidData, + "stream did not contain valid UTF-8" + )) }) } else { g.len = g.buf.len(); @@ -356,52 +366,43 @@ where // of data to return. Simply tacking on an extra DEFAULT_BUF_SIZE space every // time is 4,500 times (!) slower than a default reservation size of 32 if the // reader has a very small amount of data to return. -// -// Because we're extending the buffer with uninitialized data for trusted -// readers, we need to make sure to truncate that if any of this panics. pub(crate) fn default_read_to_end(r: &mut R, buf: &mut Vec) -> Result { let start_len = buf.len(); let start_cap = buf.capacity(); - let mut g = Guard { len: buf.len(), buf }; + + let mut initialized = 0; // Extra initialized bytes from previous loop iteration loop { - // If we've read all the way up to the capacity, reserve more space. - if g.len == g.buf.capacity() { - g.buf.reserve(32); + if buf.len() == buf.capacity() { + buf.reserve(32); // buf is full, need more space } - // Initialize any excess capacity and adjust the length so we can write - // to it. - if g.buf.len() < g.buf.capacity() { - unsafe { - // FIXME(danielhenrymantilla): #42788 - // - // - This creates a (mut) reference to a slice of - // _uninitialized_ integers, which is **undefined behavior** - // - // - Only the standard library gets to soundly "ignore" this, - // based on its privileged knowledge of unstable rustc - // internals; - let capacity = g.buf.capacity(); - g.buf.set_len(capacity); - r.initializer().initialize(&mut g.buf[g.len..]); - } + let mut read_buf = ReadBuf::uninit(buf.spare_capacity_mut()); + + // SAFETY: These bytes were initialized but not filled in the previous loop + unsafe { + read_buf.assume_init(initialized); } - let buf = &mut g.buf[g.len..]; - match r.read(buf) { - Ok(0) => return Ok(g.len - start_len), - Ok(n) => { - // We can't allow bogus values from read. If it is too large, the returned vec could have its length - // set past its capacity, or if it overflows the vec could be shortened which could create an invalid - // string if this is called via read_to_string. - assert!(n <= buf.len()); - g.len += n; - } - Err(ref e) if e.kind() == ErrorKind::Interrupted => continue, + match r.read_buf(&mut read_buf) { + Ok(()) => {} + Err(e) if e.kind() == ErrorKind::Interrupted => continue, Err(e) => return Err(e), } - if g.len == g.buf.capacity() && g.buf.capacity() == start_cap { + if read_buf.filled_len() == 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(); + + // SAFETY: ReadBuf's invariants mean this much memory is init + unsafe { + buf.set_len(new_len); + } + + if buf.len() == buf.capacity() && buf.capacity() == start_cap { // The buffer might be an exact fit. Let's read into a probe buffer // and see if it returns `Ok(0)`. If so, we've avoided an // unnecessary doubling of the capacity. But if not, append the @@ -410,10 +411,9 @@ pub(crate) fn default_read_to_end(r: &mut R, buf: &mut Vec loop { match r.read(&mut probe) { - Ok(0) => return Ok(g.len - start_len), + Ok(0) => return Ok(buf.len() - start_len), Ok(n) => { - g.buf.extend_from_slice(&probe[..n]); - g.len += n; + buf.extend_from_slice(&probe[..n]); break; } Err(ref e) if e.kind() == ErrorKind::Interrupted => continue, @@ -469,12 +469,21 @@ pub(crate) fn default_read_exact(this: &mut R, mut buf: &mut [ } } if !buf.is_empty() { - Err(Error::new_const(ErrorKind::UnexpectedEof, &"failed to fill whole buffer")) + Err(error::const_io_error!(ErrorKind::UnexpectedEof, "failed to fill whole buffer")) } else { Ok(()) } } +pub(crate) fn default_read_buf(read: F, buf: &mut ReadBuf<'_>) -> Result<()> +where + F: FnOnce(&mut [u8]) -> Result, +{ + let n = read(buf.initialize_unfilled())?; + buf.add_filled(n); + Ok(()) +} + /// The `Read` trait allows for reading bytes from a source. /// /// Implementors of the `Read` trait are called 'readers'. @@ -652,30 +661,6 @@ pub trait Read { false } - /// Determines if this `Read`er can work with buffers of uninitialized - /// memory. - /// - /// The default implementation returns an initializer which will zero - /// buffers. - /// - /// If a `Read`er guarantees that it can work properly with uninitialized - /// memory, it should call [`Initializer::nop()`]. See the documentation for - /// [`Initializer`] for details. - /// - /// The behavior of this method must be independent of the state of the - /// `Read`er - the method only takes `&self` so that it can be used through - /// trait objects. - /// - /// # Safety - /// - /// This method is unsafe because a `Read`er could otherwise return a - /// non-zeroing `Initializer` from another `Read` type without an `unsafe` - /// block. - #[inline] - unsafe fn initializer(&self) -> Initializer { - Initializer::zeroing() - } - /// Read all bytes until EOF in this source, placing them into `buf`. /// /// All bytes read from this source will be appended to the specified buffer @@ -822,7 +807,38 @@ pub trait Read { default_read_exact(self, buf) } - /// Creates a "by reference" adapter for this instance of `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 + /// 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<()> { + default_read_buf(|b| self.read(b), buf) + } + + /// Read the exact number of bytes required to fill `buf`. + /// + /// This is equivalent to the [`read_exact`](Read::read_exact) method, except that it is passed a [`ReadBuf`] 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) { + Ok(()) => {} + Err(e) if e.kind() == ErrorKind::Interrupted => continue, + Err(e) => return Err(e), + } + + if buf.filled().len() == prev_filled { + return Err(Error::new(ErrorKind::UnexpectedEof, "failed to fill buffer")); + } + } + + Ok(()) + } + + /// Creates a "by reference" adaptor for this instance of `Read`. /// /// The returned adapter also implements `Read` and will simply borrow this /// current reader. @@ -1016,13 +1032,13 @@ pub trait Read { /// /// # use std::io; /// fn main() -> io::Result<()> { -/// let stdin = io::read_to_string(&mut io::stdin())?; +/// let stdin = io::read_to_string(io::stdin())?; /// println!("Stdin was:"); /// println!("{}", stdin); /// Ok(()) /// } /// ``` -pub fn read_to_string(reader: &mut R) -> Result { +pub fn read_to_string(mut reader: R) -> Result { let mut buf = String::new(); reader.read_to_string(&mut buf)?; Ok(buf) @@ -1114,6 +1130,7 @@ impl<'a> IoSliceMut<'a> { /// assert_eq!(bufs[0].deref(), [2; 14].as_ref()); /// assert_eq!(bufs[1].deref(), [3; 8].as_ref()); /// ``` + #[allow(clippy::mem_replace_with_default)] #[inline] pub fn advance_slices(bufs: &mut &mut [IoSliceMut<'a>], n: usize) { // Number of buffers to remove. @@ -1239,6 +1256,7 @@ impl<'a> IoSlice<'a> { /// IoSlice::advance_slices(&mut bufs, 10); /// assert_eq!(bufs[0].deref(), [2; 14].as_ref()); /// assert_eq!(bufs[1].deref(), [3; 8].as_ref()); + #[allow(clippy::mem_replace_with_default)] #[inline] pub fn advance_slices(bufs: &mut &mut [IoSlice<'a>], n: usize) { // Number of buffers to remove. @@ -1270,48 +1288,6 @@ impl<'a> Deref for IoSlice<'a> { } } -/// A type used to conditionally initialize buffers passed to `Read` methods. -#[derive(Debug)] -pub struct Initializer(bool); - -impl Initializer { - /// Returns a new `Initializer` which will zero out buffers. - #[must_use] - #[inline] - pub fn zeroing() -> Initializer { - Initializer(true) - } - - /// Returns a new `Initializer` which will not zero out buffers. - /// - /// # Safety - /// - /// This may only be called by `Read`ers which guarantee that they will not - /// read from buffers passed to `Read` methods, and that the return value of - /// the method accurately reflects the number of bytes that have been - /// written to the head of the buffer. - #[must_use] - #[inline] - pub unsafe fn nop() -> Initializer { - Initializer(false) - } - - /// Indicates if a buffer should be initialized. - #[must_use] - #[inline] - pub fn should_initialize(&self) -> bool { - self.0 - } - - /// Initializes a buffer if necessary. - #[inline] - pub fn initialize(&self, buf: &mut [u8]) { - if self.should_initialize() { - unsafe { ptr::write_bytes(buf.as_mut_ptr(), 0, buf.len()) } - } - } -} - /// A trait for objects which are byte-oriented sinks. /// /// Implementors of the `Write` trait are sometimes called 'writers'. @@ -1514,9 +1490,9 @@ pub trait Write { while !buf.is_empty() { match self.write(buf) { Ok(0) => { - return Err(Error::new_const( + return Err(error::const_io_error!( ErrorKind::WriteZero, - &"failed to write whole buffer", + "failed to write whole buffer", )); } Ok(n) => buf = &buf[n..], @@ -1581,9 +1557,9 @@ pub trait Write { while !bufs.is_empty() { match self.write_vectored(bufs) { Ok(0) => { - return Err(Error::new_const( + return Err(error::const_io_error!( ErrorKind::WriteZero, - &"failed to write whole buffer", + "failed to write whole buffer", )); } Ok(n) => IoSlice::advance_slices(&mut bufs, n), @@ -1657,7 +1633,7 @@ pub trait Write { if output.error.is_err() { output.error } else { - Err(Error::new_const(ErrorKind::Uncategorized, &"formatter error")) + Err(error::const_io_error!(ErrorKind::Uncategorized, "formatter error")) } } } @@ -2336,11 +2312,6 @@ impl Read for Chain { } self.second.read_vectored(bufs) } - - unsafe fn initializer(&self) -> Initializer { - let initializer = self.first.initializer(); - if initializer.should_initialize() { initializer } else { self.second.initializer() } - } } impl BufRead for Chain { @@ -2535,8 +2506,53 @@ impl Read for Take { Ok(n) } - unsafe fn initializer(&self) -> Initializer { - self.inner.initializer() + fn read_buf(&mut self, buf: &mut ReadBuf<'_>) -> 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 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()); + + // SAFETY: no uninit data is written to ibuf + let ibuf = unsafe { &mut buf.unfilled_mut()[..limit] }; + + let mut sliced_buf = ReadBuf::uninit(ibuf); + + // SAFETY: extra_init bytes of ibuf are known to be initialized + unsafe { + sliced_buf.assume_init(extra_init); + } + + self.inner.read_buf(&mut sliced_buf)?; + + let new_init = sliced_buf.initialized_len(); + let filled = sliced_buf.filled_len(); + + // sliced_buf / ibuf must drop here + + // SAFETY: new_init bytes of buf's unfilled buffer have been initialized + unsafe { + buf.assume_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; + } + + Ok(()) } } diff --git a/sgx_tstd/src/io/readbuf.rs b/sgx_tstd/src/io/readbuf.rs new file mode 100644 index 000000000..db776d762 --- /dev/null +++ b/sgx_tstd/src/io/readbuf.rs @@ -0,0 +1,257 @@ +// 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.. + +use crate::cmp; +use crate::fmt::{self, Debug, Formatter}; +use crate::mem::MaybeUninit; + +/// A wrapper around a byte buffer that 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 +/// logically filled, and a region at the end that is fully uninitialized. The filled region is guaranteed to be a +/// subset of the initialized region. +/// +/// In summary, the contents of the buffer can be visualized as: +/// ```not_rust +/// [ capacity ] +/// [ filled | unfilled ] +/// [ initialized | uninitialized ] +/// ``` +pub struct ReadBuf<'a> { + buf: &'a mut [MaybeUninit], + filled: usize, + initialized: usize, +} + +impl Debug for ReadBuf<'_> { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + f.debug_struct("ReadBuf") + .field("init", &self.initialized()) + .field("filled", &self.filled) + .field("capacity", &self.capacity()) + .finish() + } +} + +impl<'a> ReadBuf<'a> { + /// Creates a new `ReadBuf` from a fully initialized buffer. + #[inline] + pub fn new(buf: &'a mut [u8]) -> ReadBuf<'a> { + let len = buf.len(); + + ReadBuf { + //SAFETY: initialized data never becoming uninitialized is an invariant of ReadBuf + buf: unsafe { (buf as *mut [u8]).as_uninit_slice_mut().unwrap() }, + filled: 0, + initialized: len, + } + } + + /// Creates a new `ReadBuf` from a fully uninitialized buffer. + /// + /// Use `assume_init` if part of the buffer is known to be already initialized. + #[inline] + pub fn uninit(buf: &'a mut [MaybeUninit]) -> ReadBuf<'a> { + ReadBuf { buf, filled: 0, initialized: 0 } + } + + /// Returns the total capacity of the buffer. + #[inline] + pub fn capacity(&self) -> usize { + self.buf.len() + } + + /// 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 + unsafe { MaybeUninit::slice_assume_init_ref(&self.buf[0..self.filled]) } + } + + /// Returns a mutable reference to the filled portion 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]) } + } + + /// Returns a shared reference to the initialized portion of the buffer. + /// + /// This includes the filled portion. + #[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]) } + } + + /// Returns a mutable reference to the initialized portion of the buffer. + /// + /// 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. + /// + /// # Safety + /// + /// The caller must not de-initialize portions of the buffer that have already been initialized. + #[inline] + pub unsafe fn unfilled_mut(&mut self) -> &mut [MaybeUninit] { + &mut self.buf[self.filled..] + } + + /// Returns a mutable reference to the uninitialized part of the buffer. + /// + /// It is safe to uninitialize any of these bytes. + #[inline] + pub fn uninitialized_mut(&mut self) -> &mut [MaybeUninit] { + &mut self.buf[self.initialized..] + } + + /// 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. + #[inline] + pub fn initialize_unfilled(&mut self) -> &mut [u8] { + // should optimize out the assertion + self.initialize_unfilled_to(self.remaining()) + } + + /// Returns a mutable reference to the first `n` bytes of the unfilled part of the buffer, ensuring it is + /// fully initialized. + /// + /// # Panics + /// + /// Panics if `self.remaining()` is less than `n`. + #[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; + + &mut self.initialized_mut()[filled..filled + n] + } + + /// Returns the number of bytes at the end of the slice that have not yet been filled. + #[inline] + pub fn remaining(&self) -> usize { + self.capacity() - self.filled + } + + /// Clears the buffer, resetting the filled region to empty. + /// + /// The number of initialized bytes is not changed, and the contents of the buffer are not modified. + #[inline] + pub fn clear(&mut self) { + self.set_filled(0); // The assertion in `set_filled` is optimized out + } + + /// Increases the size of the filled region of the buffer. + /// + /// The number of initialized bytes is not changed. + /// + /// # Panics + /// + /// Panics if the filled region of the buffer would become larger than the initialized region. + #[inline] + pub fn add_filled(&mut self, n: usize) { + self.set_filled(self.filled + n); + } + + /// Sets the size of the filled region of the buffer. + /// + /// The number of initialized bytes is not changed. + /// + /// 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 + /// + /// Panics if the filled region of the buffer would become larger than the initialized region. + #[inline] + pub fn set_filled(&mut self, n: usize) { + assert!(n <= self.initialized); + + self.filled = n; + } + + /// Asserts that the first `n` unfilled bytes of the buffer 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. + /// + /// # Safety + /// + /// The caller must ensure that the first `n` unfilled 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); + } + + /// Appends data to the buffer, advancing the written position and possibly also the initialized position. + /// + /// # Panics + /// + /// Panics if `self.remaining()` is less than `buf.len()`. + #[inline] + pub fn append(&mut self, buf: &[u8]) { + assert!(self.remaining() >= 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); + } + + // SAFETY: We just added the entire contents of buf to the filled section. + unsafe { self.assume_init(buf.len()) } + self.add_filled(buf.len()); + } + + /// Returns the amount of bytes that have been filled. + #[inline] + pub fn filled_len(&self) -> usize { + self.filled + } + + /// Returns the amount of bytes that have been initialized. + #[inline] + pub fn initialized_len(&self) -> usize { + self.initialized + } +} diff --git a/sgx_tstd/src/io/stdio.rs b/sgx_tstd/src/io/stdio.rs index bb7203069..8a18478f7 100644 --- a/sgx_tstd/src/io/stdio.rs +++ b/sgx_tstd/src/io/stdio.rs @@ -19,7 +19,7 @@ use crate::io::prelude::*; use crate::cell::RefCell; use crate::fmt; -use crate::io::{self, BufReader, Initializer, IoSlice, IoSliceMut, LineWriter, Lines, Split}; +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}; @@ -93,11 +93,6 @@ impl Read for StdinRaw { self.0.is_read_vectored() } - #[inline] - unsafe fn initializer(&self) -> Initializer { - Initializer::nop() - } - fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { handle_ebadf(self.0.read_to_end(buf), 0) } @@ -447,28 +442,6 @@ impl Stdin { pub fn lines(self) -> Lines> { self.into_locked().lines() } - - /// Consumes this handle and returns an iterator over input bytes, - /// split at the specified byte value. - /// - /// For detailed semantics of this method, see the documentation on - /// [`BufRead::split`]. - /// - /// # Examples - /// - /// ```no_run - /// #![feature(stdin_forwarders)] - /// use std::io; - /// - /// let splits = io::stdin().split(b'-'); - /// for split in splits { - /// println!("got a chunk: {}", String::from_utf8_lossy(&split.unwrap())); - /// } - /// ``` - #[must_use = "`self` will be dropped if the result is not used"] - pub fn split(self, byte: u8) -> Split> { - self.into_locked().split(byte) - } } impl fmt::Debug for Stdin { @@ -488,10 +461,6 @@ impl Read for Stdin { fn is_read_vectored(&self) -> bool { self.lock().is_read_vectored() } - #[inline] - unsafe fn initializer(&self) -> Initializer { - Initializer::nop() - } fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { self.lock().read_to_end(buf) } @@ -524,11 +493,6 @@ impl Read for StdinLock<'_> { self.inner.is_read_vectored() } - #[inline] - unsafe fn initializer(&self) -> Initializer { - Initializer::nop() - } - fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { self.inner.read_to_end(buf) } diff --git a/sgx_tstd/src/io/util.rs b/sgx_tstd/src/io/util.rs index 16f80555e..efc956d81 100644 --- a/sgx_tstd/src/io/util.rs +++ b/sgx_tstd/src/io/util.rs @@ -19,7 +19,7 @@ use crate::fmt; use crate::io::{ - self, BufRead, Initializer, IoSlice, IoSliceMut, Read, Seek, SeekFrom, SizeHint, Write, + self, BufRead, IoSlice, IoSliceMut, Read, ReadBuf, Seek, SeekFrom, SizeHint, Write, }; /// A reader which is always at EOF. @@ -57,8 +57,8 @@ impl Read for Empty { } #[inline] - unsafe fn initializer(&self) -> Initializer { - Initializer::nop() + fn read_buf(&mut self, _buf: &mut ReadBuf<'_>) -> io::Result<()> { + Ok(()) } } @@ -134,6 +134,24 @@ impl Read for Repeat { Ok(buf.len()) } + fn read_buf(&mut self, buf: &mut ReadBuf<'_>) -> io::Result<()> { + // SAFETY: No uninit bytes are being written + for slot in unsafe { buf.unfilled_mut() } { + slot.write(self.byte); + } + + let remaining = buf.remaining(); + + // SAFETY: the entire unfilled portion of buf has been initialized + unsafe { + buf.assume_init(remaining); + } + + buf.add_filled(remaining); + + Ok(()) + } + #[inline] fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result { let mut nwritten = 0; @@ -147,11 +165,6 @@ impl Read for Repeat { fn is_read_vectored(&self) -> bool { true } - - #[inline] - unsafe fn initializer(&self) -> Initializer { - Initializer::nop() - } } impl SizeHint for Repeat { diff --git a/sgx_tstd/src/lib.rs b/sgx_tstd/src/lib.rs index 7f3b01813..e7fe9ff83 100644 --- a/sgx_tstd/src/lib.rs +++ b/sgx_tstd/src/lib.rs @@ -46,39 +46,36 @@ #![allow(clippy::declare_interior_mutable_const)] #![allow(clippy::len_without_is_empty)] -#![allow(clippy::mem_replace_with_default)] #![allow(clippy::missing_safety_doc)] #![allow(clippy::new_without_default)] #![allow(clippy::transmute_ptr_to_ptr)] #![allow(clippy::wrong_self_convention)] #![feature(rustc_allow_const_fn_unstable)] - #![feature(alloc_error_handler)] #![feature(allocator_api)] #![feature(allocator_internals)] #![feature(allow_internal_unsafe)] #![feature(allow_internal_unstable)] #![feature(array_error_internals)] -#![feature(asm)] #![feature(assert_matches)] -#![feature(async_stream)] +#![feature(async_iterator)] #![feature(bench_black_box)] #![feature(bool_to_option)] #![feature(box_syntax)] -#![feature(c_variadic)] #![feature(c_unwind)] +#![feature(c_variadic)] #![feature(cfg_accessible)] #![feature(cfg_eval)] #![feature(cfg_target_has_atomic)] #![feature(char_error_internals)] #![feature(char_internals)] +#![feature(concat_bytes)] #![feature(concat_idents)] -#![feature(const_caller_location)] #![feature(const_fn_fn_ptr_basics)] #![feature(const_fn_trait_bound)] #![feature(const_format_args)] -#![feature(const_raw_ptr_deref)] +#![feature(const_mut_refs)] #![feature(const_trait_impl)] #![feature(core_intrinsics)] #![feature(core_panic)] @@ -88,23 +85,22 @@ #![feature(duration_checked_float)] #![feature(duration_constants)] #![feature(edition_panic)] +#![feature(exact_size_is_empty)] #![feature(extend_one)] #![feature(fn_traits)] +#![feature(float_minimum_maximum)] #![feature(format_args_nl)] #![feature(gen_future)] #![feature(get_mut_unchecked)] -#![feature(global_asm)] #![feature(hashmap_internals)] -#![feature(into_future)] #![feature(int_error_internals)] -#![feature(iter_zip)] +#![feature(into_future)] #![feature(lang_items)] #![feature(linked_list_remove)] -#![feature(llvm_asm)] #![feature(log_syntax)] #![feature(map_try_insert)] -#![feature(maybe_uninit_extra)] #![feature(maybe_uninit_slice)] +#![feature(maybe_uninit_write_slice)] #![feature(mixed_integer_ops)] #![feature(must_not_suspend)] #![feature(needs_panic_runtime)] @@ -114,11 +110,13 @@ #![feature(once_cell)] #![feature(panic_info_message)] #![feature(panic_internals)] +#![feature(panic_can_unwind)] #![feature(panic_unwind)] -#![feature(pin_static_ref)] #![feature(prelude_import)] +#![feature(ptr_as_uninit)] #![feature(ptr_internals)] #![feature(rustc_attrs)] +#![feature(slice_internals)] #![feature(specialization)] #![feature(std_internals)] #![feature(str_internals)] @@ -130,7 +128,6 @@ #![feature(try_blocks)] #![feature(try_reserve_kind)] #![feature(unboxed_closures)] -#![feature(vec_spare_capacity)] #![default_lib_allocator] // Explicitly import the prelude. The compiler uses this same unstable attribute @@ -189,6 +186,7 @@ pub use alloc_crate::string; pub use alloc_crate::vec; pub use core::any; pub use core::array; +pub use core::async_iter; pub use core::cell; pub use core::char; pub use core::clone; @@ -213,7 +211,6 @@ pub use core::option; pub use core::pin; pub use core::ptr; pub use core::result; -pub use core::stream; pub use core::u128; pub use core::u16; pub use core::u32; @@ -221,6 +218,11 @@ pub use core::u64; pub use core::u8; pub use core::usize; +// The runtime entry point and a few unstable public functions used by the +// compiler +#[macro_use] +pub mod rt; + pub mod f32; pub mod f64; @@ -257,10 +259,14 @@ pub mod task { pub use alloc_crate::task::*; } -// The runtime entry point and a few unstable public functions used by the -// compiler -#[macro_use] -pub mod rt; +pub mod arch { + // The `no_inline`-attribute is required to make the documentation of all + // targets available. + // See https://github.com/rust-lang/rust/pull/57808#issuecomment-457390549 for + // more information. + #[doc(no_inline)] // Note (#82861): required for correct documentation + pub use core::arch::*; +} // Platform-abstraction modules mod sys; @@ -295,10 +301,12 @@ pub use core::{ #[allow(deprecated)] pub use core::{ assert, assert_matches, cfg, column, compile_error, concat, concat_idents, const_format_args, - env, file, format_args, format_args_nl, include, include_bytes, include_str, line, llvm_asm, - log_syntax, module_path, option_env, stringify, trace_macros, + env, file, format_args, format_args_nl, include, include_bytes, include_str, line, log_syntax, + module_path, option_env, stringify, trace_macros, }; +pub use core::concat_bytes; + pub use core::primitive; mod sealed { diff --git a/sgx_tstd/src/macros.rs b/sgx_tstd/src/macros.rs index e992568f9..5b4e7d019 100644 --- a/sgx_tstd/src/macros.rs +++ b/sgx_tstd/src/macros.rs @@ -70,7 +70,9 @@ macro_rules! panic { /// /// io::stdout().flush().unwrap(); /// ``` +#[cfg(feature = "stdio")] #[macro_export] +#[cfg_attr(not(test), rustc_diagnostic_item = "print_macro")] #[allow_internal_unstable(print_internals)] macro_rules! print { ($($arg:tt)*) => ($crate::io::_print($crate::format_args!($($arg)*))); @@ -102,7 +104,9 @@ macro_rules! print { /// println!("hello there!"); /// println!("format {} arguments", "some"); /// ``` +#[cfg(feature = "stdio")] #[macro_export] +#[cfg_attr(not(test), rustc_diagnostic_item = "println_macro")] #[allow_internal_unstable(print_internals, format_args_nl)] macro_rules! println { () => ($crate::print!("\n")); @@ -113,10 +117,12 @@ macro_rules! println { #[cfg(not(feature = "stdio"))] #[macro_export] +#[cfg_attr(not(test), rustc_diagnostic_item = "print_macro")] macro_rules! print { ($($arg:tt)*) => ({}) } #[cfg(not(feature = "stdio"))] #[macro_export] +#[cfg_attr(not(test), rustc_diagnostic_item = "println_macro")] macro_rules! println { ($($arg:tt)*) => ({}) } /// Prints to the standard error. @@ -140,7 +146,9 @@ macro_rules! println { ($($arg:tt)*) => ({}) } /// ``` /// eprint!("Error: Could not complete task"); /// ``` +#[cfg(feature = "stdio")] #[macro_export] +#[cfg_attr(not(test), rustc_diagnostic_item = "eprint_macro")] #[allow_internal_unstable(print_internals)] macro_rules! eprint { ($($arg:tt)*) => ($crate::io::_eprint($crate::format_args!($($arg)*))); @@ -167,7 +175,9 @@ macro_rules! eprint { /// ``` /// eprintln!("Error: Could not complete task"); /// ``` +#[cfg(feature = "stdio")] #[macro_export] +#[cfg_attr(not(test), rustc_diagnostic_item = "eprintln_macro")] #[allow_internal_unstable(print_internals, format_args_nl)] macro_rules! eprintln { () => ($crate::eprint!("\n")); @@ -178,10 +188,12 @@ macro_rules! eprintln { #[cfg(not(feature = "stdio"))] #[macro_export] +#[cfg_attr(not(test), rustc_diagnostic_item = "eprint_macro")] macro_rules! eprint { ($($arg:tt)*) => ({}) } #[cfg(not(feature = "stdio"))] #[macro_export] +#[cfg_attr(not(test), rustc_diagnostic_item = "eprintln_macro")] macro_rules! eprintln { ($($arg:tt)*) => ({}) } /// Prints and returns the value of a given expression for quick and dirty @@ -309,6 +321,7 @@ macro_rules! eprintln { ($($arg:tt)*) => ({}) } /// [`debug!`]: https://docs.rs/log/*/log/macro.debug.html /// [`log`]: https://crates.io/crates/log #[macro_export] +#[cfg_attr(not(test), rustc_diagnostic_item = "dbg_macro")] macro_rules! dbg { // NOTE: We cannot use `concat!` to make a static string as a format argument // of `eprintln!` because `file!` could contain a `{` or diff --git a/sgx_tstd/src/net/addr.rs b/sgx_tstd/src/net/addr.rs index 83a4dbc06..affcf4d84 100644 --- a/sgx_tstd/src/net/addr.rs +++ b/sgx_tstd/src/net/addr.rs @@ -919,8 +919,7 @@ impl ToSocketAddrs for (Ipv6Addr, u16) { } #[cfg(feature = "net")] -#[allow(clippy::unnecessary_wraps)] -#[allow(clippy::needless_collect)] +#[allow(clippy::unnecessary_wraps, clippy::needless_collect)] fn resolve_socket_addr(lh: LookupHost) -> io::Result> { let p = lh.port(); let v: Vec<_> = lh @@ -948,7 +947,7 @@ impl ToSocketAddrs for (&str, u16) { } #[cfg(not(feature = "net"))] - let r = Err(io::Error::new_const(io::ErrorKind::InvalidInput, &"invalid socket address")); + let r = Err(io::const_io_error!(io::ErrorKind::InvalidInput, "invalid socket address")); #[cfg(feature = "net")] let r = resolve_socket_addr((host, port).try_into()?); r @@ -972,7 +971,7 @@ impl ToSocketAddrs for str { } #[cfg(not(feature = "net"))] - let r = Err(io::Error::new_const(io::ErrorKind::InvalidInput, &"invalid socket address")); + let r = Err(io::const_io_error!(io::ErrorKind::InvalidInput, "invalid socket address")); #[cfg(feature = "net")] let r = resolve_socket_addr(self.try_into()?); r diff --git a/sgx_tstd/src/net/ip.rs b/sgx_tstd/src/net/ip.rs index 79503e7bc..2bcf01efe 100644 --- a/sgx_tstd/src/net/ip.rs +++ b/sgx_tstd/src/net/ip.rs @@ -841,12 +841,7 @@ impl Ipv4Addr { #[inline] #[allow(clippy::match_like_matches_macro)] pub const fn is_documentation(&self) -> bool { - match self.octets() { - [192, 0, 2, _] => true, - [198, 51, 100, _] => true, - [203, 0, 113, _] => true, - _ => false, - } + matches!(self.octets(), [192, 0, 2, _] | [198, 51, 100, _] | [203, 0, 113, _]) } /// Converts this address to an [IPv4-compatible] [`IPv6` address]. @@ -1087,8 +1082,8 @@ impl From for u32 { /// ``` /// use std::net::Ipv4Addr; /// - /// let addr = Ipv4Addr::new(0xca, 0xfe, 0xba, 0xbe); - /// assert_eq!(0xcafebabe, u32::from(addr)); + /// let addr = Ipv4Addr::new(0x12, 0x34, 0x56, 0x78); + /// assert_eq!(0x12345678, u32::from(addr)); /// ``` #[inline] fn from(ip: Ipv4Addr) -> u32 { @@ -1105,8 +1100,8 @@ impl From for Ipv4Addr { /// ``` /// use std::net::Ipv4Addr; /// - /// let addr = Ipv4Addr::from(0xcafebabe); - /// assert_eq!(Ipv4Addr::new(0xca, 0xfe, 0xba, 0xbe), addr); + /// let addr = Ipv4Addr::from(0x12345678); + /// assert_eq!(Ipv4Addr::new(0x12, 0x34, 0x56, 0x78), addr); /// ``` #[inline] fn from(ip: u32) -> Ipv4Addr { @@ -1161,7 +1156,6 @@ impl Ipv6Addr { /// let addr = Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff); /// ``` #[allow(clippy::too_many_arguments)] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_fn_transmute))] #[must_use] #[inline] pub const fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> Ipv6Addr { @@ -1736,7 +1730,7 @@ impl fmt::Display for Ipv6Addr { } } } else { - // Slow path: write the address to a local buffer, the use f.pad. + // Slow path: write the address to a local buffer, then use f.pad. // Defined recursively by using the fast path to write to the // buffer. diff --git a/sgx_tstd/src/net/mod.rs b/sgx_tstd/src/net/mod.rs index 179670256..f6c9de47b 100644 --- a/sgx_tstd/src/net/mod.rs +++ b/sgx_tstd/src/net/mod.rs @@ -32,12 +32,14 @@ //! with networking objects like [`TcpListener`], [`TcpStream`] or [`UdpSocket`] //! * Other types are return or parameter types for various methods in this module -use crate::io::{self, Error, ErrorKind}; +use crate::io::{self, ErrorKind}; pub use self::addr::{SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs}; pub use self::ip::{IpAddr, Ipv4Addr, Ipv6Addr, Ipv6MulticastScope}; pub use self::parser::AddrParseError; #[cfg(feature = "net")] +pub use self::tcp::IntoIncoming; +#[cfg(feature = "net")] pub use self::tcp::{Incoming, TcpListener, TcpStream}; #[cfg(feature = "net")] pub use self::udp::UdpSocket; @@ -96,6 +98,6 @@ where } } Err(last_err.unwrap_or_else(|| { - Error::new_const(ErrorKind::InvalidInput, &"could not resolve to any addresses") + io::const_io_error!(ErrorKind::InvalidInput, "could not resolve to any addresses") })) } \ No newline at end of file diff --git a/sgx_tstd/src/net/tcp.rs b/sgx_tstd/src/net/tcp.rs index b939990c6..bdcadd56f 100644 --- a/sgx_tstd/src/net/tcp.rs +++ b/sgx_tstd/src/net/tcp.rs @@ -18,7 +18,7 @@ use crate::io::prelude::*; use crate::fmt; -use crate::io::{self, Initializer, IoSlice, IoSliceMut}; +use crate::io::{self, IoSlice, IoSliceMut}; use crate::net::{Shutdown, SocketAddr, ToSocketAddrs}; use crate::sys_common::net as net_imp; use crate::sys_common::{AsInner, FromInner, IntoInner}; @@ -448,7 +448,7 @@ impl TcpStream { /// use std::net::TcpStream; /// /// let stream = TcpStream::connect("127.0.0.1:8000") - /// .expect("couldn't bind to address"); + /// .expect("Couldn't connect to the server..."); /// let mut buf = [0; 10]; /// let len = stream.peek(&mut buf).expect("peek failed"); /// ``` @@ -659,12 +659,6 @@ impl Read for TcpStream { fn is_read_vectored(&self) -> bool { self.0.is_read_vectored() } - - #[inline] - unsafe fn initializer(&self) -> Initializer { - // SAFETY: Read is guaranteed to work on uninitialized memory - Initializer::nop() - } } impl Write for TcpStream { @@ -699,12 +693,6 @@ impl Read for &TcpStream { fn is_read_vectored(&self) -> bool { self.0.is_read_vectored() } - - #[inline] - unsafe fn initializer(&self) -> Initializer { - // SAFETY: Read is guaranteed to work on uninitialized memory - Initializer::nop() - } } impl Write for &TcpStream { diff --git a/sgx_tstd/src/net/udp.rs b/sgx_tstd/src/net/udp.rs index 2ba2f0b1f..52ddab8cd 100644 --- a/sgx_tstd/src/net/udp.rs +++ b/sgx_tstd/src/net/udp.rs @@ -16,7 +16,7 @@ // under the License.. use crate::fmt; -use crate::io::{self, Error, ErrorKind}; +use crate::io::{self, ErrorKind}; use crate::net::{Ipv4Addr, Ipv6Addr, SocketAddr, ToSocketAddrs}; use crate::sys_common::net as net_imp; use crate::sys_common::{AsInner, FromInner, IntoInner}; @@ -203,7 +203,9 @@ impl UdpSocket { pub fn send_to(&self, buf: &[u8], addr: A) -> io::Result { match addr.to_socket_addrs()?.next() { Some(addr) => self.0.send_to(buf, &addr), - None => Err(Error::new_const(ErrorKind::InvalidInput, &"no addresses to send data to")), + None => { + Err(io::const_io_error!(ErrorKind::InvalidInput, "no addresses to send data to")) + } } } diff --git a/sgx_tstd/src/os/fd/owned.rs b/sgx_tstd/src/os/fd/owned.rs index 4f00737ab..ca7d353f4 100644 --- a/sgx_tstd/src/os/fd/owned.rs +++ b/sgx_tstd/src/os/fd/owned.rs @@ -21,10 +21,11 @@ use super::raw::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; use crate::fmt; +use crate::fs; use crate::marker::PhantomData; use crate::mem::forget; +use crate::sys::cvt; use crate::sys_common::{AsInner, FromInner, IntoInner}; -use crate::untrusted::fs; /// A borrowed file descriptor. /// @@ -80,6 +81,21 @@ impl BorrowedFd<'_> { } } +impl OwnedFd { + /// Creates a new `OwnedFd` instance that shares the same underlying file handle + /// as the existing `OwnedFd` instance. + pub fn try_clone(&self) -> crate::io::Result { + // We want to atomically duplicate this file descriptor and set the + // CLOEXEC flag, and currently that's done via F_DUPFD_CLOEXEC. This + // is a POSIX flag that was added to Linux in 2.6.24. + let cmd = libc::F_DUPFD_CLOEXEC; + + let fd = cvt(unsafe { libc::fcntl_arg1(self.as_raw_fd(), cmd, 0) })?; + Ok(unsafe { Self::from_raw_fd(fd) }) + } + +} + impl AsRawFd for BorrowedFd<'_> { #[inline] fn as_raw_fd(&self) -> RawFd { @@ -171,6 +187,20 @@ pub trait AsFd { fn as_fd(&self) -> BorrowedFd<'_>; } +impl AsFd for &T { + #[inline] + fn as_fd(&self) -> BorrowedFd<'_> { + T::as_fd(self) + } +} + +impl AsFd for &mut T { + #[inline] + fn as_fd(&self) -> BorrowedFd<'_> { + T::as_fd(self) + } +} + impl AsFd for BorrowedFd<'_> { #[inline] fn as_fd(&self) -> BorrowedFd<'_> { @@ -291,5 +321,6 @@ impl From for crate::net::UdpSocket { } mod libc { - pub use sgx_libc::ocall::close; + pub use sgx_libc::F_DUPFD_CLOEXEC; + pub use sgx_libc::ocall::{close, fcntl_arg1}; } diff --git a/sgx_tstd/src/os/fd/raw.rs b/sgx_tstd/src/os/fd/raw.rs index d73008dbb..44a63fb4e 100644 --- a/sgx_tstd/src/os/fd/raw.rs +++ b/sgx_tstd/src/os/fd/raw.rs @@ -17,12 +17,14 @@ //! Raw Unix-like file descriptors. +use crate::fs; +#[cfg(feature = "stdio")] use crate::io; use crate::os::raw; use crate::os::unix::io::OwnedFd; use crate::sys_common::{AsInner, IntoInner}; -use crate::untrusted::fs; +#[cfg(feature = "stdio")] use sgx_libc as libc; /// Raw file descriptors. diff --git a/sgx_tstd/src/os/fs.rs b/sgx_tstd/src/os/linux/fs.rs similarity index 98% rename from sgx_tstd/src/os/fs.rs rename to sgx_tstd/src/os/linux/fs.rs index 2305e1a7b..478350c18 100644 --- a/sgx_tstd/src/os/fs.rs +++ b/sgx_tstd/src/os/linux/fs.rs @@ -15,16 +15,15 @@ // specific language governing permissions and limitations // under the License.. -//! Linux-specific extensions to primitives in the `std::fs` module. +//! Linux-specific extensions to primitives in the [`std::fs`] module. +//! +//! [`std::fs`]: crate::fs -#[cfg(feature = "untrusted_fs")] use crate::fs::Metadata; use crate::sys_common::AsInner; -#[cfg(not(feature = "untrusted_fs"))] -use crate::untrusted::fs::Metadata; #[allow(deprecated)] -use crate::os::raw; +use crate::os::linux::raw; use sgx_libc as libc; diff --git a/sgx_tstd/src/os/linux/mod.rs b/sgx_tstd/src/os/linux/mod.rs new file mode 100644 index 000000000..473f2ef3a --- /dev/null +++ b/sgx_tstd/src/os/linux/mod.rs @@ -0,0 +1,21 @@ +// 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.. + +//! Linux-specific definitions. + +pub mod fs; +pub mod raw; diff --git a/sgx_tstd/src/os/raw.rs b/sgx_tstd/src/os/linux/raw.rs similarity index 73% rename from sgx_tstd/src/os/raw.rs rename to sgx_tstd/src/os/linux/raw.rs index 1defce61e..863975732 100644 --- a/sgx_tstd/src/os/raw.rs +++ b/sgx_tstd/src/os/linux/raw.rs @@ -17,34 +17,17 @@ //! Linux-specific raw type definitions. -pub type c_char = i8; -pub type c_schar = i8; -pub type c_uchar = u8; -pub type c_short = i16; -pub type c_ushort = u16; -pub type c_int = i32; -pub type c_uint = u32; -#[cfg(target_pointer_width = "32")] -pub type c_long = i32; -#[cfg(target_pointer_width = "32")] -pub type c_ulong = u32; -#[cfg(target_pointer_width = "64")] -pub type c_long = i64; -#[cfg(target_pointer_width = "64")] -pub type c_ulong = u64; -pub type c_longlong = i64; -pub type c_ulonglong = u64; -pub type c_float = f32; -pub type c_double = f64; +#![allow(deprecated)] -#[doc(no_inline)] -pub use core::ffi::c_void; +use crate::os::raw::c_void; pub type dev_t = u64; pub type mode_t = u32; pub type pthread_t = *mut c_void; -pub use self::arch::{off_t, ino_t, nlink_t, blksize_t, blkcnt_t, stat, time_t}; +#[doc(inline)] +pub use self::arch::{blkcnt_t, blksize_t, ino_t, nlink_t, off_t, stat, time_t}; + mod arch { use crate::os::raw::{c_long, c_int}; @@ -78,4 +61,4 @@ mod arch { pub st_ctime_nsec: c_long, pub __unused: [c_long; 3], } -} \ No newline at end of file +} diff --git a/sgx_tstd/src/os/mod.rs b/sgx_tstd/src/os/mod.rs index 657af0e1c..e8c86c1f2 100644 --- a/sgx_tstd/src/os/mod.rs +++ b/sgx_tstd/src/os/mod.rs @@ -17,7 +17,7 @@ //! OS-specific functionality. -pub mod fs; +pub mod linux; pub mod raw; pub mod unix; diff --git a/sgx_tstd/src/os/raw/mod.rs b/sgx_tstd/src/os/raw/mod.rs new file mode 100644 index 000000000..57515b668 --- /dev/null +++ b/sgx_tstd/src/os/raw/mod.rs @@ -0,0 +1,89 @@ +// 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.. + +//! Platform-specific types, as defined by C. +//! +//! Code that interacts via FFI will almost certainly be using the +//! base types provided by C, which aren't nearly as nicely defined +//! as Rust's primitive types. This module provides types which will +//! match those defined by C, so that code that interacts with C will +//! refer to the correct types. + +use core::num::*; + +macro_rules! type_alias_no_nz { + { + $Alias:ident = $Real:ty; + $( $Cfg:tt )* + } => { + $( $Cfg )* + pub type $Alias = $Real; + } +} + +macro_rules! type_alias { + { + $Alias:ident = $Real:ty, $NZAlias:ident = $NZReal:ty; + $( $Cfg:tt )* + } => { + type_alias_no_nz! { $Alias = $Real; $( $Cfg )* } + + $( $Cfg )* + pub type $NZAlias = $NZReal; + } +} + +type_alias! { c_char = i8, NonZero_c_char = NonZeroI8; } +type_alias! { c_schar = i8, NonZero_c_schar = NonZeroI8; } +type_alias! { c_uchar = u8, NonZero_c_uchar = NonZeroU8; } +type_alias! { c_short = i16, NonZero_c_short = NonZeroI16; } +type_alias! { c_ushort = u16, NonZero_c_ushort = NonZeroU16; } +type_alias! { c_int = i32, NonZero_c_int = NonZeroI32; } +type_alias! { c_uint = u32, NonZero_c_uint = NonZeroU32; } +type_alias! { c_long = i32, NonZero_c_long = NonZeroI32; +#[cfg(target_pointer_width = "32")] } +type_alias! { c_ulong = u32, NonZero_c_ulong = NonZeroU32; +#[cfg(target_pointer_width = "32")] } +type_alias! { c_long = i64, NonZero_c_long = NonZeroI64; +#[cfg(target_pointer_width = "64")] } +type_alias! { c_ulong = u64, NonZero_c_ulong = NonZeroU64; +#[cfg(target_pointer_width = "64")] } +type_alias! { c_longlong = i64, NonZero_c_longlong = NonZeroI64; } +type_alias! { c_ulonglong = u64, NonZero_c_ulonglong = NonZeroU64; } +type_alias_no_nz! { c_float = f32; } +type_alias_no_nz! { c_double = f64; } + +#[doc(no_inline)] +pub use core::ffi::c_void; + +/// Equivalent to C's `size_t` type, from `stddef.h` (or `cstddef` for C++). +/// +/// This type is currently always [`usize`], however in the future there may be +/// platforms where this is not the case. +pub type c_size_t = usize; + +/// Equivalent to C's `ptrdiff_t` type, from `stddef.h` (or `cstddef` for C++). +/// +/// This type is currently always [`isize`], however in the future there may be +/// platforms where this is not the case. +pub type c_ptrdiff_t = isize; + +/// Equivalent to C's `ssize_t` (on POSIX) or `SSIZE_T` (on Windows) type. +/// +/// This type is currently always [`isize`], however in the future there may be +/// platforms where this is not the case. +pub type c_ssize_t = isize; diff --git a/sgx_tstd/src/os/unix/ffi/os_str.rs b/sgx_tstd/src/os/unix/ffi/os_str.rs index c06e5ea54..5ba5083f7 100644 --- a/sgx_tstd/src/os/unix/ffi/os_str.rs +++ b/sgx_tstd/src/os/unix/ffi/os_str.rs @@ -41,9 +41,11 @@ pub trait OsStringExt: Sealed { } impl OsStringExt for OsString { + #[inline] fn from_vec(vec: Vec) -> OsString { FromInner::from_inner(Buf { inner: vec }) } + #[inline] fn into_vec(self) -> Vec { self.into_inner().inner } diff --git a/sgx_tstd/src/os/unix/fs.rs b/sgx_tstd/src/os/unix/fs.rs index c5487a2ce..3e0de5dee 100644 --- a/sgx_tstd/src/os/unix/fs.rs +++ b/sgx_tstd/src/os/unix/fs.rs @@ -15,14 +15,17 @@ // specific language governing permissions and limitations // under the License.. -//! Unix-specific extensions to primitives in the `std::fs` module. +//! Unix-specific extensions to primitives in the [`std::fs`] module. +//! +//! [`std::fs`]: crate::fs +use super::platform::fs::MetadataExt as _; +use crate::fs::{self, OpenOptions, Permissions}; use crate::io; -use crate::os::fs::MetadataExt as _; +use crate::os::unix::io::{AsFd, AsRawFd}; use crate::path::Path; use crate::sys; use crate::sys_common::{AsInner, AsInnerMut, FromInner}; -use crate::untrusted::fs::{self, OpenOptions, Permissions}; // Used for `File::read` on intra-doc links use crate::ffi::OsStr; use crate::sealed::Sealed; @@ -125,7 +128,7 @@ pub trait FileExt { } } if !buf.is_empty() { - Err(io::Error::new_const(io::ErrorKind::UnexpectedEof, &"failed to fill whole buffer")) + Err(io::const_io_error!(io::ErrorKind::UnexpectedEof, "failed to fill whole buffer",)) } else { Ok(()) } @@ -205,9 +208,9 @@ pub trait FileExt { while !buf.is_empty() { match self.write_at(buf, offset) { Ok(0) => { - return Err(io::Error::new_const( + return Err(io::const_io_error!( io::ErrorKind::WriteZero, - &"failed to write whole buffer", + "failed to write whole buffer", )); } Ok(n) => { @@ -885,6 +888,72 @@ impl DirBuilderExt for fs::DirBuilder { } } +/// Change the owner and group of the specified path. +/// +/// Specifying either the uid or gid as `None` will leave it unchanged. +/// +/// Changing the owner typically requires privileges, such as root or a specific capability. +/// Changing the group typically requires either being the owner and a member of the group, or +/// having privileges. +/// +/// If called on a symbolic link, this will change the owner and group of the link target. To +/// change the owner and group of the link itself, see [`lchown`]. +/// +/// # Examples +/// +/// ```no_run +/// #![feature(unix_chown)] +/// use std::os::unix::fs; +/// +/// fn main() -> std::io::Result<()> { +/// fs::chown("/sandbox", Some(0), Some(0))?; +/// Ok(()) +/// } +/// ``` +pub fn chown>(dir: P, uid: Option, gid: Option) -> io::Result<()> { + sys::fs::chown(dir.as_ref(), uid.unwrap_or(u32::MAX), gid.unwrap_or(u32::MAX)) +} + +/// Change the owner and group of the file referenced by the specified open file descriptor. +/// +/// For semantics and required privileges, see [`chown`]. +/// +/// # Examples +/// +/// ```no_run +/// #![feature(unix_chown)] +/// use std::os::unix::fs; +/// +/// fn main() -> std::io::Result<()> { +/// let f = std::fs::File::open("/file")?; +/// fs::fchown(&f, Some(0), Some(0))?; +/// Ok(()) +/// } +/// ``` +pub fn fchown(fd: F, uid: Option, gid: Option) -> io::Result<()> { + sys::fs::fchown(fd.as_fd().as_raw_fd(), uid.unwrap_or(u32::MAX), gid.unwrap_or(u32::MAX)) +} + +/// Change the owner and group of the specified path, without dereferencing symbolic links. +/// +/// Identical to [`chown`], except that if called on a symbolic link, this will change the owner +/// and group of the link itself rather than the owner and group of the link target. +/// +/// # Examples +/// +/// ```no_run +/// #![feature(unix_chown)] +/// use std::os::unix::fs; +/// +/// fn main() -> std::io::Result<()> { +/// fs::lchown("/symlink", Some(0), Some(0))?; +/// Ok(()) +/// } +/// ``` +pub fn lchown>(dir: P, uid: Option, gid: Option) -> io::Result<()> { + sys::fs::lchown(dir.as_ref(), uid.unwrap_or(u32::MAX), gid.unwrap_or(u32::MAX)) +} + /// Change the root directory of the current process to the specified path. /// /// This typically requires privileges, such as root or a specific capability. diff --git a/sgx_tstd/src/os/unix/io/fd.rs b/sgx_tstd/src/os/unix/io/fd.rs index f855305f7..88143de76 100644 --- a/sgx_tstd/src/os/unix/io/fd.rs +++ b/sgx_tstd/src/os/unix/io/fd.rs @@ -15,7 +15,6 @@ // specific language governing permissions and limitations // under the License.. - //! Owned and borrowed file descriptors. pub use crate::os::fd::owned::*; diff --git a/sgx_tstd/src/os/unix/mod.rs b/sgx_tstd/src/os/unix/mod.rs index 11c2de68f..11fc726a8 100644 --- a/sgx_tstd/src/os/unix/mod.rs +++ b/sgx_tstd/src/os/unix/mod.rs @@ -21,8 +21,8 @@ //! exposes Unix-specific functions that would otherwise be inappropriate as //! part of the core `std` library. //! -//! It exposes more ways to deal with platform-specific strings (`OsStr`, -//! `OsString`), allows to set permissions more granularly, extract low-level +//! It exposes more ways to deal with platform-specific strings ([`OsStr`], +//! [`OsString`]), allows to set permissions more granularly, extract low-level //! file descriptors from files and sockets, and has platform-specific helpers //! for spawning processes. //! @@ -45,6 +45,8 @@ //! [`OsStr`]: crate::ffi::OsStr //! [`OsString`]: crate::ffi::OsString +use crate::os::linux as platform; + pub mod ffi; pub mod fs; pub mod io; @@ -71,6 +73,7 @@ pub mod prelude { #[doc(no_inline)] pub use super::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd}; #[doc(no_inline)] + #[doc(no_inline)] #[cfg(feature = "thread")] pub use super::thread::JoinHandleExt; } diff --git a/sgx_tstd/src/os/unix/net/addr.rs b/sgx_tstd/src/os/unix/net/addr.rs index 279caa9b4..8efe3aff0 100644 --- a/sgx_tstd/src/os/unix/net/addr.rs +++ b/sgx_tstd/src/os/unix/net/addr.rs @@ -19,7 +19,7 @@ use crate::ffi::OsStr; use crate::os::unix::ffi::OsStrExt; use crate::path::Path; use crate::sys::cvt; -use crate::{ascii, fmt, io, iter, mem}; +use crate::{ascii, fmt, io, mem, ptr}; use sgx_libc as libc; fn sun_path_offset(addr: &libc::sockaddr_un) -> usize { @@ -29,30 +29,33 @@ fn sun_path_offset(addr: &libc::sockaddr_un) -> usize { path - base } -pub(super) unsafe fn sockaddr_un(path: &Path) -> io::Result<(libc::sockaddr_un, libc::socklen_t)> { - let mut addr: libc::sockaddr_un = mem::zeroed(); +pub(super) fn sockaddr_un(path: &Path) -> io::Result<(libc::sockaddr_un, libc::socklen_t)> { + // SAFETY: All zeros is a valid representation for `sockaddr_un`. + let mut addr: libc::sockaddr_un = unsafe { mem::zeroed() }; addr.sun_family = libc::AF_UNIX as libc::sa_family_t; let bytes = path.as_os_str().as_bytes(); if bytes.contains(&0) { - return Err(io::Error::new_const( + return Err(io::const_io_error!( io::ErrorKind::InvalidInput, - &"paths must not contain interior null bytes", + "paths must not contain interior null bytes", )); } if bytes.len() >= addr.sun_path.len() { - return Err(io::Error::new_const( + return Err(io::const_io_error!( io::ErrorKind::InvalidInput, - &"path must be shorter than SUN_LEN", + "path must be shorter than SUN_LEN", )); } - for (dst, src) in iter::zip(&mut addr.sun_path, bytes) { - *dst = *src as libc::c_char; - } - // null byte for pathname addresses is already there because we zeroed the - // struct + // SAFETY: `bytes` and `addr.sun_path` are not overlapping and + // both point to valid memory. + // NOTE: We zeroed the memory above, so the path is already null + // terminated. + unsafe { + ptr::copy_nonoverlapping(bytes.as_ptr(), addr.sun_path.as_mut_ptr().cast(), bytes.len()) + }; let mut len = sun_path_offset(&addr) + bytes.len(); match bytes.get(0) { @@ -124,15 +127,51 @@ impl SocketAddr { // linux returns zero bytes of address len = sun_path_offset(&addr) as libc::socklen_t; // i.e., zero-length address } else if addr.sun_family != libc::AF_UNIX as libc::sa_family_t { - return Err(io::Error::new_const( + return Err(io::const_io_error!( io::ErrorKind::InvalidInput, - &"file descriptor did not correspond to a Unix socket", + "file descriptor did not correspond to a Unix socket", )); } Ok(SocketAddr { addr, len }) } + /// Constructs a `SockAddr` with the family `AF_UNIX` and the provided path. + /// + /// # Errors + /// + /// Returns an error if the path is longer than `SUN_LEN` or if it contains + /// NULL bytes. + /// + /// # Examples + /// + /// ``` + /// #![feature(unix_socket_creation)] + /// use std::os::unix::net::SocketAddr; + /// use std::path::Path; + /// + /// # fn main() -> std::io::Result<()> { + /// let address = SocketAddr::from_path("/path/to/socket")?; + /// assert_eq!(address.as_pathname(), Some(Path::new("/path/to/socket"))); + /// # Ok(()) + /// # } + /// ``` + /// + /// Creating a `SocketAddr` with a NULL byte results in an error. + /// + /// ``` + /// #![feature(unix_socket_creation)] + /// use std::os::unix::net::SocketAddr; + /// + /// assert!(SocketAddr::from_path("/path/with/\0/bytes").is_err()); + /// ``` + pub fn from_path

(path: P) -> io::Result + where + P: AsRef, + { + sockaddr_un(path.as_ref()).map(|(addr, len)| SocketAddr { addr, len }) + } + /// Returns `true` if the address is unnamed. /// /// # Examples @@ -277,9 +316,9 @@ impl SocketAddr { addr.sun_family = libc::AF_UNIX as libc::sa_family_t; if namespace.len() + 1 > addr.sun_path.len() { - return Err(io::Error::new_const( + return Err(io::const_io_error!( io::ErrorKind::InvalidInput, - &"namespace must be shorter than SUN_LEN", + "namespace must be shorter than SUN_LEN", )); } diff --git a/sgx_tstd/src/os/unix/net/listener.rs b/sgx_tstd/src/os/unix/net/listener.rs index 498d368a7..ca91a3ae2 100644 --- a/sgx_tstd/src/os/unix/net/listener.rs +++ b/sgx_tstd/src/os/unix/net/listener.rs @@ -365,6 +365,7 @@ impl<'a> IntoIterator for &'a UnixListener { /// } /// ``` #[derive(Debug)] +#[must_use = "iterators are lazy and do nothing unless consumed"] pub struct Incoming<'a> { listener: &'a UnixListener, } diff --git a/sgx_tstd/src/os/unix/net/stream.rs b/sgx_tstd/src/os/unix/net/stream.rs index c642623ad..5e797d465 100644 --- a/sgx_tstd/src/os/unix/net/stream.rs +++ b/sgx_tstd/src/os/unix/net/stream.rs @@ -18,7 +18,7 @@ use super::{recv_vectored_with_ancillary_from, send_vectored_with_ancillary_to, SocketAncillary}; use super::{sockaddr_un, SocketAddr}; use crate::fmt; -use crate::io::{self, Initializer, IoSlice, IoSliceMut}; +use crate::io::{self, IoSlice, IoSliceMut}; use crate::net::Shutdown; use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd}; use crate::os::unix::ucred; @@ -556,11 +556,6 @@ impl io::Read for UnixStream { fn is_read_vectored(&self) -> bool { io::Read::is_read_vectored(&&*self) } - - #[inline] - unsafe fn initializer(&self) -> Initializer { - Initializer::nop() - } } impl<'a> io::Read for &'a UnixStream { @@ -576,11 +571,6 @@ impl<'a> io::Read for &'a UnixStream { fn is_read_vectored(&self) -> bool { self.0.is_read_vectored() } - - #[inline] - unsafe fn initializer(&self) -> Initializer { - Initializer::nop() - } } impl io::Write for UnixStream { diff --git a/sgx_tstd/src/os/unix/raw.rs b/sgx_tstd/src/os/unix/raw.rs index 8b094baa8..93de8f8f0 100644 --- a/sgx_tstd/src/os/unix/raw.rs +++ b/sgx_tstd/src/os/unix/raw.rs @@ -17,6 +17,8 @@ //! Unix-specific primitives available on all unix platforms. +#![allow(deprecated)] + #[allow(non_camel_case_types)] pub type uid_t = u32; #[allow(non_camel_case_types)] @@ -25,8 +27,8 @@ pub type gid_t = u32; pub type pid_t = i32; #[doc(inline)] -pub use crate::os::raw::pthread_t; +pub use super::platform::raw::pthread_t; #[doc(inline)] -pub use crate::os::raw::{blkcnt_t, time_t}; +pub use super::platform::raw::{blkcnt_t, time_t}; #[doc(inline)] -pub use crate::os::raw::{blksize_t, dev_t, ino_t, mode_t, nlink_t, off_t}; +pub use super::platform::raw::{blksize_t, dev_t, ino_t, mode_t, nlink_t, off_t}; diff --git a/sgx_tstd/src/os/unix/thread.rs b/sgx_tstd/src/os/unix/thread.rs index 08127d43a..5ac3ed1b5 100644 --- a/sgx_tstd/src/os/unix/thread.rs +++ b/sgx_tstd/src/os/unix/thread.rs @@ -15,7 +15,9 @@ // specific language governing permissions and limitations // under the License.. -//! Unix-specific extensions to primitives in the `std::thread` module. +//! Unix-specific extensions to primitives in the [`std::thread`] module. +//! +//! [`std::thread`]: crate::thread #[allow(deprecated)] use crate::os::unix::raw::pthread_t; diff --git a/sgx_tstd/src/panic.rs b/sgx_tstd/src/panic.rs index 5e0526207..cca723ae0 100644 --- a/sgx_tstd/src/panic.rs +++ b/sgx_tstd/src/panic.rs @@ -20,6 +20,8 @@ use crate::any::Any; use crate::collections; use crate::panicking; +#[cfg(feature = "backtrace")] +use crate::sync::atomic::{AtomicUsize, Ordering}; use crate::sync::{SgxMutex, SgxRwLock}; use crate::thread::Result; @@ -48,6 +50,8 @@ pub use core::panic::panic_2021; pub use crate::panicking::{set_hook, take_hook}; +pub use crate::panicking::update_hook; + pub use core::panic::{Location, PanicInfo}; pub use core::panic::{AssertUnwindSafe, RefUnwindSafe, UnwindSafe}; @@ -199,3 +203,86 @@ pub fn resume_unwind(payload: Box) -> ! { pub fn always_abort() { crate::panicking::panic_count::set_always_abort(); } + +/// The configuration for whether and how the default panic hook will capture +/// and display the backtrace. +#[cfg(feature = "backtrace")] +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +#[non_exhaustive] +pub enum BacktraceStyle { + /// Prints a terser backtrace which ideally only contains relevant + /// information. + Short, + /// Prints a backtrace with all possible information. + Full, + /// Disable collecting and displaying backtraces. + Off, +} + +#[cfg(feature = "backtrace")] +impl BacktraceStyle { + pub(crate) fn full() -> Option { + Some(BacktraceStyle::Full) + } + + fn as_usize(self) -> usize { + match self { + BacktraceStyle::Short => 1, + BacktraceStyle::Full => 2, + BacktraceStyle::Off => 3, + } + } + + fn from_usize(s: usize) -> Option { + Some(match s { + 0 => return None, + 1 => BacktraceStyle::Short, + 2 => BacktraceStyle::Full, + 3 => BacktraceStyle::Off, + _ => unreachable!(), + }) + } +} + +// Tracks whether we should/can capture a backtrace, and how we should display +// that backtrace. +// +// Internally stores equivalent of an Option. +#[cfg(feature = "backtrace")] +static SHOULD_CAPTURE: AtomicUsize = AtomicUsize::new(0); + +/// Configure whether the default panic hook will capture and display a +/// backtrace. +/// +/// The default value for this setting may be set by the `RUST_BACKTRACE` +/// environment variable; see the details in [`get_backtrace_style`]. +#[cfg(feature = "backtrace")] +pub fn set_backtrace_style(style: BacktraceStyle) { + SHOULD_CAPTURE.store(style.as_usize(), Ordering::Release); +} + +/// Checks whether the standard library's panic hook will capture and print a +/// backtrace. +/// +/// This function will, if a backtrace style has not been set via +/// [`set_backtrace_style`], read the environment variable `RUST_BACKTRACE` to +/// determine a default value for the backtrace formatting: +/// +/// The first call to `get_backtrace_style` may read the `RUST_BACKTRACE` +/// environment variable if `set_backtrace_style` has not been called to +/// override the default value. After a call to `set_backtrace_style` or +/// `get_backtrace_style`, any changes to `RUST_BACKTRACE` will have no effect. +/// +/// `RUST_BACKTRACE` is read according to these rules: +/// +/// * `0` for `BacktraceStyle::Off` +/// * `full` for `BacktraceStyle::Full` +/// * `1` for `BacktraceStyle::Short` +/// * Other values are currently `BacktraceStyle::Short`, but this may change in +/// the future +/// +/// Returns `None` if backtraces aren't currently supported. +#[cfg(feature = "backtrace")] +pub fn get_backtrace_style() -> Option { + BacktraceStyle::from_usize(SHOULD_CAPTURE.load(Ordering::Acquire)) +} diff --git a/sgx_tstd/src/panicking.rs b/sgx_tstd/src/panicking.rs index 561a814d2..9df0b3801 100644 --- a/sgx_tstd/src/panicking.rs +++ b/sgx_tstd/src/panicking.rs @@ -24,15 +24,24 @@ //! * Executing a panic up to doing the actual implementation //! * Shims around "try" +#![deny(unsafe_op_in_unsafe_fn)] + +#[cfg(feature = "backtrace")] +use crate::panic::BacktraceStyle; use core::panic::{BoxMeUp, Location, PanicInfo}; use crate::any::Any; use crate::fmt; use crate::intrinsics; use crate::mem::{self, ManuallyDrop}; -use crate::ptr; -use crate::sync::atomic::{AtomicPtr, Ordering}; +#[cfg(feature = "backtrace")] +use crate::sync::atomic::{AtomicBool, Ordering}; +#[cfg(feature = "stdio")] use crate::sys::stdio::panic_output; +#[cfg(feature = "backtrace")] +use crate::sys_common::backtrace; +use crate::sys_common::rwlock::SgxThreadRwLock; +#[cfg(feature = "stdio")] use crate::sys_common::thread_info; use crate::thread; @@ -76,7 +85,20 @@ extern "C" fn __rust_foreign_exception() -> ! { rtabort!("Rust cannot catch foreign exceptions"); } -static PANIC_HANDLER: AtomicPtr<()> = AtomicPtr::new(ptr::null_mut()); +#[derive(Copy, Clone)] +enum Hook { + Default, + Custom(*mut (dyn Fn(&PanicInfo<'_>) + 'static + Sync + Send)), +} + +impl Hook { + fn custom(f: impl Fn(&PanicInfo<'_>) + 'static + Sync + Send) -> Self { + Self::Custom(Box::into_raw(Box::new(f))) + } +} + +static HOOK_LOCK: SgxThreadRwLock = SgxThreadRwLock::new(); +static mut HOOK: Hook = Hook::Default; /// Registers a custom panic hook, replacing any that was previously registered. /// @@ -98,11 +120,43 @@ static PANIC_HANDLER: AtomicPtr<()> = AtomicPtr::new(ptr::null_mut()); /// /// Panics if called from a panicking thread. /// -pub fn set_hook(hook: fn(&PanicInfo<'_>)) { - assert!(!thread::panicking(), "cannot modify the panic hook from a panicking thread"); - PANIC_HANDLER.store(hook as *mut (), Ordering::SeqCst); -} +/// # Examples +/// +/// The following will print "Custom panic hook": +/// +/// ```should_panic +/// use std::panic; +/// +/// panic::set_hook(Box::new(|_| { +/// println!("Custom panic hook"); +/// })); +/// +/// panic!("Normal panic"); +/// ``` +pub fn set_hook(hook: Box) + 'static + Sync + Send>) { + if thread::panicking() { + panic!("cannot modify the panic hook from a panicking thread"); + } + // SAFETY: + // + // - `HOOK` can only be modified while holding write access to `HOOK_LOCK`. + // - The argument of `Box::from_raw` is always a valid pointer that was created using + // `Box::into_raw`. + unsafe { + let _guard = HOOK_LOCK.write(); + let old_hook = HOOK; + HOOK = Hook::Custom(Box::into_raw(hook)); + let _ = HOOK_LOCK.write_unlock(); + + if let Hook::Custom(ptr) = old_hook { + #[allow(unused_must_use)] + { + Box::from_raw(ptr); + } + } + } +} /// Unregisters the current panic hook, returning it. /// @@ -115,29 +169,120 @@ pub fn set_hook(hook: fn(&PanicInfo<'_>)) { /// # Panics /// /// Panics if called from a panicking thread. -/// -pub fn take_hook() -> fn(&PanicInfo<'_>) { - let hook = PANIC_HANDLER.swap(ptr::null_mut(), Ordering::SeqCst); - if hook.is_null() { default_hook } else { unsafe { mem::transmute(hook) } } +/// +/// # Examples +/// +/// The following will print "Normal panic": +/// +/// ```should_panic +/// use std::panic; +/// +/// panic::set_hook(Box::new(|_| { +/// println!("Custom panic hook"); +/// })); +/// +/// let _ = panic::take_hook(); +/// +/// panic!("Normal panic"); +/// ``` +#[must_use] +pub fn take_hook() -> Box) + 'static + Sync + Send> { + if thread::panicking() { + panic!("cannot modify the panic hook from a panicking thread"); + } + + // SAFETY: + // + // - `HOOK` can only be modified while holding write access to `HOOK_LOCK`. + // - The argument of `Box::from_raw` is always a valid pointer that was created using + // `Box::into_raw`. + unsafe { + let _guard = HOOK_LOCK.write(); + let hook = HOOK; + HOOK = Hook::Default; + let _ = HOOK_LOCK.write_unlock(); + + match hook { + Hook::Default => Box::new(default_hook), + Hook::Custom(ptr) => Box::from_raw(ptr), + } + } +} + +/// Atomic combination of [`take_hook`] and [`set_hook`]. Use this to replace the panic handler with +/// a new panic handler that does something and then executes the old handler. +/// +/// [`take_hook`]: ./fn.take_hook.html +/// [`set_hook`]: ./fn.set_hook.html +/// +/// # Panics +/// +/// Panics if called from a panicking thread. +/// +/// # Examples +/// +/// The following will print the custom message, and then the normal output of panic. +/// +/// ```should_panic +/// #![feature(panic_update_hook)] +/// use std::panic; +/// +/// // Equivalent to +/// // let prev = panic::take_hook(); +/// // panic::set_hook(move |info| { +/// // println!("..."); +/// // prev(info); +/// // ); +/// panic::update_hook(move |prev, info| { +/// println!("Print custom message and execute panic handler as usual"); +/// prev(info); +/// }); +/// +/// panic!("Custom and then normal"); +/// ``` +pub fn update_hook(hook_fn: F) +where + F: Fn(&(dyn Fn(&PanicInfo<'_>) + Send + Sync + 'static), &PanicInfo<'_>) + + Sync + + Send + + 'static, +{ + if thread::panicking() { + panic!("cannot modify the panic hook from a panicking thread"); + } + + // SAFETY: + // + // - `HOOK` can only be modified while holding write access to `HOOK_LOCK`. + // - The argument of `Box::from_raw` is always a valid pointer that was created using + // `Box::into_raw`. + unsafe { + let _guard = HOOK_LOCK.write(); + let old_hook = HOOK; + HOOK = Hook::Default; + + let prev = match old_hook { + Hook::Default => Box::new(default_hook), + Hook::Custom(ptr) => Box::from_raw(ptr), + }; + + HOOK = Hook::custom(move |info| hook_fn(&prev, info)); + let _ = HOOK_LOCK.write_unlock(); + } } #[cfg(not(feature = "stdio"))] -#[allow(unused_variables)] -fn default_hook(info: &PanicInfo<'_>) {} +fn default_hook(_info: &PanicInfo<'_>) {} #[cfg(feature = "stdio")] fn default_hook(info: &PanicInfo<'_>) { - #[cfg(feature = "backtrace")] - use crate::sys_common::backtrace::{self, RustBacktrace}; - // If this is a double panic, make sure that we print a backtrace // for this panic. Otherwise only print it if logging is enabled. #[cfg(feature = "backtrace")] - let backtrace_env = if panic_count::get_count() >= 2 { - use crate::sys::backtrace::PrintFmt; - RustBacktrace::Print(PrintFmt::Full) + let backtrace = if panic_count::get_count() >= 2 { + BacktraceStyle::full() } else { - backtrace::rust_backtrace_env() + crate::panic::get_backtrace_style() }; // The current implementation always returns `Some`. @@ -156,14 +301,18 @@ fn default_hook(info: &PanicInfo<'_>) { let write = |err: &mut dyn crate::io::Write| { let _ = writeln!(err, "thread '{}' panicked at '{}', {}", name, msg, location); - #[cfg(feature = "backtrace")] { - use crate::sync::atomic::AtomicBool; + #[cfg(feature = "backtrace")] + { static FIRST_PANIC: AtomicBool = AtomicBool::new(true); - match backtrace_env { - RustBacktrace::Print(format) => drop(backtrace::print(err, format)), - RustBacktrace::Disabled => {} - RustBacktrace::RuntimeDisabled => { + match backtrace { + Some(BacktraceStyle::Short) => { + drop(backtrace::print(err, crate::sys::backtrace::PrintFmt::Short)) + } + Some(BacktraceStyle::Full) => { + drop(backtrace::print(err, crate::sys::backtrace::PrintFmt::Full)) + } + Some(BacktraceStyle::Off) => { if FIRST_PANIC.swap(false, Ordering::SeqCst) { let _ = writeln!( err, @@ -171,6 +320,8 @@ fn default_hook(info: &PanicInfo<'_>) { ); } } + // If backtraces aren't supported, do nothing. + None => {} } } }; @@ -180,13 +331,6 @@ fn default_hook(info: &PanicInfo<'_>) { } } -fn panic_handler(info: &PanicInfo<'_>) { - let hook = PANIC_HANDLER.load(Ordering::SeqCst); - let handler: fn(&PanicInfo<'_>) = - if hook.is_null() { default_hook } else { unsafe { mem::transmute(hook) } }; - handler(info); -} - #[doc(hidden)] pub mod panic_count { use crate::cell::Cell; @@ -318,12 +462,14 @@ pub unsafe fn r#try R>(f: F) -> Result> // The call to `intrinsics::r#try` is made safe by: // - `do_call`, the first argument, can be called with the initial `data_ptr`. // - `do_catch`, the second argument, can be called with the `data_ptr` as well. - // See their safety preconditions for more informations - return if intrinsics::r#try(do_call::, data_ptr, do_catch::) == 0 { - Ok(ManuallyDrop::into_inner(data.r)) - } else { - Err(ManuallyDrop::into_inner(data.p)) - }; + // See their safety preconditions for more information + unsafe { + return if intrinsics::r#try(do_call::, data_ptr, do_catch::) == 0 { + Ok(ManuallyDrop::into_inner(data.r)) + } else { + Err(ManuallyDrop::into_inner(data.p)) + }; + } // We consider unwinding to be rare, so mark this function as cold. However, // do not mark it no-inline -- that decision is best to leave to the @@ -335,7 +481,7 @@ pub unsafe fn r#try R>(f: F) -> Result> // the panic handler `__rust_panic_cleanup`. As such we can only // assume it returns the correct thing for `Box::from_raw` to work // without undefined behavior. - let obj = Box::from_raw(__rust_panic_cleanup(payload)); + let obj = unsafe { Box::from_raw(__rust_panic_cleanup(payload)) }; panic_count::decrease(); obj } @@ -349,7 +495,7 @@ pub unsafe fn r#try R>(f: F) -> Result> // expects normal function pointers. #[inline] fn do_call R, R>(data: *mut u8) { - // SAFETY: this is the responsibilty of the caller, see above. + // SAFETY: this is the responsibility of the caller, see above. unsafe { let data = data as *mut Data; let data = &mut (*data); @@ -371,7 +517,7 @@ pub unsafe fn r#try R>(f: F) -> Result> // expects normal function pointers. #[inline] fn do_catch R, R>(data: *mut u8, payload: *mut u8) { - // SAFETY: this is the responsibilty of the caller, see above. + // SAFETY: this is the responsibility of the caller, see above. // // When `__rustc_panic_cleaner` is correctly implemented we can rely // on `obj` being the correct thing to pass to `data.p` (after wrapping @@ -446,20 +592,32 @@ pub fn begin_panic_handler(info: &PanicInfo<'_>) -> ! { let loc = info.location().unwrap(); // The current implementation always returns Some let msg = info.message().unwrap(); // The current implementation always returns Some - #[cfg(feature = "backtrace")] { + #[cfg(feature = "backtrace")] + { crate::sys_common::backtrace::__rust_end_short_backtrace(move || { if let Some(msg) = msg.as_str() { - rust_panic_with_hook(&mut StrPanicPayload(msg), info.message(), loc); + rust_panic_with_hook(&mut StrPanicPayload(msg), info.message(), loc, info.can_unwind()); } else { - rust_panic_with_hook(&mut PanicPayload::new(msg), info.message(), loc); + rust_panic_with_hook( + &mut PanicPayload::new(msg), + info.message(), + loc, + info.can_unwind(), + ); } }) } - #[cfg(not(feature = "backtrace"))] { + #[cfg(not(feature = "backtrace"))] + { if let Some(msg) = msg.as_str() { - rust_panic_with_hook(&mut StrPanicPayload(msg), info.message(), loc); + rust_panic_with_hook(&mut StrPanicPayload(msg), info.message(), loc, info.can_unwind()); } else { - rust_panic_with_hook(&mut PanicPayload::new(msg), info.message(), loc); + rust_panic_with_hook( + &mut PanicPayload::new(msg), + info.message(), + loc, + info.can_unwind(), + ); } } } @@ -474,7 +632,8 @@ pub fn begin_panic_handler(info: &PanicInfo<'_>) -> ! { #[inline(never)] #[cold] #[track_caller] -pub fn begin_panic(msg: M) -> ! { +#[rustc_do_not_const_check] // hooked by const-eval +pub const fn begin_panic(msg: M) -> ! { struct PanicPayload { inner: Option, } @@ -510,11 +669,11 @@ pub fn begin_panic(msg: M) -> ! { let loc = Location::caller(); #[cfg(feature = "backtrace")] { crate::sys_common::backtrace::__rust_end_short_backtrace(move || { - rust_panic_with_hook(&mut PanicPayload::new(msg), None, loc) + rust_panic_with_hook(&mut PanicPayload::new(msg), None, loc, true) }) } #[cfg(not(feature = "backtrace"))] { - rust_panic_with_hook(&mut PanicPayload::new(msg), None, loc) + rust_panic_with_hook(&mut PanicPayload::new(msg), None, loc, true) } } @@ -527,6 +686,7 @@ fn rust_panic_with_hook( payload: &mut dyn BoxMeUp, message: Option<&fmt::Arguments<'_>>, location: &Location<'_>, + can_unwind: bool, ) -> ! { let (must_abort, panics) = panic_count::increase(); @@ -543,17 +703,37 @@ fn rust_panic_with_hook( } else { // Unfortunately, this does not print a backtrace, because creating // a `Backtrace` will allocate, which we must to avoid here. - let panicinfo = PanicInfo::internal_constructor(message, location); + let panicinfo = PanicInfo::internal_constructor(message, location, can_unwind); rtprintpanic!("{}\npanicked after panic::always_abort(), aborting.\n", panicinfo); } rsgx_abort() } - let mut info = PanicInfo::internal_constructor(message, location); - info.set_payload(payload.get()); - panic_handler(&info); + unsafe { + let mut info = PanicInfo::internal_constructor(message, location, can_unwind); + let _guard = HOOK_LOCK.read(); + match HOOK { + // Some platforms (like wasm) know that printing to stderr won't ever actually + // print anything, and if that's the case we can skip the default + // hook. Since string formatting happens lazily when calling `payload` + // methods, this means we avoid formatting the string at all! + // (The panic runtime might still call `payload.take_box()` though and trigger + // formatting.) + #[cfg(feature = "stdio")] + Hook::Default if panic_output().is_none() => {} + Hook::Default => { + info.set_payload(payload.get()); + default_hook(&info); + } + Hook::Custom(ptr) => { + info.set_payload(payload.get()); + (*ptr)(&info); + } + }; + let _ = HOOK_LOCK.read_unlock(); + } - if panics > 1 { + if panics > 1 || !can_unwind { // If a thread panics while it's already unwinding then we // have limited options. Currently our preference is to // just abort. In the future we may consider resuming diff --git a/sgx_tstd/src/path.rs b/sgx_tstd/src/path.rs index 3b2d6f354..ac7726c4f 100644 --- a/sgx_tstd/src/path.rs +++ b/sgx_tstd/src/path.rs @@ -29,6 +29,13 @@ //! [`PathBuf`]; note that the paths may differ syntactically by the //! normalization described in the documentation for the [`components`] method. //! +//! ## Case sensitivity +//! +//! Unless otherwise indicated path methods that do not access the filesystem, +//! such as [`Path::starts_with`] and [`Path::ends_with`], are case sensitive no +//! matter the platform or filesystem. An exception to this is made for Windows +//! drive letters. +//! //! ## Simple usage //! //! Path manipulation includes both parsing components from slices and building @@ -78,12 +85,12 @@ use crate::borrow::{Borrow, Cow}; use crate::cmp; +use crate::collections::TryReserveError; use crate::error::Error; use crate::fmt; #[cfg(feature = "untrusted_fs")] use crate::fs; use crate::hash::{Hash, Hasher}; -#[cfg(feature = "untrusted_fs")] use crate::io; use crate::iter::{self, FusedIterator}; use crate::ops::{self, Deref}; @@ -92,7 +99,7 @@ use crate::str::FromStr; use crate::sync::Arc; use crate::ffi::{OsStr, OsString}; - +use crate::sys; use crate::sys::path::{is_sep_byte, is_verbatim_sep, parse_prefix, MAIN_SEP_STR}; //////////////////////////////////////////////////////////////////////////////// @@ -132,6 +139,18 @@ use crate::sys::path::{is_sep_byte, is_verbatim_sep, parse_prefix, MAIN_SEP_STR} /// } /// } /// +/// # if cfg!(windows) { +/// assert_eq!(Verbatim(OsStr::new("pictures")), +/// get_path_prefix(r"\\?\pictures\kittens")); +/// assert_eq!(VerbatimUNC(OsStr::new("server"), OsStr::new("share")), +/// get_path_prefix(r"\\?\UNC\server\share")); +/// assert_eq!(VerbatimDisk(b'C'), get_path_prefix(r"\\?\c:\")); +/// assert_eq!(DeviceNS(OsStr::new("BrainInterface")), +/// get_path_prefix(r"\\.\BrainInterface")); +/// assert_eq!(UNC(OsStr::new("server"), OsStr::new("share")), +/// get_path_prefix(r"\\server\share")); +/// assert_eq!(Disk(b'C'), get_path_prefix(r"C:\Users\Rust\Pictures\Ferris")); +/// # } /// ``` #[derive(Copy, Clone, Debug, Hash, PartialOrd, Ord, PartialEq, Eq)] pub enum Prefix<'a> { @@ -247,6 +266,11 @@ pub fn is_separator(c: char) -> bool { /// For example, `/` on Unix and `\` on Windows. pub const MAIN_SEPARATOR: char = crate::sys::path::MAIN_SEP; +/// The primary separator of path components for the current platform. +/// +/// For example, `/` on Unix and `\` on Windows. +pub const MAIN_SEPARATOR_STR: &str = crate::sys::path::MAIN_SEP_STR; + //////////////////////////////////////////////////////////////////////////////// // Misc helpers //////////////////////////////////////////////////////////////////////////////// @@ -929,6 +953,25 @@ impl FusedIterator for Components<'_> {} impl<'a> cmp::PartialEq for Components<'a> { #[inline] fn eq(&self, other: &Components<'a>) -> bool { + let Components { path: _, front: _, back: _, has_physical_root: _, prefix: _ } = self; + + // Fast path for exact matches, e.g. for hashmap lookups. + // Don't explicitly compare the prefix or has_physical_root fields since they'll + // either be covered by the `path` buffer or are only relevant for `prefix_verbatim()`. + if self.path.len() == other.path.len() + && self.front == other.front + && self.back == State::Body + && other.back == State::Body + && self.prefix_verbatim() == other.prefix_verbatim() + { + // possible future improvement: this could bail out earlier if there were a + // reverse memcmp/bcmp comparing back to front + if self.path == other.path { + return true; + } + } + + // compare back to front since absolute paths often share long prefixes Iterator::eq(self.clone().rev(), other.clone().rev()) } } @@ -960,13 +1003,12 @@ fn compare_components(mut left: Components<'_>, mut right: Components<'_>) -> cm // The fast path isn't taken for paths with a PrefixComponent to avoid backtracking into // the middle of one if left.prefix.is_none() && right.prefix.is_none() && left.front == right.front { - // this might benefit from a [u8]::first_mismatch simd implementation, if it existed - let first_difference = - match left.path.iter().zip(right.path.iter()).position(|(&a, &b)| a != b) { - None if left.path.len() == right.path.len() => return cmp::Ordering::Equal, - None => left.path.len().min(right.path.len()), - Some(diff) => diff, - }; + // possible future improvement: a [u8]::first_mismatch simd implementation + let first_difference = match left.path.iter().zip(right.path).position(|(&a, &b)| a != b) { + None if left.path.len() == right.path.len() => return cmp::Ordering::Equal, + None => left.path.len().min(right.path.len()), + Some(diff) => diff, + }; if let Some(previous_sep) = left.path[..first_difference].iter().rposition(|&b| left.is_sep_byte(b)) @@ -1420,6 +1462,14 @@ impl PathBuf { self.inner.reserve(additional) } + /// Invokes [`try_reserve`] on the underlying instance of [`OsString`]. + /// + /// [`try_reserve`]: OsString::try_reserve + #[inline] + pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { + self.inner.try_reserve(additional) + } + /// Invokes [`reserve_exact`] on the underlying instance of [`OsString`]. /// /// [`reserve_exact`]: OsString::reserve_exact @@ -1428,6 +1478,14 @@ impl PathBuf { self.inner.reserve_exact(additional) } + /// Invokes [`try_reserve_exact`] on the underlying instance of [`OsString`]. + /// + /// [`try_reserve_exact`]: OsString::try_reserve_exact + #[inline] + pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> { + self.inner.try_reserve_exact(additional) + } + /// Invokes [`shrink_to_fit`] on the underlying instance of [`OsString`]. /// /// [`shrink_to_fit`]: OsString::shrink_to_fit @@ -1482,7 +1540,7 @@ impl From> for Box { } impl From> for PathBuf { - /// Converts a `Box` into a `PathBuf` + /// Converts a [Box]<[Path]> into a [`PathBuf`]. /// /// This conversion does not allocate or copy memory. #[inline] @@ -1492,7 +1550,7 @@ impl From> for PathBuf { } impl From for Box { - /// Converts a `PathBuf` into a `Box` + /// Converts a [`PathBuf`] into a [Box]<[Path]>. /// /// This conversion currently should not allocate memory, /// but this behavior is not guaranteed on all platforms or in all future versions. @@ -1510,7 +1568,7 @@ impl Clone for Box { } impl> From<&T> for PathBuf { - /// Converts a borrowed `OsStr` to a `PathBuf`. + /// Converts a borrowed [`OsStr`] to a [`PathBuf`]. /// /// Allocates a [`PathBuf`] and copies the data into it. #[inline] @@ -1649,7 +1707,8 @@ impl<'a> From> for PathBuf { } impl From for Arc { - /// Converts a [`PathBuf`] into an [`Arc`] by moving the [`PathBuf`] data into a new [`Arc`] buffer. + /// Converts a [`PathBuf`] into an [Arc]<[Path]> by moving the [`PathBuf`] data + /// into a new [`Arc`] buffer. #[inline] fn from(s: PathBuf) -> Arc { let arc: Arc = Arc::from(s.into_os_string()); @@ -1667,7 +1726,8 @@ impl From<&Path> for Arc { } impl From for Rc { - /// Converts a [`PathBuf`] into an [`Rc`] by moving the [`PathBuf`] data into a new `Rc` buffer. + /// Converts a [`PathBuf`] into an [Rc]<[Path]> by moving the [`PathBuf`] data into + /// a new [`Rc`] buffer. #[inline] fn from(s: PathBuf) -> Rc { let rc: Rc = Rc::from(s.into_os_string()); @@ -1676,7 +1736,7 @@ impl From for Rc { } impl From<&Path> for Rc { - /// Converts a [`Path`] into an [`Rc`] by copying the [`Path`] data into a new `Rc` buffer. + /// Converts a [`Path`] into an [`Rc`] by copying the [`Path`] data into a new [`Rc`] buffer. #[inline] fn from(s: &Path) -> Rc { let rc: Rc = Rc::from(s.as_os_str()); @@ -2551,7 +2611,7 @@ impl Path { /// This function will traverse symbolic links to query information about the /// destination file. In case of broken symbolic links this will return `Ok(false)`. /// - /// As opposed to the `exists()` method, this one doesn't silently ignore errors + /// As opposed to the [`exists()`] method, this one doesn't silently ignore errors /// unrelated to the path not existing. (E.g. it will return `Err(_)` in case of permission /// denied on some of the parent directories.) /// @@ -2564,6 +2624,8 @@ impl Path { /// assert!(!Path::new("does_not_exist.txt").try_exists().expect("Can't check existence of file does_not_exist.txt")); /// assert!(Path::new("/root/secret_file.txt").try_exists().is_err()); /// ``` + /// + /// [`exists()`]: Self::exists // FIXME: stabilization should modify documentation of `exists()` to recommend this method // instead. #[cfg(feature = "untrusted_fs")] @@ -2644,12 +2706,11 @@ impl Path { /// #[cfg_attr(unix, doc = "```no_run")] #[cfg_attr(not(unix), doc = "```ignore")] - /// #![feature(is_symlink)] /// use std::path::Path; /// use std::os::unix::fs::symlink; /// /// let link_path = Path::new("link"); - /// symlink("/origin_does_not_exists/", link_path).unwrap(); + /// symlink("/origin_does_not_exist/", link_path).unwrap(); /// assert_eq!(link_path.is_symlink(), true); /// assert_eq!(link_path.exists(), false); /// ``` @@ -2733,9 +2794,51 @@ impl cmp::PartialEq for Path { impl Hash for Path { fn hash(&self, h: &mut H) { - for component in self.components() { - component.hash(h); + let bytes = self.as_u8_slice(); + let (prefix_len, verbatim) = match parse_prefix(&self.inner) { + Some(prefix) => { + prefix.hash(h); + (prefix.len(), prefix.is_verbatim()) + } + None => (0, false), + }; + let bytes = &bytes[prefix_len..]; + + let mut component_start = 0; + let mut bytes_hashed = 0; + + for i in 0..bytes.len() { + let is_sep = if verbatim { is_verbatim_sep(bytes[i]) } else { is_sep_byte(bytes[i]) }; + if is_sep { + if i > component_start { + let to_hash = &bytes[component_start..i]; + h.write(to_hash); + bytes_hashed += to_hash.len(); + } + + // skip over separator and optionally a following CurDir item + // since components() would normalize these away. + component_start = i + 1; + + let tail = &bytes[component_start..]; + + if !verbatim { + component_start += match tail { + [b'.'] => 1, + [b'.', sep, ..] if is_sep_byte(*sep) => 1, + _ => 0, + }; + } + } + } + + if component_start < bytes.len() { + let to_hash = &bytes[component_start..]; + h.write(to_hash); + bytes_hashed += to_hash.len(); } + + h.write_usize(bytes_hashed); } } @@ -2920,3 +3023,83 @@ impl Error for StripPrefixError { "prefix not found" } } + +/// Makes the path absolute without accessing the filesystem. +/// +/// If the path is relative, the current directory is used as the base directory. +/// All intermediate components will be resolved according to platforms-specific +/// rules but unlike [`canonicalize`][crate::fs::canonicalize] this does not +/// resolve symlinks and may succeed even if the path does not exist. +/// +/// If the `path` is empty or getting the +/// [current directory][crate::env::current_dir] fails then an error will be +/// returned. +/// +/// # Examples +/// +/// ## Posix paths +/// +/// ``` +/// #![feature(absolute_path)] +/// # #[cfg(unix)] +/// fn main() -> std::io::Result<()> { +/// use std::path::{self, Path}; +/// +/// // Relative to absolute +/// let absolute = path::absolute("foo/./bar")?; +/// assert!(absolute.ends_with("foo/bar")); +/// +/// // Absolute to absolute +/// let absolute = path::absolute("/foo//test/.././bar.rs")?; +/// assert_eq!(absolute, Path::new("/foo/test/../bar.rs")); +/// Ok(()) +/// } +/// # #[cfg(not(unix))] +/// # fn main() {} +/// ``` +/// +/// The path is resolved using [POSIX semantics][posix-semantics] except that +/// it stops short of resolving symlinks. This means it will keep `..` +/// components and trailing slashes. +/// +/// ## Windows paths +/// +/// ``` +/// #![feature(absolute_path)] +/// # #[cfg(windows)] +/// fn main() -> std::io::Result<()> { +/// use std::path::{self, Path}; +/// +/// // Relative to absolute +/// let absolute = path::absolute("foo/./bar")?; +/// assert!(absolute.ends_with(r"foo\bar")); +/// +/// // Absolute to absolute +/// let absolute = path::absolute(r"C:\foo//test\..\./bar.rs")?; +/// +/// assert_eq!(absolute, Path::new(r"C:\foo\bar.rs")); +/// Ok(()) +/// } +/// # #[cfg(not(windows))] +/// # fn main() {} +/// ``` +/// +/// For verbatim paths this will simply return the path as given. For other +/// paths this is currently equivalent to calling [`GetFullPathNameW`][windows-path] +/// This may change in the future. +/// +/// [posix-semantics]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_13 +/// [windows-path]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfullpathnamew +#[cfg(feature = "untrusted_fs")] +pub fn absolute>(path: P) -> io::Result { + _absolute(path) +} + +pub(crate) fn _absolute>(path: P) -> io::Result { + let path = path.as_ref(); + if path.as_os_str().is_empty() { + Err(io::const_io_error!(io::ErrorKind::InvalidInput, "cannot make an empty path absolute",)) + } else { + sys::path::absolute(path) + } +} diff --git a/sgx_tstd/src/prelude/v1.rs b/sgx_tstd/src/prelude/v1.rs index 3ac7da018..756a2c2e8 100644 --- a/sgx_tstd/src/prelude/v1.rs +++ b/sgx_tstd/src/prelude/v1.rs @@ -46,25 +46,23 @@ pub use crate::result::Result::{self, Err, Ok}; #[doc(no_inline)] pub use core::prelude::v1::{ assert, cfg, column, compile_error, concat, concat_idents, env, file, format_args, - format_args_nl, include, include_bytes, include_str, line, llvm_asm, log_syntax, module_path, - option_env, stringify, trace_macros, Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, - PartialOrd, + format_args_nl, include, include_bytes, include_str, line, log_syntax, module_path, option_env, + stringify, trace_macros, Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd, }; -// FIXME: Attribute and internal derive macros are not documented because for them rustdoc generates -// dead links which fail link checker testing. -#[allow(deprecated, deprecated_in_future)] -#[doc(hidden)] -pub use core::prelude::v1::{ - global_allocator, test, test_case, RustcDecodable, RustcEncodable, -}; +#[doc(no_inline)] +pub use core::prelude::v1::concat_bytes; + +#[allow(deprecated)] +pub use core::prelude::v1::{RustcDecodable, RustcEncodable}; + +// Do not `doc(no_inline)` so that they become doc items on their own +// (no public module for them to be re-exported from). +pub use core::prelude::v1::{derive, global_allocator, test, test_case}; -#[doc(hidden)] -pub use core::prelude::v1::derive; -#[doc(hidden)] +// Do not `doc(no_inline)` either. pub use core::prelude::v1::cfg_accessible; -#[doc(hidden)] pub use core::prelude::v1::cfg_eval; // The file so far is equivalent to src/libcore/prelude/v1.rs, diff --git a/sgx_tstd/src/rt.rs b/sgx_tstd/src/rt.rs index cebae7842..3104350e3 100644 --- a/sgx_tstd/src/rt.rs +++ b/sgx_tstd/src/rt.rs @@ -37,6 +37,7 @@ pub use core::panicking::{panic_display, panic_fmt}; // - the standard error output // - some dedicated platform specific output // - nothing (so this macro is a no-op) +#[cfg(feature = "stdio")] macro_rules! rtprintpanic { ($($t:tt)*) => { if let Some(mut out) = crate::sys::stdio::panic_output() { @@ -45,6 +46,13 @@ macro_rules! rtprintpanic { } } +#[cfg(not(feature = "stdio"))] +macro_rules! rtprintpanic { + ($($t:tt)*) => { + format_args!($($t)*); + } +} + macro_rules! rtabort { ($($t:tt)*) => { { @@ -118,7 +126,7 @@ global_dtors_object! { // One-time runtime cleanup. // NOTE: this is not guaranteed to run, for example when the program aborts. -fn cleanup() { +pub (crate) fn cleanup() { static CLEANUP: Once = Once::new(); CLEANUP.call_once(|| { // Flush stdout and disable buffering. diff --git a/sgx_tstd/src/sgxfs.rs b/sgx_tstd/src/sgxfs.rs index ffacfad1c..2a702c067 100644 --- a/sgx_tstd/src/sgxfs.rs +++ b/sgx_tstd/src/sgxfs.rs @@ -17,7 +17,7 @@ //! Filesystem manipulation operations. -use crate::io::{self, SeekFrom, Seek, Read, Initializer, Write}; +use crate::io::{self, SeekFrom, Seek, Read, Write}; use crate::path::Path; use crate::sys::sgxfs as fs_imp; use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner}; @@ -157,11 +157,6 @@ impl Read for SgxFile { fn read(&mut self, buf: &mut [u8]) -> io::Result { self.inner.read(buf) } - - #[inline] - unsafe fn initializer(&self) -> Initializer { - Initializer::nop() - } } impl Write for SgxFile { @@ -181,11 +176,6 @@ impl<'a> Read for &'a SgxFile { fn read(&mut self, buf: &mut [u8]) -> io::Result { self.inner.read(buf) } - - #[inline] - unsafe fn initializer(&self) -> Initializer { - Initializer::nop() - } } impl<'a> Write for &'a SgxFile { diff --git a/sgx_tstd/src/sync/mpsc/mod.rs b/sgx_tstd/src/sync/mpsc/mod.rs index 805deb160..55fd9a09c 100644 --- a/sgx_tstd/src/sync/mpsc/mod.rs +++ b/sgx_tstd/src/sync/mpsc/mod.rs @@ -435,12 +435,13 @@ pub struct TryIter<'a, T: 'a> { } /// An owning iterator over messages on a [`Receiver`], -/// created by **Receiver::into_iter**. +/// created by [`into_iter`]. /// /// This iterator will block whenever [`next`] /// is called, waiting for a new message, and [`None`] will be /// returned if the corresponding channel has hung up. /// +/// [`into_iter`]: Receiver::into_iter /// [`next`]: Iterator::next /// /// # Examples diff --git a/sgx_tstd/src/sync/mutex.rs b/sgx_tstd/src/sync/mutex.rs index 0bba39cc7..6cbf87abd 100644 --- a/sgx_tstd/src/sync/mutex.rs +++ b/sgx_tstd/src/sync/mutex.rs @@ -213,6 +213,9 @@ unsafe impl Sync for SgxMutex {} /// [`lock`]: Mutex::lock /// [`try_lock`]: Mutex::try_lock #[must_use = "if unused the Mutex will immediately unlock"] +#[must_not_suspend = "holding a MutexGuard across suspend \ + points can cause deadlocks, delays, \ + and cause Futures to not implement `Send`"] pub struct SgxMutexGuard<'a, T: ?Sized + 'a> { lock: &'a SgxMutex, poison: poison::Guard, diff --git a/sgx_tstd/src/sync/once.rs b/sgx_tstd/src/sync/once.rs index 262dc8137..999b47d54 100644 --- a/sgx_tstd/src/sync/once.rs +++ b/sgx_tstd/src/sync/once.rs @@ -104,6 +104,7 @@ use crate::cell::Cell; use crate::fmt; use crate::marker; +use crate::panic::{RefUnwindSafe, UnwindSafe}; use crate::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; use crate::thread::{self, SgxThread as Thread}; @@ -134,6 +135,10 @@ pub struct Once { unsafe impl Sync for Once {} unsafe impl Send for Once {} +impl UnwindSafe for Once {} + +impl RefUnwindSafe for Once {} + /// State yielded to [`Once::call_once_force()`]’s closure parameter. The state /// can be used to query the poison status of the [`Once`]. #[derive(Debug)] diff --git a/sgx_tstd/src/sync/remutex.bak.rs b/sgx_tstd/src/sync/remutex.bak.rs deleted file mode 100644 index 6e2aafbe6..000000000 --- a/sgx_tstd/src/sync/remutex.bak.rs +++ /dev/null @@ -1,186 +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.. - - -use alloc_crate::boxed::Box; -use core::fmt; -use core::ops::Deref; -use crate::sys_common::poison::{self, LockResult, TryLockError, TryLockResult}; -use crate::sys_common::remutex as sys; - -pub use crate::sys_common::remutex::SgxReentrantThreadMutex; - - -/// A re-entrant mutual exclusion -/// -/// This mutex will block *other* threads waiting for the lock to become -/// available. The thread which has already locked the mutex can lock it -/// multiple times without blocking, preventing a common source of deadlocks. -pub struct SgxReentrantMutex { - inner: Box, - poison: poison::Flag, - data: T, -} - -unsafe impl Send for SgxReentrantMutex {} -unsafe impl Sync for SgxReentrantMutex {} - -impl SgxReentrantMutex { - /// Creates a new reentrant mutex in an unlocked state. - pub fn new(t: T) -> SgxReentrantMutex { - SgxReentrantMutex{ - inner: Box::new(sys::SgxReentrantThreadMutex::new()), - poison: poison::Flag::new(), - data: t, - } - } - - /// Acquires a mutex, blocking the current thread until it is able to do so. - /// - /// This function will block the caller until it is available to acquire the mutex. - /// Upon returning, the thread is the only thread with the mutex held. When the thread - /// calling this method already holds the lock, the call shall succeed without - /// blocking. - /// - /// # Errors - /// - /// If another user of this mutex panicked while holding the mutex, then - /// this call will return failure if the mutex would otherwise be - /// acquired. - pub fn lock(&self) -> LockResult> { - unsafe { - self.inner.lock(); - SgxReentrantMutexGuard::new(self) - } - } - - /// Attempts to acquire this lock. - /// - /// If the lock could not be acquired at this time, then `Err` is returned. - /// Otherwise, an RAII guard is returned. - /// - /// This function does not block. - /// - /// # Errors - /// - /// If another user of this mutex panicked while holding the mutex, then - /// this call will return failure if the mutex would otherwise be - /// acquired. - pub fn try_lock(&self) -> TryLockResult> { - unsafe { - match self.inner.try_lock() { - Ok(_) => Ok(SgxReentrantMutexGuard::new(self)?), - Err(_) => Err(TryLockError::WouldBlock), - } - } - } -} - -impl Drop for SgxReentrantMutex { - fn drop(&mut self) { - // This is actually safe b/c we know that there is no further usage of - // this mutex (it's up to the user to arrange for a mutex to get - // dropped, that's not our job) - let result = unsafe { self.inner.destroy() }; - debug_assert_eq!(result, Ok(()), "Error when destroy an SgxReentrantMutex: {}", result.unwrap_err()); - } -} - -impl fmt::Debug for SgxReentrantMutex { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.try_lock() { - Ok(guard) => f.debug_struct("SgxReentrantMutex").field("data", &*guard).finish(), - Err(TryLockError::Poisoned(err)) => { - f.debug_struct("SgxReentrantMutex").field("data", &**err.get_ref()).finish() - }, - Err(TryLockError::WouldBlock) => { - struct LockedPlaceholder; - impl fmt::Debug for LockedPlaceholder { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str("") - } - } - - f.debug_struct("SgxReentrantMutex").field("data", &LockedPlaceholder).finish() - } - } - } -} - -/// An RAII implementation of a "scoped lock" of a mutex. When this structure is -/// dropped (falls out of scope), the lock will be unlocked. -/// -/// The data protected by the mutex can be accessed through this guard via its -/// Deref implementation. -/// -/// # Mutability -/// -/// Unlike `MutexGuard`, `ReentrantMutexGuard` does not implement `DerefMut`, -/// because implementation of the trait would violate Rust’s reference aliasing -/// rules. Use interior mutability (usually `RefCell`) in order to mutate the -/// guarded data. -#[must_use] -pub struct SgxReentrantMutexGuard<'a, T: 'a> { - // funny underscores due to how Deref currently works (it disregards field - // privacy). - lock: &'a SgxReentrantMutex, - poison: poison::Guard, -} - -impl !Send for SgxReentrantMutexGuard<'_, T> {} - -impl<'mutex, T> SgxReentrantMutexGuard<'mutex, T> { - fn new(lock: &'mutex SgxReentrantMutex) -> LockResult> { - poison::map_result(lock.poison.borrow(), |guard| { - SgxReentrantMutexGuard { - lock: lock, - poison: guard, - } - }) - } -} - -impl Deref for SgxReentrantMutexGuard<'_, T> { - type Target = T; - - fn deref(&self) -> &T { - &self.lock.data - } -} - -impl Drop for SgxReentrantMutexGuard<'_, T> { - #[inline] - fn drop(&mut self) { - let result = unsafe { - self.lock.poison.done(&self.poison); - self.lock.inner.unlock() - }; - debug_assert_eq!(result, Ok(()), "Error when unlocking an SgxReentrantMutex: {}", result.unwrap_err()); - } -} - -impl fmt::Debug for SgxReentrantMutexGuard<'_, T> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Debug::fmt(&**self, f) - } -} - -impl fmt::Display for SgxReentrantMutexGuard<'_, T> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - (**self).fmt(f) - } -} diff --git a/sgx_tstd/src/sys/backtrace/mod.rs b/sgx_tstd/src/sys/backtrace/mod.rs index 9e6dc805b..f26ea11b7 100644 --- a/sgx_tstd/src/sys/backtrace/mod.rs +++ b/sgx_tstd/src/sys/backtrace/mod.rs @@ -138,7 +138,7 @@ pub mod gnu { pub fn get_enclave_filename() -> io::Result> { let p = enclave::get_enclave_path(); let result = match p { - None => Err(Error::new(ErrorKind::Other, "Not implemented")), + None => Err(Error::new(ErrorKind::Other, "no enclave path found")), Some(path) => { let cstr = CString::new(path.as_os_str().as_bytes())?; let v = unsafe { mem::transmute(cstr.into_bytes_with_nul()) }; diff --git a/sgx_tstd/src/sys/fd.rs b/sgx_tstd/src/sys/fd.rs index cac613562..f38a9e410 100644 --- a/sgx_tstd/src/sys/fd.rs +++ b/sgx_tstd/src/sys/fd.rs @@ -16,7 +16,7 @@ // under the License.. use crate::cmp; -use crate::io::{self, Initializer, IoSlice, IoSliceMut, Read}; +use crate::io::{self, IoSlice, IoSliceMut, Read, ReadBuf}; use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd}; use crate::sys::cvt; use crate::sys_common::{AsInner, FromInner, IntoInner}; @@ -66,27 +66,36 @@ impl FileDesc { } pub fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result { - unsafe fn cvt_pread64( - fd: c_int, - buf: *mut c_void, - count: usize, - offset: i64, - ) -> io::Result { - use libc::pread64; - cvt(pread64(fd, buf, count, offset)) - } + use libc::pread64; unsafe { - cvt_pread64( + cvt(pread64( self.as_raw_fd(), buf.as_mut_ptr() as *mut c_void, cmp::min(buf.len(), READ_LIMIT), offset as i64, - ) + )) .map(|n| n as usize) } } + pub fn read_buf(&self, buf: &mut ReadBuf<'_>) -> io::Result<()> { + let ret = cvt(unsafe { + libc::read( + self.as_raw_fd(), + buf.unfilled_mut().as_mut_ptr() as *mut c_void, + cmp::min(buf.remaining(), READ_LIMIT), + ) + })?; + + // Safety: `ret` bytes were written to the initialized portion of the buffer + unsafe { + buf.assume_init(ret as usize); + } + buf.add_filled(ret as usize); + Ok(()) + } + pub fn write(&self, buf: &[u8]) -> io::Result { let ret = cvt(unsafe { libc::write( @@ -115,23 +124,15 @@ impl FileDesc { } pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result { - unsafe fn cvt_pwrite64( - fd: c_int, - buf: *const c_void, - count: usize, - offset: i64, - ) -> io::Result { - use libc::pwrite64; - cvt(pwrite64(fd, buf, count, offset)) - } + use libc::pwrite64; unsafe { - cvt_pwrite64( + cvt(pwrite64( self.as_raw_fd(), buf.as_ptr() as *const c_void, cmp::min(buf.len(), READ_LIMIT), offset as i64, - ) + )) .map(|n| n as usize) } } @@ -159,12 +160,9 @@ impl FileDesc { } } + #[inline] pub fn duplicate(&self) -> io::Result { - // We want to atomically duplicate this file descriptor and set the - // CLOEXEC flag, and currently that's done via F_DUPFD_CLOEXEC. This - // is a POSIX flag that was added to Linux in 2.6.24. - let fd = cvt(unsafe { libc::fcntl_arg1(self.as_raw_fd(), libc::F_DUPFD_CLOEXEC, 0) })?; - Ok(unsafe { FileDesc::from_raw_fd(fd) }) + Ok(Self(self.0.try_clone()?)) } } @@ -172,11 +170,6 @@ impl<'a> Read for &'a FileDesc { fn read(&mut self, buf: &mut [u8]) -> io::Result { (**self).read(buf) } - - #[inline] - unsafe fn initializer(&self) -> Initializer { - Initializer::nop() - } } impl AsInner for FileDesc { diff --git a/sgx_tstd/src/sys/fs.rs b/sgx_tstd/src/sys/fs.rs index 3e8daf3f7..bcebf727e 100644 --- a/sgx_tstd/src/sys/fs.rs +++ b/sgx_tstd/src/sys/fs.rs @@ -19,7 +19,7 @@ use crate::os::unix::prelude::*; use crate::ffi::{CStr, CString, OsStr, OsString}; use crate::fmt; -use crate::io::{self, Error, IoSlice, IoSliceMut, SeekFrom}; +use crate::io::{self, Error, IoSlice, IoSliceMut, ReadBuf, SeekFrom}; use crate::mem; use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd}; use crate::path::{Path, PathBuf}; @@ -29,11 +29,10 @@ use crate::sys::fd::FileDesc; use crate::sys::time::SystemTime; use crate::sys::{cvt, cvt_r}; use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner}; -use crate::untrusted::fs; -use sgx_libc::{c_int, dirent64, mode_t, off64_t, stat64}; +use sgx_libc::{c_int, dirent64, mode_t, off64_t, stat64, time_t}; -pub use crate::sys_common::fs::{remove_dir_all, try_exists}; +pub use crate::sys_common::fs::try_exists; pub struct File(FileDesc); @@ -115,22 +114,22 @@ impl FileAttr { impl FileAttr { pub fn modified(&self) -> io::Result { Ok(SystemTime::from(libc::timespec { - tv_sec: self.stat.st_mtime as libc::time_t, + tv_sec: self.stat.st_mtime as time_t, tv_nsec: self.stat.st_mtime_nsec as _, })) } pub fn accessed(&self) -> io::Result { Ok(SystemTime::from(libc::timespec { - tv_sec: self.stat.st_atime as libc::time_t, + tv_sec: self.stat.st_atime as time_t, tv_nsec: self.stat.st_atime_nsec as _, })) } pub fn created(&self) -> io::Result { - Err(io::Error::new_const( + Err(io::const_io_error!( io::ErrorKind::Unsupported, - &"creation time is not available on this platform \ + "creation time is not available on this platform \ currently", )) } @@ -235,16 +234,16 @@ impl Drop for Dir { impl DirEntry { pub fn path(&self) -> PathBuf { - self.dir.root.join(OsStr::from_bytes(self.name_bytes())) + self.dir.root.join(self.file_name_os_str()) } pub fn file_name(&self) -> OsString { - OsStr::from_bytes(self.name_bytes()).to_os_string() + self.file_name_os_str().to_os_string() } pub fn metadata(&self) -> io::Result { let fd = cvt(unsafe { libc::dirfd(self.dir.dirp.0) })?; - let name = self.entry.d_name.as_ptr(); + let name = self.name_cstr().as_ptr(); let mut stat: stat64 = unsafe { mem::zeroed() }; cvt(unsafe { libc::fstatat64(fd, name, &mut stat, libc::AT_SYMLINK_NOFOLLOW) })?; Ok(FileAttr::from_stat64(stat)) @@ -259,7 +258,7 @@ impl DirEntry { libc::DT_SOCK => Ok(FileType { mode: libc::S_IFSOCK }), libc::DT_DIR => Ok(FileType { mode: libc::S_IFDIR }), libc::DT_BLK => Ok(FileType { mode: libc::S_IFBLK }), - _ => lstat(&self.path()).map(|m| m.file_type()), + _ => self.metadata().map(|m| m.file_type()), } } @@ -271,6 +270,10 @@ impl DirEntry { unsafe { CStr::from_ptr(self.entry.d_name.as_ptr()).to_bytes() } } + fn name_cstr(&self) -> &CStr { + unsafe { CStr::from_ptr(self.entry.d_name.as_ptr()) } + } + pub fn file_name_os_str(&self) -> &OsStr { OsStr::from_bytes(self.name_bytes()) } @@ -401,7 +404,7 @@ impl File { pub fn truncate(&self, size: u64) -> io::Result<()> { use crate::convert::TryInto; let size: off64_t = - size.try_into().map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))?; + size.try_into().map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))?; cvt_r(|| unsafe { libc::ftruncate64(self.as_raw_fd(), size) }).map(drop) } @@ -422,6 +425,10 @@ impl File { self.0.read_at(buf, offset) } + pub fn read_buf(&self, buf: &mut ReadBuf<'_>) -> io::Result<()> { + self.0.read_buf(buf) + } + pub fn write(&self, buf: &[u8]) -> io::Result { self.0.write(buf) } @@ -577,7 +584,10 @@ pub fn readdir(p: &Path) -> io::Result { Err(Error::last_os_error()) } else { let inner = InnerReadDir { dirp: Dir(ptr), root }; - Ok(ReadDir { inner: Arc::new(inner), end_of_stream: false }) + Ok(ReadDir { + inner: Arc::new(inner), + end_of_stream: false, + }) } } } @@ -676,7 +686,7 @@ pub fn canonicalize(p: &Path) -> io::Result { Ok(PathBuf::from(OsString::from_vec(buf))) } -fn open_from(from: &Path) -> io::Result<(fs::File, fs::Metadata)> { +fn open_from(from: &Path) -> io::Result<(crate::fs::File, crate::fs::Metadata)> { use crate::untrusted::fs::File; use crate::sys_common::fs::NOT_FILE_ERROR; @@ -690,10 +700,12 @@ fn open_from(from: &Path) -> io::Result<(fs::File, fs::Metadata)> { fn open_to_and_set_permissions( to: &Path, - reader_metadata: fs::Metadata, -) -> io::Result<(fs::File, fs::Metadata)> { + reader_metadata: crate::fs::Metadata, +) -> io::Result<(crate::fs::File, crate::fs::Metadata)> { + use crate::fs::OpenOptions; + let perm = reader_metadata.permissions(); - let writer = fs::OpenOptions::new() + let writer = OpenOptions::new() // create the file with the correct mode right away .mode(perm.mode()) .write(true) @@ -717,6 +729,18 @@ pub fn copy(from: &Path, to: &Path) -> io::Result { io::copy::copy(&mut reader, &mut writer) } +pub fn chown(_path: &Path, _uid: u32, _gid: u32) -> io::Result<()> { + super::unsupported::unsupported() +} + +pub fn fchown(_fd: c_int, _uid: u32, _gid: u32) -> io::Result<()> { + super::unsupported::unsupported() +} + +pub fn lchown(_path: &Path, _uid: u32, _gid: u32) -> io::Result<()> { + super::unsupported::unsupported() +} + pub fn chroot(_dir: &Path) -> io::Result<()> { super::unsupported::unsupported() } @@ -729,3 +753,113 @@ mod libc { }; pub use sgx_libc::*; } + +pub use remove_dir_impl::remove_dir_all; + +mod remove_dir_impl { + use super::{cstr, lstat, Dir, DirEntry, InnerReadDir, ReadDir}; + use crate::ffi::CStr; + use crate::io; + use crate::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd}; + use crate::os::unix::prelude::{OwnedFd, RawFd}; + use crate::path::{Path, PathBuf}; + use crate::sync::Arc; + use crate::sys::{cvt, cvt_r}; + use libc::{fdopendir, openat, unlinkat}; + + pub fn openat_nofollow_dironly(parent_fd: Option, p: &CStr) -> io::Result { + let fd = cvt_r(|| unsafe { + openat( + parent_fd.unwrap_or(libc::AT_FDCWD), + p.as_ptr(), + libc::O_CLOEXEC | libc::O_RDONLY | libc::O_NOFOLLOW | libc::O_DIRECTORY, + ) + })?; + Ok(unsafe { OwnedFd::from_raw_fd(fd) }) + } + + fn fdreaddir(dir_fd: OwnedFd) -> io::Result<(ReadDir, RawFd)> { + let ptr = unsafe { fdopendir(dir_fd.as_raw_fd()) }; + if ptr.is_null() { + return Err(io::Error::last_os_error()); + } + let dirp = Dir(ptr); + // file descriptor is automatically closed by libc::closedir() now, so give up ownership + let new_parent_fd = dir_fd.into_raw_fd(); + // a valid root is not needed because we do not call any functions involving the full path + // of the DirEntrys. + let dummy_root = PathBuf::new(); + Ok(( + ReadDir { + inner: Arc::new(InnerReadDir { dirp, root: dummy_root }), + end_of_stream: false, + }, + new_parent_fd, + )) + } + + fn is_dir(ent: &DirEntry) -> Option { + match ent.entry.d_type { + libc::DT_UNKNOWN => None, + libc::DT_DIR => Some(true), + _ => Some(false), + } + } + + fn remove_dir_all_recursive(parent_fd: Option, p: &Path) -> io::Result<()> { + let pcstr = cstr(p)?; + + // entry is expected to be a directory, open as such + let fd = openat_nofollow_dironly(parent_fd, &pcstr)?; + + // open the directory passing ownership of the fd + let (dir, fd) = fdreaddir(fd)?; + for child in dir { + let child = child?; + match is_dir(&child) { + Some(true) => { + remove_dir_all_recursive(Some(fd), Path::new(&child.file_name()))?; + } + Some(false) => { + cvt(unsafe { unlinkat(fd, child.name_cstr().as_ptr(), 0) })?; + } + None => match cvt(unsafe { unlinkat(fd, child.name_cstr().as_ptr(), 0) }) { + // type unknown - try to unlink + Err(err) + if err.raw_os_error() == Some(libc::EISDIR) + || err.raw_os_error() == Some(libc::EPERM) => + { + // if the file is a directory unlink fails with EISDIR on Linux and EPERM everyhwere else + remove_dir_all_recursive(Some(fd), Path::new(&child.file_name()))?; + } + result => { + result?; + } + }, + } + } + + // unlink the directory after removing its contents + cvt(unsafe { + unlinkat(parent_fd.unwrap_or(libc::AT_FDCWD), pcstr.as_ptr(), libc::AT_REMOVEDIR) + })?; + Ok(()) + } + + pub fn remove_dir_all(p: &Path) -> io::Result<()> { + // We cannot just call remove_dir_all_recursive() here because that would not delete a passed + // symlink. No need to worry about races, because remove_dir_all_recursive() does not recurse + // into symlinks. + let attr = lstat(p)?; + if attr.file_type().is_symlink() { + crate::fs::remove_file(p) + } else { + remove_dir_all_recursive(None, p) + } + } + + mod libc { + pub use sgx_libc::ocall::{fdopendir, openat, unlinkat}; + pub use sgx_libc::*; + } +} diff --git a/sgx_tstd/src/sys/mod.rs b/sgx_tstd/src/sys/mod.rs index 589e18c63..781125600 100644 --- a/sgx_tstd/src/sys/mod.rs +++ b/sgx_tstd/src/sys/mod.rs @@ -75,7 +75,7 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind { libc::ENOSPC => StorageFull, libc::ENOSYS => Unsupported, libc::EMLINK => TooManyLinks, - libc::ENAMETOOLONG => FilenameTooLong, + libc::ENAMETOOLONG => InvalidFilename, libc::ENETDOWN => NetworkDown, libc::ENETUNREACH => NetworkUnreachable, libc::ENOTCONN => NotConnected, @@ -148,9 +148,6 @@ pub mod unsupported { } pub fn unsupported_err() -> io::Error { - io::Error::new_const( - io::ErrorKind::Unsupported, - &"operation not supported on this platform", - ) + io::const_io_error!(io::ErrorKind::Unsupported, "operation not supported on this platform",) } } diff --git a/sgx_tstd/src/sys/net.rs b/sgx_tstd/src/sys/net.rs index 06839990d..7375f0726 100644 --- a/sgx_tstd/src/sys/net.rs +++ b/sgx_tstd/src/sys/net.rs @@ -44,9 +44,6 @@ pub fn cvt_gai(err: c_int) -> io::Result<()> { return Ok(()); } - // We may need to trigger a glibc workaround. See on_resolver_failure() for details. - // on_resolver_failure(); - if err == libc::EAI_SYSTEM { return Err(io::Error::last_os_error()); } @@ -117,9 +114,9 @@ impl Socket { let mut pollfd = libc::pollfd { fd: self.as_raw_fd(), events: libc::POLLOUT, revents: 0 }; if timeout.as_secs() == 0 && timeout.subsec_nanos() == 0 { - return Err(io::Error::new_const( + return Err(io::const_io_error!( io::ErrorKind::InvalidInput, - &"cannot set a 0 duration timeout", + "cannot set a 0 duration timeout", )); } @@ -128,7 +125,7 @@ impl Socket { loop { let elapsed = start.elapsed(); if elapsed >= timeout { - return Err(io::Error::new_const(io::ErrorKind::TimedOut, &"connection timed out")); + return Err(io::const_io_error!(io::ErrorKind::TimedOut, "connection timed out")); } let timeout = timeout - elapsed; @@ -155,9 +152,9 @@ impl Socket { // for POLLHUP rather than read readiness if pollfd.revents & libc::POLLHUP != 0 { let e = self.take_error()?.unwrap_or_else(|| { - io::Error::new_const( + io::const_io_error!( io::ErrorKind::Uncategorized, - &"no error set after POLLHUP", + "no error set after POLLHUP", ) }); return Err(e); @@ -169,16 +166,6 @@ impl Socket { } } - // Attention: - // this function is a blocking function, which make an OCALL - // and block itself **in the untrusted OS**. This is very much - // dangerous and is misleading. - // In SGX programming, execution is by default in enclave and - // cannot leak information by design. Howeverm, this function - // is not. It leaks events. - // This function is guarded by feature `net` and should only - // be used on demand. - // We don't support linux kernel < 2.6.28. So we only use accept4. pub fn accept(&self, storage: *mut sockaddr, len: *mut socklen_t) -> io::Result { // Unfortunately the only known way right now to accept a socket and // atomically set the CLOEXEC flag is to use the `accept4` syscall on @@ -274,9 +261,9 @@ impl Socket { let timeout = match dur { Some(dur) => { if dur.as_secs() == 0 && dur.subsec_nanos() == 0 { - return Err(io::Error::new_const( + return Err(io::const_io_error!( io::ErrorKind::InvalidInput, - &"cannot set a 0 duration timeout", + "cannot set a 0 duration timeout", )); } diff --git a/sgx_tstd/src/sys/os.rs b/sgx_tstd/src/sys/os.rs index de3821c7a..afcedf78b 100644 --- a/sgx_tstd/src/sys/os.rs +++ b/sgx_tstd/src/sys/os.rs @@ -52,7 +52,7 @@ pub fn set_errno(e: i32) { pub fn error_string(error: i32) -> String { let mut buf = [0_i8; TMPBUF_SZ]; unsafe { - assert!(!(trts_error::error_string(error, &mut buf) < 0), "strerror_r failure"); + assert!(trts_error::error_string(error, &mut buf) >= 0, "strerror_r failure"); let p = buf.as_ptr() as *const _; str::from_utf8(CStr::from_ptr(p).to_bytes()).unwrap().to_owned() @@ -162,9 +162,9 @@ impl StdError for JoinPathsError { pub fn current_exe() -> io::Result { match crate::fs::read_link("/proc/self/exe") { - Err(ref e) if e.kind() == io::ErrorKind::NotFound => Err(io::Error::new_const( + Err(ref e) if e.kind() == io::ErrorKind::NotFound => Err(io::const_io_error!( io::ErrorKind::Uncategorized, - &"no /proc/self/exe available. Is /proc mounted?", + "no /proc/self/exe available. Is /proc mounted?", )), other => other, } diff --git a/sgx_tstd/src/sys/os_str.rs b/sgx_tstd/src/sys/os_str.rs index dec62b444..33d038784 100644 --- a/sgx_tstd/src/sys/os_str.rs +++ b/sgx_tstd/src/sys/os_str.rs @@ -19,6 +19,7 @@ //! systems: just a `Vec`/`[u8]`. use crate::borrow::Cow; +use crate::collections::TryReserveError; use crate::fmt; use crate::fmt::Write; use crate::mem; @@ -125,11 +126,21 @@ impl Buf { self.inner.reserve(additional) } + #[inline] + pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { + self.inner.try_reserve(additional) + } + #[inline] pub fn reserve_exact(&mut self, additional: usize) { self.inner.reserve_exact(additional) } + #[inline] + pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> { + self.inner.try_reserve_exact(additional) + } + #[inline] pub fn shrink_to_fit(&mut self) { self.inner.shrink_to_fit() diff --git a/sgx_tstd/src/sys/path.rs b/sgx_tstd/src/sys/path.rs index d7d98cb0c..61ee74376 100644 --- a/sgx_tstd/src/sys/path.rs +++ b/sgx_tstd/src/sys/path.rs @@ -15,8 +15,10 @@ // specific language governing permissions and limitations // under the License.. +use crate::env; use crate::ffi::OsStr; -use crate::path::Prefix; +use crate::io; +use crate::path::{Path, PathBuf, Prefix}; #[inline] pub fn is_sep_byte(b: u8) -> bool { @@ -28,9 +30,50 @@ pub fn is_verbatim_sep(b: u8) -> bool { b == b'/' } +#[inline] pub fn parse_prefix(_: &OsStr) -> Option> { None } pub const MAIN_SEP_STR: &str = "/"; pub const MAIN_SEP: char = '/'; + +/// Make a POSIX path absolute without changing its semantics. +pub(crate) fn absolute(path: &Path) -> io::Result { + // This is mostly a wrapper around collecting `Path::components`, with + // exceptions made where this conflicts with the POSIX specification. + // See 4.13 Pathname Resolution, IEEE Std 1003.1-2017 + // https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_13 + + let mut components = path.components(); + let path_os = path.as_os_str().bytes(); + + let mut normalized = if path.is_absolute() { + // "If a pathname begins with two successive characters, the + // first component following the leading characters may be + // interpreted in an implementation-defined manner, although more than + // two leading characters shall be treated as a single + // character." + if path_os.starts_with(b"//") && !path_os.starts_with(b"///") { + components.next(); + PathBuf::from("//") + } else { + PathBuf::new() + } + } else { + env::current_dir()? + }; + normalized.extend(components); + + // "Interfaces using pathname resolution may specify additional constraints + // when a pathname that does not name an existing directory contains at + // least one non- character and contains one or more trailing + // characters". + // A trailing is also meaningful if "a symbolic link is + // encountered during pathname resolution". + if path_os.ends_with(b"/") { + normalized.push(""); + } + + Ok(normalized) +} diff --git a/sgx_tstd/src/sys/rwlock.bak.rs b/sgx_tstd/src/sys/rwlock.bak.rs deleted file mode 100644 index b9339a519..000000000 --- a/sgx_tstd/src/sys/rwlock.bak.rs +++ /dev/null @@ -1,308 +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.. - -use core::cell::UnsafeCell; -use crate::sync::{SgxThreadCondvar, SgxThreadMutex, SgxThreadSpinlock}; -use crate::thread; -use sgx_trts::libc; -use sgx_types::{sgx_thread_t, SysError, SGX_THREAD_T_NULL}; - -struct SgxThreadRwLockInner { - readers_num: u32, - writers_num: u32, - busy: u32, - writer_thread: sgx_thread_t, - condvar: SgxThreadCondvar, - mutex: SgxThreadMutex, - spinlock: SgxThreadSpinlock, -} - -impl SgxThreadRwLockInner { - const fn new() -> Self { - SgxThreadRwLockInner { - readers_num: 0, - writers_num: 0, - busy: 0, - writer_thread: SGX_THREAD_T_NULL, - condvar: SgxThreadCondvar::new(), - mutex: SgxThreadMutex::new(), - spinlock: SgxThreadSpinlock::new(), - } - } - - unsafe fn ref_busy(&mut self) -> SysError { - let ret: SysError; - self.spinlock.lock(); - { - if self.busy == u32::MAX { - ret = Err(libc::EAGAIN); - } else { - self.busy += 1; - ret = Ok(()); - } - } - self.spinlock.unlock(); - ret - } - - unsafe fn deref_busy(&mut self) -> SysError { - let ret: SysError; - self.spinlock.lock(); - { - if self.busy == 0 { - ret = Err(libc::EAGAIN); - } else { - self.busy -= 1; - ret = Ok(()); - } - } - self.spinlock.unlock(); - ret - } - - unsafe fn read(&mut self) -> SysError { - self.ref_busy()?; - self.mutex.lock(); - { - if self.writer_thread == thread::rsgx_thread_self() { - self.mutex.unlock(); - self.deref_busy(); - return Err(libc::EDEADLK); - } - if self.readers_num == u32::MAX { - self.mutex.unlock(); - self.deref_busy(); - return Err(libc::EAGAIN); - } - while self.writers_num > 0 { - self.condvar.wait(&self.mutex); - } - self.readers_num += 1; - } - self.mutex.unlock(); - self.deref_busy(); - Ok(()) - } - - unsafe fn try_read(&mut self) -> SysError { - self.ref_busy()?; - self.mutex.lock(); - { - let mut ret = Ok(()); - if self.writer_thread == thread::rsgx_thread_self() { - ret = Err(libc::EDEADLK); - } else if self.readers_num == u32::MAX { - ret = Err(libc::EAGAIN); - } else if self.writers_num > 0 { - ret = Err(libc::EBUSY); - } - match ret { - Ok(_) => {} - Err(e) => { - self.mutex.unlock(); - self.deref_busy(); - return Err(e); - } - } - self.readers_num += 1; - } - self.mutex.unlock(); - self.deref_busy(); - Ok(()) - } - - unsafe fn write(&mut self) -> SysError { - self.ref_busy()?; - self.mutex.lock(); - { - if self.writer_thread == thread::rsgx_thread_self() { - self.mutex.unlock(); - self.deref_busy(); - return Err(libc::EDEADLK); - } - - if self.writers_num == u32::MAX { - self.mutex.unlock(); - self.deref_busy(); - return Err(libc::EAGAIN); - } - - self.writers_num += 1; - while self.readers_num > 0 { - self.condvar.wait(&self.mutex); - } - while self.writer_thread != SGX_THREAD_T_NULL { - self.condvar.wait(&self.mutex); - } - self.writer_thread = thread::rsgx_thread_self(); - } - self.mutex.unlock(); - self.deref_busy(); - Ok(()) - } - - pub unsafe fn try_write(&mut self) -> SysError { - self.ref_busy()?; - self.mutex.lock(); - { - let mut ret = Ok(()); - if self.writer_thread == thread::rsgx_thread_self() { - ret = Err(libc::EDEADLK); - } else if self.writers_num == u32::MAX { - ret = Err(libc::EAGAIN); - } else if self.readers_num > 0 || self.writer_thread != SGX_THREAD_T_NULL { - ret = Err(libc::EBUSY); - } - - match ret { - Ok(_) => {} - Err(e) => { - self.mutex.unlock(); - self.deref_busy(); - return Err(e); - } - } - self.writers_num += 1; - self.writer_thread = thread::rsgx_thread_self(); - } - self.mutex.unlock(); - self.deref_busy(); - Ok(()) - } - - unsafe fn read_unlock(&mut self) -> SysError { - self.raw_unlock() - } - - unsafe fn write_unlock(&mut self) -> SysError { - self.raw_unlock() - } - - unsafe fn raw_unlock(&mut self) -> SysError { - self.mutex.lock(); - { - if self.readers_num > 0 { - self.readers_num -= 1; - if self.readers_num == 0 && self.writers_num > 0 { - self.condvar.broadcast(); - } - } else { - if self.writer_thread != thread::rsgx_thread_self() { - self.mutex.unlock(); - return Err(libc::EPERM); - } - self.writers_num -= 1; - self.writer_thread = SGX_THREAD_T_NULL; - if self.busy > 0 { - self.condvar.broadcast(); - } - } - } - self.mutex.unlock(); - Ok(()) - } - - unsafe fn destroy(&mut self) -> SysError { - self.mutex.lock(); - { - if self.readers_num > 0 || self.writers_num > 0 || self.busy > 0 { - self.spinlock.unlock(); - return Err(libc::EBUSY); - } - - self.condvar.destroy(); - self.mutex.destroy(); - } - self.spinlock.unlock(); - Ok(()) - } -} - -/// An OS-based reader-writer lock. -/// -/// This structure is entirely unsafe and serves as the lowest layer of a -/// cross-platform binding of system rwlocks. It is recommended to use the -/// safer types at the top level of this crate instead of this type. -pub struct SgxThreadRwLock { - lock: UnsafeCell, -} - -impl SgxThreadRwLock { - /// Creates a new reader-writer lock for use. - pub const fn new() -> Self { - SgxThreadRwLock { - lock: UnsafeCell::new(SgxThreadRwLockInner::new()), - } - } - - /// Acquires shared access to the underlying lock, blocking the current - /// thread to do so. - #[inline] - pub unsafe fn read(&self) -> SysError { - let rwlock: &mut SgxThreadRwLockInner = &mut *self.lock.get(); - rwlock.read() - } - - /// Attempts to acquire shared access to this lock, returning whether it - /// succeeded or not. - /// - /// This function does not block the current thread. - #[inline] - pub unsafe fn try_read(&self) -> SysError { - let rwlock: &mut SgxThreadRwLockInner = &mut *self.lock.get(); - rwlock.try_read() - } - - /// Acquires write access to the underlying lock, blocking the current thread - /// to do so. - #[inline] - pub unsafe fn write(&self) -> SysError { - let rwlock: &mut SgxThreadRwLockInner = &mut *self.lock.get(); - rwlock.write() - } - - /// Attempts to acquire exclusive access to this lock, returning whether it - /// succeeded or not. - /// - /// This function does not block the current thread. - #[inline] - pub unsafe fn try_write(&self) -> SysError { - let rwlock: &mut SgxThreadRwLockInner = &mut *self.lock.get(); - rwlock.try_write() - } - - /// Unlocks previously acquired shared access to this lock. - #[inline] - pub unsafe fn read_unlock(&self) -> SysError { - let rwlock: &mut SgxThreadRwLockInner = &mut *self.lock.get(); - rwlock.read_unlock() - } - - /// Unlocks previously acquired exclusive access to this lock. - #[inline] - pub unsafe fn write_unlock(&self) -> SysError { - let rwlock: &mut SgxThreadRwLockInner = &mut *self.lock.get(); - rwlock.write_unlock() - } - - /// Destroys OS-related resources with this RWLock. - #[inline] - pub unsafe fn destroy(&self) -> SysError { - let rwlock: &mut SgxThreadRwLockInner = &mut *self.lock.get(); - rwlock.destroy() - } -} diff --git a/sgx_tstd/src/sys/thread.rs b/sgx_tstd/src/sys/thread.rs index 8d0cfefef..538995b94 100644 --- a/sgx_tstd/src/sys/thread.rs +++ b/sgx_tstd/src/sys/thread.rs @@ -138,9 +138,9 @@ impl Drop for Thread { pub fn available_parallelism() -> io::Result { let cpus = enclave::rsgx_get_cpu_core_num(); - NonZeroUsize::new(cpus as usize).ok_or_else(|| io::Error::new_const( + NonZeroUsize::new(cpus as usize).ok_or_else(|| io::const_io_error!( io::ErrorKind::NotFound, - &"The number of hardware threads is not known for the target platform", + "The number of hardware threads is not known for the target platform", )) } diff --git a/sgx_tstd/src/sys/time.rs b/sgx_tstd/src/sys/time.rs index 9f28de2a0..d9b351a96 100644 --- a/sgx_tstd/src/sys/time.rs +++ b/sgx_tstd/src/sys/time.rs @@ -157,15 +157,6 @@ mod inner { Instant { t: now(libc::CLOCK_MONOTONIC) } } - pub const fn zero() -> Instant { - Instant { t: Timespec::zero() } - } - - pub fn actually_monotonic() -> bool { - (cfg!(target_os = "linux") && cfg!(target_arch = "x86_64")) - || (cfg!(target_os = "linux") && cfg!(target_arch = "x86")) - } - pub fn checked_sub_instant(&self, other: &Instant) -> Option { self.t.sub_timespec(&other.t).ok() } diff --git a/sgx_tstd/src/sys_common/backtrace.rs b/sgx_tstd/src/sys_common/backtrace.rs index 5f3a88c29..dd2d30ce9 100644 --- a/sgx_tstd/src/sys_common/backtrace.rs +++ b/sgx_tstd/src/sys_common/backtrace.rs @@ -24,7 +24,6 @@ use crate::fmt; use crate::io; use crate::io::prelude::*; use crate::path::{Path, PathBuf}; -use crate::sync::atomic::{self, Ordering}; use crate::sync::SgxThreadMutex as ThreadMutex; use crate::sys::backtrace::{self, BacktraceFmt, BytesOrWideString, PrintFmt}; @@ -163,58 +162,14 @@ where result } -pub enum RustBacktrace { - Print(PrintFmt), - Disabled, - RuntimeDisabled, -} - -/// Controls how the backtrace should be formatted. -#[derive(Debug, Copy, Clone, Eq, PartialEq)] -pub enum PrintFormat { - /// Show only relevant data from the backtrace. - Short = 2, - /// Show all the frames with absolute path for files. - Full = 3, -} - -static ENABLED: atomic::AtomicIsize = atomic::AtomicIsize::new(1); - -// For now logging is turned off by default, and this function checks to see -// whether the magical environment variable is present to see if it's turned on. -pub fn rust_backtrace_env() -> RustBacktrace { - // If the `backtrace` feature of this crate isn't enabled quickly return - // `None` so this can be constant propagated all over the place to turn - // optimize away callers. - if !cfg!(feature = "backtrace") { - return RustBacktrace::Disabled; - } - - match ENABLED.load(Ordering::SeqCst) { - 0 => RustBacktrace::Disabled, - 1 => RustBacktrace::RuntimeDisabled, - 2 => RustBacktrace::Print(PrintFmt::Short), - 3 => RustBacktrace::Print(PrintFmt::Full), - _ => unreachable!(), - } -} - -pub fn set_enabled(print_fmt: PrintFormat) { - ENABLED.store(match print_fmt { - PrintFormat::Short => 2, - PrintFormat::Full => 3, - }, Ordering::SeqCst); -} - /// Prints the filename of the backtrace frame. /// /// See also `output`. -#[allow(unused_variables)] pub fn output_filename( fmt: &mut fmt::Formatter<'_>, bows: BytesOrWideString<'_>, - print_fmt: PrintFmt, - cwd: Option<&PathBuf>, + _print_fmt: PrintFmt, + _cwd: Option<&PathBuf>, ) -> fmt::Result { let file: Cow<'_, Path> = match bows { BytesOrWideString::Bytes(bytes) => { @@ -233,4 +188,4 @@ pub fn output_filename( // } // } fmt::Display::fmt(&file.display(), fmt) -} \ No newline at end of file +} diff --git a/sgx_tstd/src/sys_common/fs.rs b/sgx_tstd/src/sys_common/fs.rs index 0b6ea9394..e006f9aa5 100644 --- a/sgx_tstd/src/sys_common/fs.rs +++ b/sgx_tstd/src/sys_common/fs.rs @@ -14,13 +14,14 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License.. + +use crate::fs; use crate::io::{self, Error, ErrorKind}; use crate::path::Path; -use crate::untrusted::fs; -pub(crate) const NOT_FILE_ERROR: Error = Error::new_const( +pub(crate) const NOT_FILE_ERROR: Error = io::const_io_error!( ErrorKind::InvalidInput, - &"the source path is neither a regular file nor a symlink to a regular file", + "the source path is neither a regular file nor a symlink to a regular file", ); pub fn copy(from: &Path, to: &Path) -> io::Result { diff --git a/sgx_tstd/src/sys_common/net.rs b/sgx_tstd/src/sys_common/net.rs index f7964efc1..dea810c74 100644 --- a/sgx_tstd/src/sys_common/net.rs +++ b/sgx_tstd/src/sys_common/net.rs @@ -21,7 +21,7 @@ use crate::cmp; use crate::convert::{TryFrom, TryInto}; use crate::ffi::CString; use crate::fmt; -use crate::io::{self, Error, ErrorKind, IoSlice, IoSliceMut}; +use crate::io::{self, ErrorKind, IoSlice, IoSliceMut}; use crate::mem; use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr}; use crate::ptr; @@ -82,7 +82,7 @@ pub fn sockaddr_to_addr(storage: &c::sockaddr_storage, len: usize) -> io::Result *(storage as *const _ as *const c::sockaddr_in6) }))) } - _ => Err(Error::new_const(ErrorKind::InvalidInput, &"invalid argument")), + _ => Err(io::const_io_error!(ErrorKind::InvalidInput, "invalid argument")), } } @@ -106,6 +106,7 @@ impl LookupHost { } } +#[allow(clippy::transmute_ptr_to_ref)] impl Iterator for LookupHost { type Item = SocketAddr; fn next(&mut self) -> Option { @@ -113,7 +114,7 @@ impl Iterator for LookupHost { unsafe { let cur = self.cur.as_ref()?; self.cur = cur.ai_next; - match sockaddr_to_addr(&*(cur.ai_addr as *const c::sockaddr_storage), cur.ai_addrlen as usize) { + match sockaddr_to_addr(mem::transmute(cur.ai_addr), cur.ai_addrlen as usize) { Ok(addr) => return Some(addr), Err(_) => continue, } @@ -139,7 +140,7 @@ impl TryFrom<&str> for LookupHost { ($e:expr, $msg:expr) => { match $e { Some(r) => r, - None => return Err(io::Error::new_const(io::ErrorKind::InvalidInput, &$msg)), + None => return Err(io::const_io_error!(io::ErrorKind::InvalidInput, $msg)), } }; } diff --git a/sgx_tstd/src/sys_common/thread_local_key.rs b/sgx_tstd/src/sys_common/thread_local_key.rs index e1245085e..a6d04ea41 100644 --- a/sgx_tstd/src/sys_common/thread_local_key.rs +++ b/sgx_tstd/src/sys_common/thread_local_key.rs @@ -64,7 +64,7 @@ #![allow(non_camel_case_types)] #![allow(dead_code)] // sys isn't exported yet -use core::sync::atomic::{self, AtomicUsize, Ordering}; +use crate::sync::atomic::{self, AtomicUsize, Ordering}; use crate::sys::thread_local_key as imp; use crate::sync::SgxThreadMutex; diff --git a/sgx_tstd/src/sys_common/thread_parker/generic.rs b/sgx_tstd/src/sys_common/thread_parker/generic.rs index 68da1298f..f30e346ce 100644 --- a/sgx_tstd/src/sys_common/thread_parker/generic.rs +++ b/sgx_tstd/src/sys_common/thread_parker/generic.rs @@ -15,7 +15,7 @@ // specific language governing permissions and limitations // under the License.. -//! Parker implementaiton based on a Mutex and Condvar. +//! Parker implementation based on a Mutex and Condvar. use crate::sync::atomic::AtomicUsize; use crate::sync::atomic::Ordering::SeqCst; @@ -37,7 +37,7 @@ impl Parker { Parker { state: AtomicUsize::new(EMPTY), lock: Mutex::new(()), cvar: Condvar::new() } } - // This implementaiton doesn't require `unsafe`, but other implementations + // This implementation doesn't require `unsafe`, but other implementations // may assume this is only called by the thread that owns the Parker. #[allow(clippy::single_match)] pub unsafe fn park(&self) { @@ -73,7 +73,7 @@ impl Parker { } } - // This implementaiton doesn't require `unsafe`, but other implementations + // This implementation doesn't require `unsafe`, but other implementations // may assume this is only called by the thread that owns the Parker. pub unsafe fn park_timeout(&self, dur: Duration) { // Like `park` above we have a fast path for an already-notified thread, and diff --git a/sgx_tstd/src/sys_common/wtf8.rs b/sgx_tstd/src/sys_common/wtf8.rs index d37342a5d..771be710d 100644 --- a/sgx_tstd/src/sys_common/wtf8.rs +++ b/sgx_tstd/src/sys_common/wtf8.rs @@ -37,6 +37,7 @@ use core::str::next_code_point; use crate::borrow::Cow; use crate::char; +use crate::collections::TryReserveError; use crate::fmt; use crate::hash::{Hash, Hasher}; use crate::iter::FromIterator; @@ -246,11 +247,47 @@ impl Wtf8Buf { self.bytes.reserve(additional) } + /// Tries to reserve capacity for at least `additional` more length units + /// in the given `Wtf8Buf`. The `Wtf8Buf` may reserve more space to 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. + /// + /// # Errors + /// + /// If the capacity overflows, or the allocator reports a failure, then an error + /// is returned. + #[inline] + pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { + self.bytes.try_reserve(additional) + } + #[inline] pub fn reserve_exact(&mut self, additional: usize) { self.bytes.reserve_exact(additional) } + /// Tries to reserve the minimum capacity for exactly `additional` + /// length units in the given `Wtf8Buf`. After calling + /// `try_reserve_exact`, capacity will be greater than or equal to + /// `self.len() + additional` if it returns `Ok(())`. + /// Does nothing if the capacity is already sufficient. + /// + /// Note that the allocator may give the `Wtf8Buf` more space than it + /// requests. Therefore, capacity can not be relied upon to be precisely + /// minimal. Prefer [`try_reserve`] if future insertions are expected. + /// + /// [`try_reserve`]: Wtf8Buf::try_reserve + /// + /// # Errors + /// + /// If the capacity overflows, or the allocator reports a failure, then an error + /// is returned. + #[inline] + pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> { + self.bytes.try_reserve_exact(additional) + } + #[inline] pub fn shrink_to_fit(&mut self) { self.bytes.shrink_to_fit() @@ -825,7 +862,8 @@ impl<'a> Iterator for Wtf8CodePoints<'a> { #[inline] fn next(&mut self) -> Option { - next_code_point(&mut self.bytes).map(|c| CodePoint { value: c }) + // SAFETY: `self.bytes` has been created from a WTF-8 string + unsafe { next_code_point(&mut self.bytes).map(|c| CodePoint { value: c }) } } #[inline] diff --git a/sgx_tstd/src/thread/local.rs b/sgx_tstd/src/thread/local.rs index e98c26de8..631951455 100644 --- a/sgx_tstd/src/thread/local.rs +++ b/sgx_tstd/src/thread/local.rs @@ -116,6 +116,7 @@ impl fmt::Debug for LocalKey { /// /// [`std::thread::LocalKey`]: crate::thread::LocalKey #[macro_export] +#[cfg_attr(not(test), rustc_diagnostic_item = "thread_local_macro")] #[allow_internal_unstable(thread_local_internals)] macro_rules! thread_local { // empty (base case for the recursion) @@ -151,11 +152,11 @@ macro_rules! __thread_local_inner { #[cfg(not(feature = "thread"))] #[inline] // see comments below unsafe fn __getit() -> $crate::result::Result<&'static $t, $crate::thread::AccessError> { - const _REQUIRE_UNSTABLE: () = $crate::thread::require_unstable_const_init_thread_local(); + const INIT_EXPR: $t = $init; if !$crate::mem::needs_drop::<$t>() || $crate::thread::thread_policy() == $crate::thread::SgxThreadPolicy::Bound { #[thread_local] - static mut VAL: $t = $init; + static mut VAL: $t = INIT_EXPR; Ok(&VAL) } else { Err($crate::thread::AccessError::new( @@ -166,7 +167,10 @@ macro_rules! __thread_local_inner { #[cfg(feature = "thread")] unsafe fn __getit() -> $crate::result::Result<&'static $t, $crate::thread::AccessError> { - const _REQUIRE_UNSTABLE: () = $crate::thread::require_unstable_const_init_thread_local(); + const INIT_EXPR: $t = $init; + + #[thread_local] + static mut VAL: $t = INIT_EXPR; // If a dtor isn't needed we can do something "very raw" and // just get going. @@ -182,8 +186,6 @@ macro_rules! __thread_local_inner { )); } - #[thread_local] - static mut VAL: $t = $init; // 0 == dtor not registered // 1 == dtor registered, dtor not run // 2 == dtor registered and is running or has run @@ -242,7 +244,11 @@ macro_rules! __thread_local_inner { static __KEY: $crate::thread::__FastLocalKeyInner<$t> = $crate::thread::__FastLocalKeyInner::new(); - __KEY.get(__init) + // FIXME: remove the #[allow(...)] marker when macros don't + // raise warning for missing/extraneous unsafe blocks anymore. + // See https://github.com/rust-lang/rust/issues/74838. + #[allow(unused_unsafe)] + unsafe { __KEY.get(__init) } } unsafe { @@ -421,7 +427,7 @@ pub mod statik { pub unsafe fn get(&self, init: fn() -> T) -> Result<&'static T, AccessError> { if !mem::needs_drop::() || thread::thread_policy() == SgxThreadPolicy::Bound { - // SAFETY: The caller must ensure no reference is ever handed out to + // SAFETY: The caller must ensure no reference is ever handed out to // the inner cell nor mutable reference to the Option inside said // cell. This make it safe to hand a reference, though the lifetime // of 'static is itself unsafe, making the get method unsafe. @@ -509,7 +515,7 @@ pub mod fast { Key { inner: LazyKeyInner::new(), dtor_state: Cell::new(DtorState::Unregistered) } } - // note that this is just a publically-callable function only for the + // note that this is just a publicly-callable function only for the // const-initialized form of thread locals, basically a way to call the // free `register_dtor` function defined elsewhere in libstd. pub unsafe fn register_dtor(a: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) { @@ -518,7 +524,7 @@ pub mod fast { pub unsafe fn get T>(&self, init: F) -> Result<&'static T, AccessError> { // SAFETY: See the definitions of `LazyKeyInner::get` and - // `try_initialize` for more informations. + // `try_initialize` for more information. // // The caller must ensure no mutable references are ever active to // the inner cell or the inner T when this is called. @@ -547,13 +553,13 @@ pub mod fast { if !super::pthread_info_tls.m_pthread.is_null() { // Note: - // If the current thread was created by pthread_create, we should call + // If the current thread was created by `pthread_create`, we should call // the try_register_dtor function. You can know whether the current thread has // been created by pthread_create() through the m_thread member of pthread_info // (thread local storage) of pthread library in intel sgx sdk. // - // Destructor will only be called when a thread created by pthread_create exits, - // because sys_common::thread_local::StaticKey does not call pthread_key_delete + // Destructor will only be called when a thread created by `pthread_create` exits, + // because `sys_common::thread_local::StaticKey` does not call `pthread_key_delete` // to trigger the destructor. if !mem::needs_drop::() || self.try_register_dtor() { // SAFETY: See comment above (his function doc). diff --git a/sgx_tstd/src/thread/mod.rs b/sgx_tstd/src/thread/mod.rs index 33fe85400..9fcaf3f62 100644 --- a/sgx_tstd/src/thread/mod.rs +++ b/sgx_tstd/src/thread/mod.rs @@ -55,6 +55,12 @@ pub use sgx_trts::enclave::SgxThreadPolicy; #[macro_use] mod local; +#[cfg(feature = "thread")] +mod scoped; + +#[cfg(feature = "thread")] +pub use scoped::{scope, Scope, ScopedJoinHandle}; + pub use self::local::{AccessError, LocalKey}; pub use self::local::statik::Key as __StaticLocalKeyInner; @@ -63,11 +69,6 @@ pub use self::local::fast::Key as __FastLocalKeyInner; #[cfg(feature = "thread")] pub use self::local::os::Key as __OsLocalKeyInner; -// This is only used to make thread locals with `const { .. }` initialization -// expressions unstable. If and/or when that syntax is stabilized with thread -// locals this will simply be removed. -pub const fn require_unstable_const_init_thread_local() {} - //////////////////////////////////////////////////////////////////////////////// // Builder //////////////////////////////////////////////////////////////////////////////// @@ -113,6 +114,7 @@ pub const fn require_unstable_const_init_thread_local() {} /// [`unwrap`]: crate::result::Result::unwrap /// [naming-threads]: ./index.html#naming-threads #[cfg(feature = "thread")] +#[must_use = "must eventually spawn the thread"] #[derive(Debug)] pub struct Builder { // A name for the thread-to-be, for identification in panic messages @@ -280,6 +282,20 @@ impl Builder { F: FnOnce() -> T, F: Send + 'a, T: Send + 'a, + { + Ok(JoinHandle(self.spawn_unchecked_(f, None)?)) + } + + unsafe fn spawn_unchecked_<'a, 'scope, F, T>( + self, + f: F, + scope_data: Option<&'scope scoped::ScopeData>, + ) -> io::Result> + where + F: FnOnce() -> T, + F: Send + 'a, + T: Send + 'a, + 'scope: 'a, { let Builder { name } = self; @@ -288,7 +304,8 @@ impl Builder { })); let their_thread = my_thread.clone(); - let my_packet: Arc>>> = Arc::new(UnsafeCell::new(None)); + let my_packet: Arc> = + Arc::new(Packet { scope: scope_data, result: UnsafeCell::new(None) }); let their_packet = my_packet.clone(); let main = move || { @@ -306,10 +323,14 @@ impl Builder { // closure (it is an Arc<...>) and `my_packet` will be stored in the // same `JoinInner` as this closure meaning the mutation will be // safe (not modify it and affect a value far away). - *their_packet.get() = Some(try_result); + *their_packet.result.get() = Some(try_result); }; - Ok(JoinHandle(JoinInner { + if let Some(scope_data) = scope_data { + scope_data.increment_num_running_threads(); + } + + Ok(JoinInner { // SAFETY: // // `imp::Thread::new` takes a closure with a `'static` lifetime, since it's passed @@ -323,14 +344,14 @@ impl Builder { // Similarly, the `sys` implementation must guarantee that no references to the closure // exist after the thread has terminated, which is signaled by `Thread::join` // returning. - native: Some(imp::Thread::new( + native: imp::Thread::new( mem::transmute::, Box>( Box::new(main), - ), - )?), + ), + )?, thread: my_thread, - packet: Packet(my_packet), - })) + packet: my_packet, + }) } } @@ -787,10 +808,13 @@ pub fn park_timeout(dur: Duration) { /// A unique identifier for a running thread. /// -/// A `ThreadId` is an opaque object that has a unique value for each thread -/// that creates one. `ThreadId`s are not guaranteed to correspond to a thread's -/// system-designated identifier. A `ThreadId` can be retrieved from the [`id`] -/// method on a [`Thread`]. +/// A `ThreadId` is an opaque object that uniquely identifies each thread +/// created during the lifetime of a process. `ThreadId`s are guaranteed not to +/// be reused, even when a thread terminates. `ThreadId`s are under the control +/// of Rust's standard library and there may not be any relationship between +/// `ThreadId` and the underlying platform's notion of a thread identifier -- +/// the two concepts cannot, therefore, be used interchangeably. A `ThreadId` +/// can be retrieved from the [`id`] method on a [`Thread`]. /// /// # Examples /// @@ -821,7 +845,10 @@ impl ThreadId { // If we somehow use up all our bits, panic so that we're not // covering up subtle bugs of IDs being reused. - assert!(!(COUNTER == u64::MAX), "failed to generate unique thread ID: bitspace exhausted"); + if COUNTER == u64::MAX { + let _ = GUARD.unlock(); // in case the panic handler ends up calling `ThreadId::new()`, avoid reentrant lock acquire. + panic!("failed to generate unique thread ID: bitspace exhausted"); + } let id = COUNTER; COUNTER += 1; @@ -1044,46 +1071,60 @@ impl fmt::Debug for SgxThread { /// [`std::panic::resume_unwind`]: crate::panic::resume_unwind pub type Result = crate::result::Result>; -// This packet is used to communicate the return value between the spawned thread -// and the rest of the program. Memory is shared through the `Arc` within and there's -// no need for a mutex here because synchronization happens with `join()` (the -// caller will never read this packet until the thread has exited). +// This packet is used to communicate the return value between the spawned +// thread and the rest of the program. It is shared through an `Arc` and +// there's no need for a mutex here because synchronization happens with `join()` +// (the caller will never read this packet until the thread has exited). // -// This packet itself is then stored into a `JoinInner` which in turns is placed -// in `JoinHandle` and `JoinGuard`. Due to the usage of `UnsafeCell` we need to -// manually worry about impls like Send and Sync. The type `T` should -// already always be Send (otherwise the thread could not have been created) and -// this type is inherently Sync because no methods take &self. Regardless, -// however, we add inheriting impls for Send/Sync to this type to ensure it's -// Send/Sync and that future modifications will still appropriately classify it. +// An Arc to the packet is stored into a `JoinInner` which in turns is placed +// in `JoinHandle`. #[cfg(feature = "thread")] -struct Packet(Arc>>>); +struct Packet<'scope, T> { + scope: Option<&'scope scoped::ScopeData>, + result: UnsafeCell>>, +} +// Due to the usage of `UnsafeCell` we need to manually implement Sync. +// The type `T` should already always be Send (otherwise the thread could not +// have been created) and the Packet is Sync because all access to the +// `UnsafeCell` synchronized (by the `join()` boundary), and `ScopeData` is Sync. #[cfg(feature = "thread")] -unsafe impl Send for Packet {} +unsafe impl<'scope, T: Sync> Sync for Packet<'scope, T> {} + #[cfg(feature = "thread")] -unsafe impl Sync for Packet {} +impl<'scope, T> Drop for Packet<'scope, T> { + fn drop(&mut self) { + // Book-keeping so the scope knows when it's done. + if let Some(scope) = self.scope { + // If this packet was for a thread that ran in a scope, the thread + // panicked, and nobody consumed the panic payload, we make sure + // the scope function will panic. + let unhandled_panic = matches!(self.result.get_mut(), Some(Err(_))); + scope.decrement_num_running_threads(unhandled_panic); + } + } +} /// Inner representation for JoinHandle #[cfg(feature = "thread")] -struct JoinInner { - native: Option, +struct JoinInner<'scope, T> { + native: imp::Thread, thread: SgxThread, - packet: Packet, + packet: Arc>, } #[cfg(feature = "thread")] -impl JoinInner { - fn join(&mut self) -> Result { - self.native.take().unwrap().join(); - unsafe { (*self.packet.0.get()).take().unwrap() } +impl<'scope, T> JoinInner<'scope, T> { + fn join(mut self) -> Result { + self.native.join(); + Arc::get_mut(&mut self.packet).unwrap().result.get_mut().take().unwrap() } } /// An owned permission to join on a thread (block on its termination). /// /// A `JoinHandle` *detaches* the associated thread when it is dropped, which -/// means that there is no longer any handle to thread and no way to `join` +/// means that there is no longer any handle to the thread and no way to `join` /// on it. /// /// Due to platform restrictions, it is not possible to [`Clone`] this @@ -1143,7 +1184,7 @@ impl JoinInner { /// [`thread::Builder::spawn`]: Builder::spawn /// [`thread::spawn`]: spawn #[cfg(feature = "thread")] -pub struct JoinHandle(JoinInner); +pub struct JoinHandle(JoinInner<'static, T>); #[cfg(feature = "thread")] unsafe impl Send for JoinHandle {} @@ -1206,22 +1247,30 @@ impl JoinHandle { /// }).unwrap(); /// join_handle.join().expect("Couldn't join on the associated thread"); /// ``` - pub fn join(mut self) -> Result { + pub fn join(self) -> Result { self.0.join() } + + /// Checks if the associated thread is still running its main function. + /// + /// This might return `false` for a brief moment after the thread's main + /// function has returned, but before the thread itself has stopped running. + pub fn is_running(&self) -> bool { + Arc::strong_count(&self.0.packet) > 1 + } } #[cfg(feature = "thread")] impl AsInner for JoinHandle { fn as_inner(&self) -> &imp::Thread { - self.0.native.as_ref().unwrap() + &self.0.native } } #[cfg(feature = "thread")] impl IntoInner for JoinHandle { fn into_inner(self) -> imp::Thread { - self.0.native.unwrap() + self.0.native } } @@ -1256,9 +1305,12 @@ fn _assert_sync_and_send() { /// The purpose of this API is to provide an easy and portable way to query /// the default amount of parallelism the program should use. Among other things it /// does not expose information on NUMA regions, does not account for -/// differences in (co)processor capabilities, and will not modify the program's -/// global state in order to more accurately query the amount of available -/// parallelism. +/// differences in (co)processor capabilities or current system load, +/// and will not modify the program's global state in order to more accurately +/// query the amount of available parallelism. +/// +/// Where both fixed steady-state and burst limits are available the steady-state +/// capacity will be used to ensure more predictable latencies. /// /// Resource limits can be changed during the runtime of a program, therefore the value is /// not cached and instead recomputed every time this function is called. It should not be @@ -1271,6 +1323,15 @@ fn _assert_sync_and_send() { /// platform-specific APIs as well. The following platform limitations currently /// apply to `available_parallelism`: /// +/// On Windows: +/// - It may undercount the amount of parallelism available on systems with more +/// than 64 logical CPUs. However, programs typically need specific support to +/// take advantage of more than 64 logical CPUs, and in the absence of such +/// support, the number returned by this function accurately reflects the +/// number of logical CPUs the program can use by default. +/// - It may overcount the amount of parallelism available on systems limited by +/// process-wide affinity masks, or job object limitations. +/// /// On Linux: /// - It may overcount the amount of parallelism available when limited by a /// process-wide affinity mask, or when affected by cgroup limits. @@ -1292,10 +1353,10 @@ fn _assert_sync_and_send() { /// /// ``` /// # #![allow(dead_code)] -/// #![feature(available_parallelism)] -/// use std::thread; +/// use std::{io, thread}; /// -/// let count = thread::available_parallelism().map(|n| n.get()).unwrap_or(1); +/// let count = thread::available_parallelism()?.get(); +/// assert!(count >= 1_usize); /// ``` #[cfg(feature = "thread")] pub fn available_parallelism() -> io::Result { diff --git a/sgx_tstd/src/thread/scoped.rs b/sgx_tstd/src/thread/scoped.rs new file mode 100644 index 000000000..5a4b9c9d0 --- /dev/null +++ b/sgx_tstd/src/thread/scoped.rs @@ -0,0 +1,332 @@ +// 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.. + +use super::{current, park, Builder, JoinInner, Result, SgxThread}; +use crate::fmt; +use crate::io; +use crate::marker::PhantomData; +use crate::panic::{catch_unwind, resume_unwind, AssertUnwindSafe}; +use crate::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; +use crate::sync::Arc; + +/// A scope to spawn scoped threads in. +/// +/// See [`scope`] for details. +pub struct Scope<'env> { + data: ScopeData, + /// Invariance over 'env, to make sure 'env cannot shrink, + /// which is necessary for soundness. + /// + /// Without invariance, this would compile fine but be unsound: + /// + /// ```compile_fail + /// #![feature(scoped_threads)] + /// + /// std::thread::scope(|s| { + /// s.spawn(|s| { + /// let a = String::from("abcd"); + /// s.spawn(|_| println!("{:?}", a)); // might run after `a` is dropped + /// }); + /// }); + /// ``` + env: PhantomData<&'env mut &'env ()>, +} + +/// An owned permission to join on a scoped thread (block on its termination). +/// +/// See [`Scope::spawn`] for details. +pub struct ScopedJoinHandle<'scope, T>(JoinInner<'scope, T>); + +pub(super) struct ScopeData { + num_running_threads: AtomicUsize, + a_thread_panicked: AtomicBool, + main_thread: SgxThread, +} + +impl ScopeData { + pub(super) fn increment_num_running_threads(&self) { + // We check for 'overflow' with usize::MAX / 2, to make sure there's no + // chance it overflows to 0, which would result in unsoundness. + if self.num_running_threads.fetch_add(1, Ordering::Relaxed) > usize::MAX / 2 { + // This can only reasonably happen by mem::forget()'ing many many ScopedJoinHandles. + self.decrement_num_running_threads(false); + panic!("too many running threads in thread scope"); + } + } + pub(super) fn decrement_num_running_threads(&self, panic: bool) { + if panic { + self.a_thread_panicked.store(true, Ordering::Relaxed); + } + if self.num_running_threads.fetch_sub(1, Ordering::Release) == 1 { + self.main_thread.unpark(); + } + } +} + +/// Create a scope for spawning scoped threads. +/// +/// The function passed to `scope` will be provided a [`Scope`] object, +/// through which scoped threads can be [spawned][`Scope::spawn`]. +/// +/// Unlike non-scoped threads, scoped threads can borrow non-`'static` data, +/// as the scope guarantees all threads will be joined at the end of the scope. +/// +/// All threads spawned within the scope that haven't been manually joined +/// will be automatically joined before this function returns. +/// +/// # Panics +/// +/// If any of the automatically joined threads panicked, this function will panic. +/// +/// If you want to handle panics from spawned threads, +/// [`join`][ScopedJoinHandle::join] them before the end of the scope. +/// +/// # Example +/// +/// ``` +/// #![feature(scoped_threads)] +/// use std::thread; +/// +/// let mut a = vec![1, 2, 3]; +/// let mut x = 0; +/// +/// thread::scope(|s| { +/// s.spawn(|_| { +/// println!("hello from the first scoped thread"); +/// // We can borrow `a` here. +/// dbg!(&a); +/// }); +/// s.spawn(|_| { +/// println!("hello from the second scoped thread"); +/// // We can even mutably borrow `x` here, +/// // because no other threads are using it. +/// x += a[0] + a[2]; +/// }); +/// println!("hello from the main thread"); +/// }); +/// +/// // After the scope, we can modify and access our variables again: +/// a.push(4); +/// assert_eq!(x, a.len()); +/// ``` +#[track_caller] +pub fn scope<'env, F, T>(f: F) -> T +where + F: FnOnce(&Scope<'env>) -> T, +{ + let scope = Scope { + data: ScopeData { + num_running_threads: AtomicUsize::new(0), + main_thread: current(), + a_thread_panicked: AtomicBool::new(false), + }, + env: PhantomData, + }; + + // Run `f`, but catch panics so we can make sure to wait for all the threads to join. + let result = catch_unwind(AssertUnwindSafe(|| f(&scope))); + + // Wait until all the threads are finished. + while scope.data.num_running_threads.load(Ordering::Acquire) != 0 { + park(); + } + + // Throw any panic from `f`, or the return value of `f` if no thread panicked. + match result { + Err(e) => resume_unwind(e), + Ok(_) if scope.data.a_thread_panicked.load(Ordering::Relaxed) => { + panic!("a scoped thread panicked") + } + Ok(result) => result, + } +} + +impl<'env> Scope<'env> { + /// Spawns a new thread within a scope, returning a [`ScopedJoinHandle`] for it. + /// + /// Unlike non-scoped threads, threads spawned with this function may + /// borrow non-`'static` data from the outside the scope. See [`scope`] for + /// details. + /// + /// The join handle provides a [`join`] method that can be used to join the spawned + /// thread. If the spawned thread panics, [`join`] will return an [`Err`] containing + /// the panic payload. + /// + /// If the join handle is dropped, the spawned thread will implicitly joined at the + /// end of the scope. In that case, if the spawned thread panics, [`scope`] will + /// panic after all threads are joined. + /// + /// This call will create a thread using default parameters of [`Builder`]. + /// If you want to specify the stack size or the name of the thread, use + /// [`Builder::spawn_scoped`] instead. + /// + /// # Panics + /// + /// Panics if the OS fails to create a thread; use [`Builder::spawn_scoped`] + /// to recover from such errors. + /// + /// [`join`]: ScopedJoinHandle::join + pub fn spawn<'scope, F, T>(&'scope self, f: F) -> ScopedJoinHandle<'scope, T> + where + F: FnOnce(&Scope<'env>) -> T + Send + 'env, + T: Send + 'env, + { + Builder::new().spawn_scoped(self, f).expect("failed to spawn thread") + } +} + +impl Builder { + /// Spawns a new scoped thread using the settings set through this `Builder`. + /// + /// Unlike [`Scope::spawn`], this method yields an [`io::Result`] to + /// capture any failure to create the thread at the OS level. + /// + /// [`io::Result`]: crate::io::Result + /// + /// # Panics + /// + /// Panics if a thread name was set and it contained null bytes. + /// + /// # Example + /// + /// ``` + /// #![feature(scoped_threads)] + /// use std::thread; + /// + /// let mut a = vec![1, 2, 3]; + /// let mut x = 0; + /// + /// thread::scope(|s| { + /// thread::Builder::new() + /// .name("first".to_string()) + /// .spawn_scoped(s, |_| + /// { + /// println!("hello from the {:?} scoped thread", thread::current().name()); + /// // We can borrow `a` here. + /// dbg!(&a); + /// }) + /// .unwrap(); + /// thread::Builder::new() + /// .name("second".to_string()) + /// .spawn_scoped(s, |_| + /// { + /// println!("hello from the {:?} scoped thread", thread::current().name()); + /// // We can even mutably borrow `x` here, + /// // because no other threads are using it. + /// x += a[0] + a[2]; + /// }) + /// .unwrap(); + /// println!("hello from the main thread"); + /// }); + /// + /// // After the scope, we can modify and access our variables again: + /// a.push(4); + /// assert_eq!(x, a.len()); + /// ``` + pub fn spawn_scoped<'scope, 'env, F, T>( + self, + scope: &'scope Scope<'env>, + f: F, + ) -> io::Result> + where + F: FnOnce(&Scope<'env>) -> T + Send + 'env, + T: Send + 'env, + { + Ok(ScopedJoinHandle(unsafe { self.spawn_unchecked_(|| f(scope), Some(&scope.data)) }?)) + } +} + +impl<'scope, T> ScopedJoinHandle<'scope, T> { + /// Extracts a handle to the underlying thread. + /// + /// # Examples + /// + /// ``` + /// #![feature(scoped_threads)] + /// #![feature(thread_is_running)] + /// + /// use std::thread; + /// + /// thread::scope(|s| { + /// let t = s.spawn(|_| { + /// println!("hello"); + /// }); + /// println!("thread id: {:?}", t.thread().id()); + /// }); + /// ``` + #[must_use] + pub fn thread(&self) -> &SgxThread { + &self.0.thread + } + + /// Waits for the associated thread to finish. + /// + /// This function will return immediately if the associated thread has already finished. + /// + /// In terms of [atomic memory orderings], the completion of the associated + /// thread synchronizes with this function returning. + /// In other words, all operations performed by that thread + /// [happen before](https://doc.rust-lang.org/nomicon/atomics.html#data-accesses) + /// all operations that happen after `join` returns. + /// + /// If the associated thread panics, [`Err`] is returned with the panic payload. + /// + /// [atomic memory orderings]: crate::sync::atomic + /// + /// # Examples + /// + /// ``` + /// #![feature(scoped_threads)] + /// #![feature(thread_is_running)] + /// + /// use std::thread; + /// + /// thread::scope(|s| { + /// let t = s.spawn(|_| { + /// panic!("oh no"); + /// }); + /// assert!(t.join().is_err()); + /// }); + /// ``` + pub fn join(self) -> Result { + self.0.join() + } + + /// Checks if the associated thread is still running its main function. + /// + /// This might return `false` for a brief moment after the thread's main + /// function has returned, but before the thread itself has stopped running. + pub fn is_running(&self) -> bool { + Arc::strong_count(&self.0.packet) > 1 + } +} + +impl<'env> fmt::Debug for Scope<'env> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Scope") + .field("num_running_threads", &self.data.num_running_threads.load(Ordering::Relaxed)) + .field("a_thread_panicked", &self.data.a_thread_panicked.load(Ordering::Relaxed)) + .field("main_thread", &self.data.main_thread) + .finish_non_exhaustive() + } +} + +impl<'scope, T> fmt::Debug for ScopedJoinHandle<'scope, T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("ScopedJoinHandle").finish_non_exhaustive() + } +} diff --git a/sgx_tstd/src/time.rs b/sgx_tstd/src/time.rs index fe761bc53..6de47078f 100644 --- a/sgx_tstd/src/time.rs +++ b/sgx_tstd/src/time.rs @@ -48,8 +48,6 @@ #![allow(clippy::needless_doctest_main)] -mod monotonic; - use crate::error::Error; use crate::fmt; use crate::ops::{Add, AddAssign, Sub, SubAssign}; @@ -58,16 +56,16 @@ use crate::sys_common::FromInner; pub use core::time::Duration; -pub use core::time::FromSecsError; +pub use core::time::FromFloatSecsError; /// A measurement of a monotonically nondecreasing clock. /// Opaque and useful only with [`Duration`]. /// -/// Instants are always guaranteed to be no less than any previously measured -/// instant when created, and are often useful for tasks such as measuring +/// Instants are always guaranteed, barring [platform bugs], to be no less than any previously +/// measured instant when created, and are often useful for tasks such as measuring /// benchmarks or timing how long an operation takes. /// -/// Note, however, that instants are not guaranteed to be **steady**. In other +/// Note, however, that instants are **not** guaranteed to be **steady**. In other /// words, each tick of the underlying clock might not be the same length (e.g. /// some seconds may be longer than others). An instant may jump forwards or /// experience time dilation (slow down or speed up), but it will never go @@ -97,6 +95,8 @@ pub use core::time::FromSecsError; /// } /// ``` /// +/// [platform bugs]: Instant#monotonicity +/// /// # OS-specific behaviors /// /// An `Instant` is a wrapper around system-specific types and it may behave @@ -138,6 +138,26 @@ pub use core::time::FromSecsError; /// > structure cannot represent the new point in time. /// /// [`add`]: Instant::add +/// +/// ## Monotonicity +/// +/// On all platforms `Instant` will try to use an OS API that guarantees monotonic behavior +/// if available, which is the case for all [tier 1] platforms. +/// In practice such guarantees are – under rare circumstances – broken by hardware, virtualization +/// or operating system bugs. To work around these bugs and platforms not offering monotonic clocks +/// [`duration_since`], [`elapsed`] and [`sub`] saturate to zero. In older Rust versions this +/// lead to a panic instead. [`checked_duration_since`] can be used to detect and handle situations +/// where monotonicity is violated, or `Instant`s are subtracted in the wrong order. +/// +/// This workaround obscures programming errors where earlier and later instants are accidentally +/// swapped. For this reason future rust versions may reintroduce panics. +/// +/// [tier 1]: https://doc.rust-lang.org/rustc/platform-support.html +/// [`duration_since`]: Instant::duration_since +/// [`elapsed`]: Instant::elapsed +/// [`sub`]: Instant::sub +/// [`checked_duration_since`]: Instant::checked_duration_since +/// #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct Instant(time::Instant); @@ -189,7 +209,12 @@ pub struct Instant(time::Instant); /// } /// ``` /// -/// # Underlying System calls +/// # Platform-specific behavior +/// +/// The precision of `SystemTime` can depend on the underlying OS-specific time format. +/// For example, on Windows the time is represented in 100 nanosecond intervals whereas Linux +/// can represent nanosecond intervals. +/// /// Currently, the following system calls are being used to get the current time using `now()`: /// /// | Platform | System call | @@ -258,81 +283,47 @@ impl Instant { Instant::_now() } + #[inline] pub(crate) fn _now() -> Instant { - let os_now = time::Instant::now(); - - // And here we come upon a sad state of affairs. The whole point of - // `Instant` is that it's monotonically increasing. We've found in the - // wild, however, that it's not actually monotonically increasing for - // one reason or another. These appear to be OS and hardware level bugs, - // and there's not really a whole lot we can do about them. Here's a - // taste of what we've found: - // - // * #48514 - OpenBSD, x86_64 - // * #49281 - linux arm64 and s390x - // * #51648 - windows, x86 - // * #56560 - windows, x86_64, AWS - // * #56612 - windows, x86, vm (?) - // * #56940 - linux, arm64 - // * https://bugzilla.mozilla.org/show_bug.cgi?id=1487778 - a similar - // Firefox bug - // - // It seems that this just happens a lot in the wild. - // We're seeing panics across various platforms where consecutive calls - // to `Instant::now`, such as via the `elapsed` function, are panicking - // as they're going backwards. Placed here is a last-ditch effort to try - // to fix things up. We keep a global "latest now" instance which is - // returned instead of what the OS says if the OS goes backwards. - // - // To hopefully mitigate the impact of this, a few platforms are - // excluded as "these at least haven't gone backwards yet". - // - // While issues have been seen on arm64 platforms the Arm architecture - // requires that the counter monotonically increases and that it must - // provide a uniform view of system time (e.g. it must not be possible - // for a core to recieve a message from another core with a time stamp - // and observe time going backwards (ARM DDI 0487G.b D11.1.2). While - // there have been a few 64bit SoCs that have bugs which cause time to - // not monoticially increase, these have been fixed in the Linux kernel - // and we shouldn't penalize all Arm SoCs for those who refuse to - // update their kernels: - // SUN50I_ERRATUM_UNKNOWN1 - Allwinner A64 / Pine A64 - fixed in 5.1 - // FSL_ERRATUM_A008585 - Freescale LS2080A/LS1043A - fixed in 4.10 - // HISILICON_ERRATUM_161010101 - Hisilicon 1610 - fixed in 4.11 - // ARM64_ERRATUM_858921 - Cortex A73 - fixed in 4.12 - if time::Instant::actually_monotonic() { - return Instant(os_now); - } - - Instant(monotonic::monotonize(os_now)) + Instant(time::Instant::now()) } - /// Returns the amount of time elapsed from another instant to this one. + /// Returns the amount of time elapsed from another instant to this one, + /// or zero duration if that instant is later than this one. /// /// # Panics /// - /// This function will panic if `earlier` is later than `self`. + /// Previous rust versions panicked when `earlier` was later than `self`. Currently this + /// method saturates. Future versions may reintroduce the panic in some circumstances. + /// See [Monotonicity]. + /// + /// [Monotonicity]: Instant#monotonicity /// /// # Examples /// /// ```no_run /// use std::time::{Duration, Instant}; /// use std::thread::sleep; - /// use std::untrusted::time::InstantEx; /// /// let now = Instant::now(); /// sleep(Duration::new(1, 0)); /// let new_now = Instant::now(); /// println!("{:?}", new_now.duration_since(now)); + /// println!("{:?}", now.duration_since(new_now)); // 0ns /// ``` #[must_use] pub fn duration_since(&self, earlier: Instant) -> Duration { - self.0.checked_sub_instant(&earlier.0).expect("supplied instant is later than self") + self.checked_duration_since(earlier).unwrap_or_default() } /// Returns the amount of time elapsed from another instant to this one, /// or None if that instant is later than this one. /// + /// Due to [monotonicity bugs], even under correct logical ordering of the passed `Instant`s, + /// this method can return `None`. + /// + /// [monotonicity bugs]: Instant#monotonicity + /// /// # Examples /// /// ```no_run @@ -376,9 +367,11 @@ impl Instant { /// /// # Panics /// - /// This function may panic if the current time is earlier than this - /// instant, which is something that can happen if an `Instant` is - /// produced synthetically. + /// Previous rust versions panicked when self was earlier than the current time. Currently this + /// method returns a Duration of zero in that case. Future versions may reintroduce the panic. + /// See [Monotonicity]. + /// + /// [Monotonicity]: Instant#monotonicity /// /// # Examples /// @@ -454,6 +447,16 @@ impl SubAssign for Instant { impl Sub for Instant { type Output = Duration; + /// Returns the amount of time elapsed from another instant to this one, + /// or zero duration if that instant is later than this one. + /// + /// # Panics + /// + /// Previous rust versions panicked when `other` was later than `self`. Currently this + /// method saturates. Future versions may reintroduce the panic in some circumstances. + /// See [Monotonicity]. + /// + /// [Monotonicity]: Instant#monotonicity fn sub(self, other: Instant) -> Duration { self.duration_since(other) } @@ -503,6 +506,7 @@ impl SystemTime { SystemTime::_now() } + #[inline] pub(crate) fn _now() -> SystemTime { SystemTime(time::SystemTime::now()) } diff --git a/sgx_tstd/src/time/monotonic.rs b/sgx_tstd/src/time/monotonic.rs deleted file mode 100644 index f577a6c11..000000000 --- a/sgx_tstd/src/time/monotonic.rs +++ /dev/null @@ -1,134 +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.. - -use crate::sys::time; - -#[inline] -pub(super) fn monotonize(raw: time::Instant) -> time::Instant { - inner::monotonize(raw) -} - -#[cfg(all(target_has_atomic = "64", not(target_has_atomic = "128")))] -pub mod inner { - use crate::sync::atomic::AtomicU64; - use crate::sync::atomic::Ordering::*; - use crate::sys::time; - use crate::time::Duration; - - pub(in crate::time) const ZERO: time::Instant = time::Instant::zero(); - - // bits 30 and 31 are never used since the nanoseconds part never exceeds 10^9 - const UNINITIALIZED: u64 = 0b11 << 30; - static MONO: AtomicU64 = AtomicU64::new(UNINITIALIZED); - - #[inline] - pub(super) fn monotonize(raw: time::Instant) -> time::Instant { - monotonize_impl(&MONO, raw) - } - - #[inline] - pub(in crate::time) fn monotonize_impl(mono: &AtomicU64, raw: time::Instant) -> time::Instant { - let delta = raw.checked_sub_instant(&ZERO).unwrap(); - let secs = delta.as_secs(); - // occupies no more than 30 bits (10^9 seconds) - let nanos = delta.subsec_nanos() as u64; - - // This wraps around every 136 years (2^32 seconds). - // To detect backsliding we use wrapping arithmetic and declare forward steps smaller - // than 2^31 seconds as expected and everything else as a backslide which will be - // monotonized. - // This could be a problem for programs that call instants at intervals greater - // than 68 years. Interstellar probes may want to ensure that actually_monotonic() is true. - let packed = (secs << 32) | nanos; - let updated = mono.fetch_update(Relaxed, Relaxed, |old| { - (old == UNINITIALIZED || packed.wrapping_sub(old) < u64::MAX / 2).then_some(packed) - }); - match updated { - Ok(_) => raw, - Err(newer) => { - // Backslide occurred. We reconstruct monotonized time from the upper 32 bit of the - // passed in value and the 64bits loaded from the atomic - let seconds_lower = newer >> 32; - let mut seconds_upper = secs & 0xffff_ffff_0000_0000; - if secs & 0xffff_ffff > seconds_lower { - // Backslide caused the lower 32bit of the seconds part to wrap. - // This must be the case because the seconds part is larger even though - // we are in the backslide branch, i.e. the seconds count should be smaller or equal. - // - // We assume that backslides are smaller than 2^32 seconds - // which means we need to add 1 to the upper half to restore it. - // - // Example: - // most recent observed time: 0xA1_0000_0000_0000_0000u128 - // bits stored in AtomicU64: 0x0000_0000_0000_0000u64 - // backslide by 1s - // caller time is 0xA0_ffff_ffff_0000_0000u128 - // -> we can fix up the upper half time by adding 1 << 32 - seconds_upper = seconds_upper.wrapping_add(0x1_0000_0000); - } - let secs = seconds_upper | seconds_lower; - let nanos = newer as u32; - ZERO.checked_add_duration(&Duration::new(secs, nanos)).unwrap() - } - } - } -} - -#[cfg(target_has_atomic = "128")] -pub mod inner { - use crate::sync::atomic::AtomicU128; - use crate::sync::atomic::Ordering::*; - use crate::sys::time; - use crate::time::Duration; - - const ZERO: time::Instant = time::Instant::zero(); - static MONO: AtomicU128 = AtomicU128::new(0); - - #[inline] - pub(super) fn monotonize(raw: time::Instant) -> time::Instant { - let delta = raw.checked_sub_instant(&ZERO).unwrap(); - // Split into seconds and nanos since Duration doesn't have a - // constructor that takes a u128 - let secs = delta.as_secs() as u128; - let nanos = delta.subsec_nanos() as u128; - let timestamp: u128 = secs << 64 | nanos; - let timestamp = MONO.fetch_max(timestamp, Relaxed).max(timestamp); - let secs = (timestamp >> 64) as u64; - let nanos = timestamp as u32; - ZERO.checked_add_duration(&Duration::new(secs, nanos)).unwrap() - } -} - -#[cfg(not(any(target_has_atomic = "64", target_has_atomic = "128")))] -pub mod inner { - use crate::cmp; - use crate::sys::time; - use crate::sys_common::mutex::StaticMutex; - - #[inline] - pub(super) fn monotonize(os_now: time::Instant) -> time::Instant { - static LOCK: SgxThreadMutex = SgxThreadMutex::new(); - static mut LAST_NOW: time::Instant = time::Instant::zero(); - unsafe { - let _lock = LOCK.lock(); - let now = cmp::max(LAST_NOW, os_now); - LAST_NOW = now; - let _ = LOCK.unlock(); - now - } - } -} diff --git a/sgx_tstd/src/untrusted/path.rs b/sgx_tstd/src/untrusted/path.rs index eae984347..fb6144fef 100644 --- a/sgx_tstd/src/untrusted/path.rs +++ b/sgx_tstd/src/untrusted/path.rs @@ -15,10 +15,9 @@ // specific language governing permissions and limitations // under the License.. -use crate::untrusted::fs; +use crate::fs; use crate::io; -use crate::path::Path; -use crate::path::PathBuf; +use crate::path::{self, Path, PathBuf}; pub trait PathEx { fn metadata(&self) -> io::Result; @@ -275,3 +274,73 @@ impl PathEx for Path { fs::symlink_metadata(self).map(|m| m.is_symlink()).unwrap_or(false) } } + +/// Makes the path absolute without accessing the filesystem. +/// +/// If the path is relative, the current directory is used as the base directory. +/// All intermediate components will be resolved according to platforms-specific +/// rules but unlike [`canonicalize`][crate::fs::canonicalize] this does not +/// resolve symlinks and may succeed even if the path does not exist. +/// +/// If the `path` is empty or getting the +/// [current directory][crate::env::current_dir] fails then an error will be +/// returned. +/// +/// # Examples +/// +/// ## Posix paths +/// +/// ``` +/// #![feature(absolute_path)] +/// # #[cfg(unix)] +/// fn main() -> std::io::Result<()> { +/// use std::path::{self, Path}; +/// +/// // Relative to absolute +/// let absolute = path::absolute("foo/./bar")?; +/// assert!(absolute.ends_with("foo/bar")); +/// +/// // Absolute to absolute +/// let absolute = path::absolute("/foo//test/.././bar.rs")?; +/// assert_eq!(absolute, Path::new("/foo/test/../bar.rs")); +/// Ok(()) +/// } +/// # #[cfg(not(unix))] +/// # fn main() {} +/// ``` +/// +/// The path is resolved using [POSIX semantics][posix-semantics] except that +/// it stops short of resolving symlinks. This means it will keep `..` +/// components and trailing slashes. +/// +/// ## Windows paths +/// +/// ``` +/// #![feature(absolute_path)] +/// # #[cfg(windows)] +/// fn main() -> std::io::Result<()> { +/// use std::path::{self, Path}; +/// +/// // Relative to absolute +/// let absolute = path::absolute("foo/./bar")?; +/// assert!(absolute.ends_with(r"foo\bar")); +/// +/// // Absolute to absolute +/// let absolute = path::absolute(r"C:\foo//test\..\./bar.rs")?; +/// +/// assert_eq!(absolute, Path::new(r"C:\foo\bar.rs")); +/// Ok(()) +/// } +/// # #[cfg(not(windows))] +/// # fn main() {} +/// ``` +/// +/// For verbatim paths this will simply return the path as given. For other +/// paths this is currently equivalent to calling [`GetFullPathNameW`][windows-path] +/// This may change in the future. +/// +/// [posix-semantics]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_13 +/// [windows-path]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfullpathnamew +pub fn absolute>(path: P) -> io::Result { + path::_absolute(path) +} diff --git a/sgx_tunittest/Cargo.toml b/sgx_tunittest/Cargo.toml index b218bd02e..75bc127fc 100644 --- a/sgx_tunittest/Cargo.toml +++ b/sgx_tunittest/Cargo.toml @@ -6,7 +6,7 @@ repository = "https://github.com/apache/teaclave-sgx-sdk" license-file = "LICENSE" documentation = "https://teaclave.apache.org/sgx-sdk-docs/" description = "Rust SGX SDK provides the ability to write Intel SGX applications in Rust Programming Language." -edition = "2018" +edition = "2021" include = [ "LICENSE", diff --git a/sgx_types/BUILD b/sgx_types/BUILD index 99de06303..c83124bef 100644 --- a/sgx_types/BUILD +++ b/sgx_types/BUILD @@ -3,7 +3,7 @@ load("@io_bazel_rules_rust//rust:rust.bzl", "rust_library") rust_library( name = "sgx_types", visibility = ["//visibility:public"], - edition = "2018", + edition = "2021", srcs = glob(["src/*.rs"]), deps = [], ) \ No newline at end of file diff --git a/sgx_types/Cargo.toml b/sgx_types/Cargo.toml index 04dd8786f..f46b1769b 100644 --- a/sgx_types/Cargo.toml +++ b/sgx_types/Cargo.toml @@ -6,7 +6,7 @@ repository = "https://github.com/apache/teaclave-sgx-sdk" license-file = "LICENSE" documentation = "https://teaclave.apache.org/sgx-sdk-docs/" description = "Rust SGX SDK provides the ability to write Intel SGX applications in Rust Programming Language." -edition = "2018" +edition = "2021" [lib] name = "sgx_types" diff --git a/sgx_ucrypto/Cargo.toml b/sgx_ucrypto/Cargo.toml index 99d1547de..5fe574aa2 100644 --- a/sgx_ucrypto/Cargo.toml +++ b/sgx_ucrypto/Cargo.toml @@ -6,7 +6,7 @@ repository = "https://github.com/apache/teaclave-sgx-sdk" license-file = "LICENSE" documentation = "https://teaclave.apache.org/sgx-sdk-docs/" description = "Rust SGX SDK provides the ability to write Intel SGX applications in Rust Programming Language." -edition = "2018" +edition = "2021" [lib] name = "sgx_ucrypto" diff --git a/sgx_unwind/Cargo.toml b/sgx_unwind/Cargo.toml index feae3479c..c90d47760 100644 --- a/sgx_unwind/Cargo.toml +++ b/sgx_unwind/Cargo.toml @@ -7,7 +7,7 @@ repository = "https://github.com/apache/teaclave-sgx-sdk" license-file = "LICENSE" documentation = "https://teaclave.apache.org/sgx-sdk-docs/" description = "Rust SGX SDK provides the ability to write Intel SGX applications in Rust Programming Language." -edition = "2018" +edition = "2021" exclude = [ "libunwind/autom4te.cache/*", "libunwind/aclocal.m4", diff --git a/sgx_unwind/build.rs b/sgx_unwind/build.rs index dada8f683..89c560373 100644 --- a/sgx_unwind/build.rs +++ b/sgx_unwind/build.rs @@ -15,8 +15,6 @@ // specific language governing permissions and limitations // under the License.. -#![feature(available_parallelism)] - extern crate sgx_build_helper as build_helper; use build_helper::{native_lib_boilerplate, run}; diff --git a/sgx_unwind/libunwind/src/se-iterate-phdr.c b/sgx_unwind/libunwind/src/se-iterate-phdr.c index 85f08f242..74390a692 100644 --- a/sgx_unwind/libunwind/src/se-iterate-phdr.c +++ b/sgx_unwind/libunwind/src/se-iterate-phdr.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2020 Intel Corporation. All rights reserved. + * Copyright (C) 2011-2021 Intel Corporation. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/sgx_unwind/libunwind/src/se-libc-stubs.c b/sgx_unwind/libunwind/src/se-libc-stubs.c index bb94ecee8..cb1592c3b 100644 --- a/sgx_unwind/libunwind/src/se-libc-stubs.c +++ b/sgx_unwind/libunwind/src/se-libc-stubs.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2020 Intel Corporation. All rights reserved. + * Copyright (C) 2011-2021 Intel Corporation. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/sgx_unwind/src/macros.rs b/sgx_unwind/src/macros.rs index a1d26d6e0..ae6fa6e0e 100644 --- a/sgx_unwind/src/macros.rs +++ b/sgx_unwind/src/macros.rs @@ -1,12 +1,19 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. +// 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 // -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. +// 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.. /// A macro for defining `#[cfg]` if-else statements. /// diff --git a/sgx_urts/Cargo.toml b/sgx_urts/Cargo.toml index 00c5b2b3e..b5a23208e 100644 --- a/sgx_urts/Cargo.toml +++ b/sgx_urts/Cargo.toml @@ -6,7 +6,7 @@ repository = "https://github.com/apache/teaclave-sgx-sdk" license-file = "LICENSE" documentation = "https://teaclave.apache.org/sgx-sdk-docs/" description = "Rust SGX SDK provides the ability to write Intel SGX applications in Rust Programming Language." -edition = "2018" +edition = "2021" [lib] name = "sgx_urts" diff --git a/sgx_urts/src/file.rs b/sgx_urts/src/file.rs index 16662321e..0b6d8b746 100644 --- a/sgx_urts/src/file.rs +++ b/sgx_urts/src/file.rs @@ -56,6 +56,26 @@ pub extern "C" fn u_open64_ocall( ret } +#[no_mangle] +pub extern "C" fn u_openat_ocall( + error: *mut c_int, + dirfd: c_int, + pathname: *const c_char, + flags: c_int, +) -> c_int { + let mut errno = 0; + let ret = unsafe { libc::openat(dirfd, pathname, flags) }; + if ret < 0 { + errno = Error::last_os_error().raw_os_error().unwrap_or(0); + } + if !error.is_null() { + unsafe { + *error = errno; + } + } + ret +} + #[no_mangle] pub extern "C" fn u_fstat_ocall(error: *mut c_int, fd: c_int, buf: *mut stat) -> c_int { let mut errno = 0; @@ -337,6 +357,26 @@ pub extern "C" fn u_link_ocall( ret } +#[no_mangle] +pub extern "C" fn u_unlinkat_ocall( + error: *mut c_int, + dirfd: c_int, + pathname: *const c_char, + flags: c_int, +) -> c_int { + let mut errno = 0; + let ret = unsafe { libc::unlinkat(dirfd, pathname, flags) }; + if ret < 0 { + errno = Error::last_os_error().raw_os_error().unwrap_or(0); + } + if !error.is_null() { + unsafe { + *error = errno; + } + } + ret +} + #[no_mangle] pub extern "C" fn u_linkat_ocall( error: *mut c_int, @@ -477,6 +517,21 @@ pub extern "C" fn u_rmdir_ocall(error: *mut c_int, pathname: *const c_char) -> c ret } +#[no_mangle] +pub extern "C" fn u_fdopendir_ocall(error: *mut c_int, fd: c_int) -> *mut DIR { + let mut errno = 0; + let ret = unsafe { libc::fdopendir(fd) }; + if ret.is_null() { + errno = Error::last_os_error().raw_os_error().unwrap_or(0); + } + if !error.is_null() { + unsafe { + *error = errno; + } + } + ret +} + #[no_mangle] pub extern "C" fn u_opendir_ocall(error: *mut c_int, pathname: *const c_char) -> *mut DIR { let mut errno = 0; diff --git a/sgx_ustdc/file.c b/sgx_ustdc/file.c index 33030158a..2a3fa7c34 100644 --- a/sgx_ustdc/file.c +++ b/sgx_ustdc/file.c @@ -47,6 +47,15 @@ int u_open64_ocall(int *error, const char *path, int oflag, int mode) return ret; } +int u_openat_ocall(int *error, int dirfd, const char *pathname, int flags) +{ + int ret = openat(dirfd, pathname, flags); + if (error) { + *error = ret == -1 ? errno : 0; + } + return ret; +} + int u_fstat_ocall(int *error, int fd, struct stat *buf) { int ret = fstat(fd, buf); @@ -200,6 +209,15 @@ int u_link_ocall(int *error, const char *oldpath, const char *newpath) return ret; } +int u_unlinkat_ocall(int *error, int dirfd, const char *pathname, int flags) +{ + int ret = unlinkat(dirfd, pathname, flags); + if (error) { + *error = ret == -1 ? errno : 0; + } + return ret; +} + int u_linkat_ocall(int *error, int olddirfd, const char *oldpath, int newdirfd, const char *newpath, int flags) { int ret = linkat(olddirfd, oldpath, newdirfd, newpath, flags); @@ -272,7 +290,16 @@ int u_rmdir_ocall(int *error, const char *pathname) return ret; } -void *u_opendir_ocall(int *error, const char *pathname) +DIR *u_fdopendir_ocall(int *error, int fd) +{ + DIR *ret = fdopendir(fd); + if (error) { + *error = ret == NULL ? errno : 0; + } + return ret; +} + +DIR *u_opendir_ocall(int *error, const char *pathname) { DIR *ret = opendir(pathname); if (error) { diff --git a/xargo/sgx_tstd/Cargo.toml b/xargo/sgx_tstd/Cargo.toml index 391c5b1fa..7a1c23c9d 100644 --- a/xargo/sgx_tstd/Cargo.toml +++ b/xargo/sgx_tstd/Cargo.toml @@ -3,7 +3,7 @@ name = "std" version = "0.0.0" authors = ["The Teaclave Authors"] build = "build.rs" -edition = "2018" +edition = "2021" [lib] name = "std" diff --git a/xargo/x86_64-unknown-linux-sgx.json b/xargo/x86_64-unknown-linux-sgx.json index 69b38be21..53f104e25 100644 --- a/xargo/x86_64-unknown-linux-sgx.json +++ b/xargo/x86_64-unknown-linux-sgx.json @@ -1,13 +1,13 @@ { "arch": "x86_64", "cpu": "x86-64", + "crt-static-respected": true, "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128", "dynamic-linking": true, "env": "sgx", - "exe-allocation-crate": "alloc_system", "executables": true, - "has-elf-tls": true, "has-rpath": true, + "has-thread-local": true, "linker-flavor": "gcc", "linker-is-gnu": true, "llvm-target": "x86_64-unknown-linux-gnu", @@ -30,6 +30,13 @@ 1 ] }, + "supported-sanitizers": [ + "address", + "cfi", + "leak", + "memory", + "thread" + ], "target-c-int-width": "32", "target-endian": "little", "target-family": "unix",