diff options
Diffstat (limited to 'src/rust')
34 files changed, 548 insertions, 319 deletions
diff --git a/src/rust/.rustfmt.toml b/src/rust/.rustfmt.toml index f25bd51883..4ff839dcf3 100644 --- a/src/rust/.rustfmt.toml +++ b/src/rust/.rustfmt.toml @@ -1,2 +1,12 @@ -max_width = 80 -comment_width = 80 +max_width = 100 +hard_tabs = false +tab_spaces = 4 +newline_style = "Unix" +#use_small_heuristics = "Default" +reorder_imports = true +reorder_modules = true +remove_nested_parens = true +merge_derives = true +use_try_shorthand = false +use_field_init_shorthand = false +force_explicit_abi = true diff --git a/src/rust/Cargo.toml b/src/rust/Cargo.toml index c3e44d2a79..e399dbb33a 100644 --- a/src/rust/Cargo.toml +++ b/src/rust/Cargo.toml @@ -14,3 +14,18 @@ members = [ debug = true panic = "abort" +[features] +default = [] +# If this feature is enabled, test code which calls Tor C code from Rust will +# execute with `cargo test`. Due to numerous linker issues (#25386), this is +# currently disabled by default. Crates listed here are those which, in their +# unittests, doctests, and/or integration tests, call C code. +test-c-from-rust = [ + "crypto/test-c-from-rust", +] + +# We have to define a feature here because doctests don't get cfg(test), +# and we need to disable some C dependencies when running the doctests +# because of the various linker issues. See +# https://github.com/rust-lang/rust/issues/45599 +test_linking_hack = [] diff --git a/src/rust/build.rs b/src/rust/build.rs index b943aa5535..123d5c0682 100644 --- a/src/rust/build.rs +++ b/src/rust/build.rs @@ -10,14 +10,12 @@ use std::collections::HashMap; use std::env; use std::fs::File; -use std::io::prelude::*; use std::io; +use std::io::prelude::*; use std::path::PathBuf; /// Wrapper around a key-value map. -struct Config( - HashMap<String,String> -); +struct Config(HashMap<String, String>); /// Locate a config.rust file generated by autoconf, starting in the OUT_DIR /// location provided by cargo and recursing up the directory tree. Note that @@ -31,9 +29,9 @@ fn find_cfg() -> io::Result<String> { return Ok(path.to_str().unwrap().to_owned()); } path.pop(); // remove config.rust - if ! path.pop() { // can't remove last part of directory - return Err(io::Error::new(io::ErrorKind::NotFound, - "No config.rust")); + if !path.pop() { + // can't remove last part of directory + return Err(io::Error::new(io::ErrorKind::NotFound, "No config.rust")); } } } @@ -55,12 +53,11 @@ impl Config { } let idx = match s.find("=") { None => { - return Err(io::Error::new(io::ErrorKind::InvalidData, - "missing =")); - }, - Some(x) => x + return Err(io::Error::new(io::ErrorKind::InvalidData, "missing =")); + } + Some(x) => x, }; - let (var,eq_val) = s.split_at(idx); + let (var, eq_val) = s.split_at(idx); let val = &eq_val[1..]; map.insert(var.to_owned(), val.to_owned()); } @@ -70,34 +67,34 @@ impl Config { /// Return a reference to the value whose key is 'key'. /// /// Panics if 'key' is not found in the configuration. - fn get(&self, key : &str) -> &str { + fn get(&self, key: &str) -> &str { self.0.get(key).unwrap() } /// Add a dependency on a static C library that is part of Tor, by name. - fn component(&self, s : &str) { + fn component(&self, s: &str) { println!("cargo:rustc-link-lib=static={}", s); } /// Add a dependency on a native library that is not part of Tor, by name. - fn dependency(&self, s : &str) { + fn dependency(&self, s: &str) { println!("cargo:rustc-link-lib={}", s); } /// Add a link path, relative to Tor's build directory. - fn link_relpath(&self, s : &str) { + fn link_relpath(&self, s: &str) { let builddir = self.get("BUILDDIR"); println!("cargo:rustc-link-search=native={}/{}", builddir, s); } /// Add an absolute link path. - fn link_path(&self, s : &str) { + fn link_path(&self, s: &str) { println!("cargo:rustc-link-search=native={}", s); } /// Parse the CFLAGS in s, looking for -l and -L items, and adding /// rust configuration as appropriate. - fn from_cflags(&self, s : &str) { + fn from_cflags(&self, s: &str) { let mut next_is_lib = false; let mut next_is_path = false; for ent in self.get(s).split_whitespace() { @@ -138,8 +135,7 @@ pub fn main() { cfg.from_cflags("TOR_LDFLAGS_openssl"); cfg.from_cflags("TOR_LDFLAGS_libevent"); - cfg.link_relpath("src/common"); - cfg.link_relpath("src/ext/keccak-tiny"); + cfg.link_relpath("src/lib"); cfg.link_relpath("src/ext/keccak-tiny"); cfg.link_relpath("src/ext/ed25519/ref10"); cfg.link_relpath("src/ext/ed25519/donna"); @@ -149,11 +145,25 @@ pub fn main() { // will have dependencies on all the other rust packages that // tor uses. We must be careful with factoring and dependencies // moving forward! - cfg.component("or-crypto-testing"); - cfg.component("or-ctime-testing"); - cfg.component("or-testing"); - cfg.component("or-event-testing"); - cfg.component("or-ctime-testing"); + cfg.component("tor-crypt-ops-testing"); + cfg.component("tor-sandbox-testing"); + cfg.component("tor-encoding-testing"); + cfg.component("tor-fs-testing"); + cfg.component("tor-time-testing"); + cfg.component("tor-net-testing"); + cfg.component("tor-thread-testing"); + cfg.component("tor-memarea-testing"); + cfg.component("tor-log-testing"); + cfg.component("tor-lock-testing"); + cfg.component("tor-fdio-testing"); + cfg.component("tor-container-testing"); + cfg.component("tor-smartlist-core-testing"); + cfg.component("tor-string-testing"); + cfg.component("tor-malloc"); + cfg.component("tor-wallclock"); + cfg.component("tor-err-testing"); + cfg.component("tor-intmath-testing"); + cfg.component("tor-ctime-testing"); cfg.component("curve25519_donna"); cfg.component("keccak-tiny"); cfg.component("ed25519_ref10"); @@ -162,6 +172,7 @@ pub fn main() { cfg.from_cflags("TOR_ZLIB_LIBS"); cfg.from_cflags("TOR_LIB_MATH"); + cfg.from_cflags("NSS_LIBS"); cfg.from_cflags("TOR_OPENSSL_LIBS"); cfg.from_cflags("TOR_LIBEVENT_LIBS"); cfg.from_cflags("TOR_LIB_WS32"); @@ -171,7 +182,7 @@ pub fn main() { cfg.from_cflags("TOR_LZMA_LIBS"); cfg.from_cflags("TOR_ZSTD_LIBS"); cfg.from_cflags("LIBS"); - }, + } _ => { panic!("No configuration in build.rs for package {}", package); } diff --git a/src/rust/crypto/Cargo.toml b/src/rust/crypto/Cargo.toml index 869e0d6256..6ebfe0dc11 100644 --- a/src/rust/crypto/Cargo.toml +++ b/src/rust/crypto/Cargo.toml @@ -26,3 +26,13 @@ rand = { version = "=0.5.0-pre.2", default-features = false } rand_core = { version = "=0.2.0-pre.0", default-features = false } [features] +# If this feature is enabled, test code which calls Tor C code from Rust will +# execute with `cargo test`. Due to numerous linker issues (#25386), this is +# currently disabled by default. +test-c-from-rust = [] + +# We have to define a feature here because doctests don't get cfg(test), +# and we need to disable some C dependencies when running the doctests +# because of the various linker issues. See +# https://github.com/rust-lang/rust/issues/45599 +test_linking_hack = [] diff --git a/src/rust/crypto/digests/sha2.rs b/src/rust/crypto/digests/sha2.rs index 03e0843dc0..55d0027665 100644 --- a/src/rust/crypto/digests/sha2.rs +++ b/src/rust/crypto/digests/sha2.rs @@ -6,17 +6,17 @@ pub use digest::Digest; +use digest::generic_array::typenum::U32; +use digest::generic_array::typenum::U64; +use digest::generic_array::GenericArray; use digest::BlockInput; use digest::FixedOutput; use digest::Input; -use digest::generic_array::GenericArray; -use digest::generic_array::typenum::U32; -use digest::generic_array::typenum::U64; -use external::crypto_digest::CryptoDigest; -use external::crypto_digest::DigestAlgorithm; use external::crypto_digest::get_256_bit_digest; use external::crypto_digest::get_512_bit_digest; +use external::crypto_digest::CryptoDigest; +use external::crypto_digest::DigestAlgorithm; pub use external::crypto_digest::DIGEST256_LEN; pub use external::crypto_digest::DIGEST512_LEN; @@ -54,7 +54,9 @@ pub struct Sha256 { /// A new `Sha256` digest. impl Default for Sha256 { fn default() -> Sha256 { - Sha256{ engine: CryptoDigest::new(Some(DigestAlgorithm::SHA2_256)) } + Sha256 { + engine: CryptoDigest::new(Some(DigestAlgorithm::SHA2_256)), + } } } @@ -121,7 +123,9 @@ pub struct Sha512 { /// A new `Sha512` digest. impl Default for Sha512 { fn default() -> Sha512 { - Sha512{ engine: CryptoDigest::new(Some(DigestAlgorithm::SHA2_512)) } + Sha512 { + engine: CryptoDigest::new(Some(DigestAlgorithm::SHA2_512)), + } } } @@ -165,22 +169,27 @@ impl FixedOutput for Sha512 { #[cfg(test)] mod test { + #[cfg(feature = "test-c-from-rust")] use digest::Digest; + #[cfg(feature = "test-c-from-rust")] use super::*; + #[cfg(feature = "test-c-from-rust")] #[test] fn sha256_default() { let _: Sha256 = Sha256::default(); } + #[cfg(feature = "test-c-from-rust")] #[test] fn sha256_digest() { let mut h: Sha256 = Sha256::new(); let mut result: [u8; DIGEST256_LEN] = [0u8; DIGEST256_LEN]; - let expected = [151, 223, 53, 136, 181, 163, 242, 75, 171, 195, - 133, 27, 55, 47, 11, 167, 26, 157, 205, 222, 212, - 59, 20, 185, 208, 105, 97, 191, 193, 112, 125, 157]; + let expected = [ + 151, 223, 53, 136, 181, 163, 242, 75, 171, 195, 133, 27, 55, 47, 11, 167, 26, 157, 205, + 222, 212, 59, 20, 185, 208, 105, 97, 191, 193, 112, 125, 157, + ]; h.input(b"foo"); h.input(b"bar"); @@ -193,21 +202,24 @@ mod test { assert_eq!(result, expected); } + #[cfg(feature = "test-c-from-rust")] #[test] fn sha512_default() { let _: Sha512 = Sha512::default(); } + #[cfg(feature = "test-c-from-rust")] #[test] fn sha512_digest() { let mut h: Sha512 = Sha512::new(); let mut result: [u8; DIGEST512_LEN] = [0u8; DIGEST512_LEN]; - let expected = [203, 55, 124, 16, 176, 245, 166, 44, 128, 54, 37, 167, - 153, 217, 233, 8, 190, 69, 231, 103, 245, 209, 71, 212, 116, - 73, 7, 203, 5, 89, 122, 164, 237, 211, 41, 160, 175, 20, 122, - 221, 12, 244, 24, 30, 211, 40, 250, 30, 121, 148, 38, 88, 38, - 179, 237, 61, 126, 246, 240, 103, 202, 153, 24, 90]; + let expected = [ + 203, 55, 124, 16, 176, 245, 166, 44, 128, 54, 37, 167, 153, 217, 233, 8, 190, 69, 231, + 103, 245, 209, 71, 212, 116, 73, 7, 203, 5, 89, 122, 164, 237, 211, 41, 160, 175, 20, + 122, 221, 12, 244, 24, 30, 211, 40, 250, 30, 121, 148, 38, 88, 38, 179, 237, 61, 126, + 246, 240, 103, 202, 153, 24, 90, + ]; h.input(b"foo"); h.input(b"bar"); diff --git a/src/rust/crypto/lib.rs b/src/rust/crypto/lib.rs index f72a859dd7..4eceb4cbd1 100644 --- a/src/rust/crypto/lib.rs +++ b/src/rust/crypto/lib.rs @@ -24,7 +24,8 @@ //! assert!(result == [b'X'; DIGEST256_LEN]); //! ``` -#[deny(missing_docs)] +// XXX: add missing docs +//#![deny(missing_docs)] // External crates from cargo or TOR_RUST_DEPENDENCIES. extern crate digest; @@ -41,5 +42,5 @@ extern crate external; #[macro_use] extern crate tor_log; -pub mod digests; // Unfortunately named "digests" plural to avoid name conflict with the digest crate +pub mod digests; // Unfortunately named "digests" plural to avoid name conflict with the digest crate pub mod rand; diff --git a/src/rust/crypto/rand/rng.rs b/src/rust/crypto/rand/rng.rs index 07a0a7bdc7..64ceb22424 100644 --- a/src/rust/crypto/rand/rng.rs +++ b/src/rust/crypto/rand/rng.rs @@ -12,15 +12,15 @@ mod internal { use std::u64; + use rand_core::impls::next_u32_via_fill; + use rand_core::impls::next_u64_via_fill; use rand_core::CryptoRng; use rand_core::Error; use rand_core::RngCore; - use rand_core::impls::next_u32_via_fill; - use rand_core::impls::next_u64_via_fill; use external::c_tor_crypto_rand; - use external::c_tor_crypto_strongest_rand; use external::c_tor_crypto_seed_rng; + use external::c_tor_crypto_strongest_rand; use tor_log::LogDomain; use tor_log::LogSeverity; @@ -45,12 +45,15 @@ mod internal { #[allow(dead_code)] pub fn new() -> Self { if !c_tor_crypto_seed_rng() { - tor_log_msg!(LogSeverity::Warn, LogDomain::General, - "TorRng::from_seed()", - "The RNG could not be seeded!"); + tor_log_msg!( + LogSeverity::Warn, + LogDomain::General, + "TorRng::from_seed()", + "The RNG could not be seeded!" + ); } // XXX also log success at info level —isis - TorRng{ _unused: [0u8; 0] } + TorRng { _unused: [0u8; 0] } } } @@ -92,12 +95,15 @@ mod internal { #[allow(dead_code)] pub fn new() -> Self { if !c_tor_crypto_seed_rng() { - tor_log_msg!(LogSeverity::Warn, LogDomain::General, - "TorStrongestRng::from_seed()", - "The RNG could not be seeded!"); + tor_log_msg!( + LogSeverity::Warn, + LogDomain::General, + "TorStrongestRng::from_seed()", + "The RNG could not be seeded!" + ); } // XXX also log success at info level —isis - TorStrongestRng{ _unused: [0u8; 0] } + TorStrongestRng { _unused: [0u8; 0] } } } @@ -137,4 +143,3 @@ mod internal { // Finally, expose the public functionality of whichever appropriate internal // module. pub use self::internal::*; - diff --git a/src/rust/external/Cargo.toml b/src/rust/external/Cargo.toml index 60ec03be40..4735144ee6 100644 --- a/src/rust/external/Cargo.toml +++ b/src/rust/external/Cargo.toml @@ -14,3 +14,9 @@ name = "external" path = "lib.rs" crate_type = ["rlib", "staticlib"] +[features] +# We have to define a feature here because doctests don't get cfg(test), +# and we need to disable some C dependencies when running the doctests +# because of the various linker issues. See +# https://github.com/rust-lang/rust/issues/45599 +test_linking_hack = [] diff --git a/src/rust/external/crypto_digest.rs b/src/rust/external/crypto_digest.rs index 3e8801f203..ebcf2e88a9 100644 --- a/src/rust/external/crypto_digest.rs +++ b/src/rust/external/crypto_digest.rs @@ -125,15 +125,35 @@ type smartlist_t = Stringlist; #[allow(dead_code)] extern "C" { fn crypto_digest(digest: *mut c_char, m: *const c_char, len: size_t) -> c_int; - fn crypto_digest256(digest: *mut c_char, m: *const c_char, len: size_t, - algorithm: digest_algorithm_t) -> c_int; - fn crypto_digest512(digest: *mut c_char, m: *const c_char, len: size_t, - algorithm: digest_algorithm_t) -> c_int; - fn crypto_common_digests(ds_out: *mut common_digests_t, m: *const c_char, len: size_t) -> c_int; - fn crypto_digest_smartlist_prefix(digest_out: *mut c_char, len_out: size_t, prepend: *const c_char, - lst: *const smartlist_t, append: *const c_char, alg: digest_algorithm_t); - fn crypto_digest_smartlist(digest_out: *mut c_char, len_out: size_t, - lst: *const smartlist_t, append: *const c_char, alg: digest_algorithm_t); + fn crypto_digest256( + digest: *mut c_char, + m: *const c_char, + len: size_t, + algorithm: digest_algorithm_t, + ) -> c_int; + fn crypto_digest512( + digest: *mut c_char, + m: *const c_char, + len: size_t, + algorithm: digest_algorithm_t, + ) -> c_int; + fn crypto_common_digests(ds_out: *mut common_digests_t, m: *const c_char, len: size_t) + -> c_int; + fn crypto_digest_smartlist_prefix( + digest_out: *mut c_char, + len_out: size_t, + prepend: *const c_char, + lst: *const smartlist_t, + append: *const c_char, + alg: digest_algorithm_t, + ); + fn crypto_digest_smartlist( + digest_out: *mut c_char, + len_out: size_t, + lst: *const smartlist_t, + append: *const c_char, + alg: digest_algorithm_t, + ); fn crypto_digest_algorithm_get_name(alg: digest_algorithm_t) -> *const c_char; fn crypto_digest_algorithm_get_length(alg: digest_algorithm_t) -> size_t; fn crypto_digest_algorithm_parse_name(name: *const c_char) -> c_int; @@ -145,11 +165,21 @@ extern "C" { fn crypto_digest_get_digest(digest: *mut crypto_digest_t, out: *mut c_char, out_len: size_t); fn crypto_digest_dup(digest: *const crypto_digest_t) -> *mut crypto_digest_t; fn crypto_digest_assign(into: *mut crypto_digest_t, from: *const crypto_digest_t); - fn crypto_hmac_sha256(hmac_out: *mut c_char, key: *const c_char, key_len: size_t, - msg: *const c_char, msg_len: size_t); - fn crypto_mac_sha3_256(mac_out: *mut uint8_t, len_out: size_t, - key: *const uint8_t, key_len: size_t, - msg: *const uint8_t, msg_len: size_t); + fn crypto_hmac_sha256( + hmac_out: *mut c_char, + key: *const c_char, + key_len: size_t, + msg: *const c_char, + msg_len: size_t, + ); + fn crypto_mac_sha3_256( + mac_out: *mut uint8_t, + len_out: size_t, + key: *const uint8_t, + key_len: size_t, + msg: *const uint8_t, + msg_len: size_t, + ); fn crypto_xof_new() -> *mut crypto_xof_t; fn crypto_xof_add_bytes(xof: *mut crypto_xof_t, data: *const uint8_t, len: size_t); fn crypto_xof_squeeze_bytes(xof: *mut crypto_xof_t, out: *mut uint8_t, len: size_t); @@ -238,12 +268,12 @@ impl CryptoDigest { unsafe { // XXX This is a pretty awkward API to use from Rust... digest = match algo { - DIGEST_SHA1 => crypto_digest_new(), - DIGEST_SHA256 => crypto_digest256_new(DIGEST_SHA256), + DIGEST_SHA1 => crypto_digest_new(), + DIGEST_SHA256 => crypto_digest256_new(DIGEST_SHA256), DIGEST_SHA3_256 => crypto_digest256_new(DIGEST_SHA3_256), - DIGEST_SHA512 => crypto_digest512_new(DIGEST_SHA512), + DIGEST_SHA512 => crypto_digest512_new(DIGEST_SHA512), DIGEST_SHA3_512 => crypto_digest512_new(DIGEST_SHA3_512), - _ => abort(), + _ => abort(), } } } @@ -285,9 +315,11 @@ impl CryptoDigest { /// * `crypto_digest_add_bytes` pub fn add_bytes(&self, bytes: &[u8]) { unsafe { - crypto_digest_add_bytes(self.0 as *mut crypto_digest_t, - bytes.as_ptr() as *const c_char, - bytes.len() as size_t) + crypto_digest_add_bytes( + self.0 as *mut crypto_digest_t, + bytes.as_ptr() as *const c_char, + bytes.len() as size_t, + ) } } } @@ -331,9 +363,11 @@ pub fn get_256_bit_digest(digest: CryptoDigest) -> [u8; DIGEST256_LEN] { let mut buffer: [u8; DIGEST256_LEN] = [0u8; DIGEST256_LEN]; unsafe { - crypto_digest_get_digest(digest.0, - buffer.as_mut_ptr() as *mut c_char, - DIGEST256_LEN as size_t); + crypto_digest_get_digest( + digest.0, + buffer.as_mut_ptr() as *mut c_char, + DIGEST256_LEN as size_t, + ); if buffer.as_ptr().is_null() { abort(); @@ -373,9 +407,11 @@ pub fn get_512_bit_digest(digest: CryptoDigest) -> [u8; DIGEST512_LEN] { let mut buffer: [u8; DIGEST512_LEN] = [0u8; DIGEST512_LEN]; unsafe { - crypto_digest_get_digest(digest.0, - buffer.as_mut_ptr() as *mut c_char, - DIGEST512_LEN as size_t); + crypto_digest_get_digest( + digest.0, + buffer.as_mut_ptr() as *mut c_char, + DIGEST512_LEN as size_t, + ); if buffer.as_ptr().is_null() { abort(); @@ -390,17 +426,29 @@ mod test { #[test] fn test_layout_common_digests_t() { - assert_eq!(::std::mem::size_of::<common_digests_t>(), 64usize, - concat!("Size of: ", stringify!(common_digests_t))); - assert_eq!(::std::mem::align_of::<common_digests_t>(), 1usize, - concat!("Alignment of ", stringify!(common_digests_t))); + assert_eq!( + ::std::mem::size_of::<common_digests_t>(), + 64usize, + concat!("Size of: ", stringify!(common_digests_t)) + ); + assert_eq!( + ::std::mem::align_of::<common_digests_t>(), + 1usize, + concat!("Alignment of ", stringify!(common_digests_t)) + ); } #[test] fn test_layout_crypto_digest_t() { - assert_eq!(::std::mem::size_of::<crypto_digest_t>(), 0usize, - concat!("Size of: ", stringify!(crypto_digest_t))); - assert_eq!(::std::mem::align_of::<crypto_digest_t>(), 1usize, - concat!("Alignment of ", stringify!(crypto_digest_t))); + assert_eq!( + ::std::mem::size_of::<crypto_digest_t>(), + 0usize, + concat!("Size of: ", stringify!(crypto_digest_t)) + ); + assert_eq!( + ::std::mem::align_of::<crypto_digest_t>(), + 1usize, + concat!("Alignment of ", stringify!(crypto_digest_t)) + ); } } diff --git a/src/rust/external/crypto_rand.rs b/src/rust/external/crypto_rand.rs index af1ade0161..b68f98b358 100644 --- a/src/rust/external/crypto_rand.rs +++ b/src/rust/external/crypto_rand.rs @@ -2,7 +2,7 @@ // Copyright (c) 2018, isis agora lovecruft // See LICENSE for licensing information -//! Bindings to external (P)RNG interfaces and utilities in +//! Bindings to external (P)RNG interfaces and utilities in //! src/common/crypto_rand.[ch]. //! //! We wrap our C implementations in src/common/crypto_rand.[ch] here in order @@ -80,8 +80,5 @@ pub fn c_tor_crypto_rand_time_range(min: &Duration, max: &Duration) -> Duration /// Return a pseudorandom 64-bit float, chosen uniformly from the range [0.0, 1.0). pub fn c_tor_crypto_rand_double() -> f64 { - unsafe { - crypto_rand_double() - } + unsafe { crypto_rand_double() } } - diff --git a/src/rust/external/external.rs b/src/rust/external/external.rs index b9e17f021d..d342fe096e 100644 --- a/src/rust/external/external.rs +++ b/src/rust/external/external.rs @@ -1,17 +1,14 @@ -// Copyright (c) 2016-2017, The Tor Project, Inc. */ +// Copyright (c) 2016-2018, The Tor Project, Inc. */ // See LICENSE for licensing information */ use libc::{c_char, c_int}; use std::ffi::CString; extern "C" { - fn tor_version_as_new_as( - platform: *const c_char, - cutoff: *const c_char, - ) -> c_int; + fn tor_version_as_new_as(platform: *const c_char, cutoff: *const c_char) -> c_int; } -/// Wrap calls to tor_version_as_new_as, defined in src/or/routerparse.c +/// Wrap calls to tor_version_as_new_as, defined in routerparse.c pub fn c_tor_version_as_new_as(platform: &str, cutoff: &str) -> bool { // CHK: These functions should log a warning if an error occurs. This // can be added when integration with tor's logger is added to rust @@ -25,9 +22,17 @@ pub fn c_tor_version_as_new_as(platform: &str, cutoff: &str) -> bool { Err(_) => return false, }; - let result: c_int = unsafe { - tor_version_as_new_as(c_platform.as_ptr(), c_cutoff.as_ptr()) - }; + let result: c_int = unsafe { tor_version_as_new_as(c_platform.as_ptr(), c_cutoff.as_ptr()) }; result == 1 } + +extern "C" { + fn tor_is_using_nss() -> c_int; +} + +/// Return true if Tor was built to use NSS. +pub fn c_tor_is_using_nss() -> bool +{ + 0 != unsafe { tor_is_using_nss() } +} diff --git a/src/rust/protover/Cargo.toml b/src/rust/protover/Cargo.toml index a8480e142a..2f7783e76c 100644 --- a/src/rust/protover/Cargo.toml +++ b/src/rust/protover/Cargo.toml @@ -4,6 +4,11 @@ version = "0.0.1" name = "protover" [features] +# We have to define a feature here because doctests don't get cfg(test), +# and we need to disable some C dependencies when running the doctests +# because of the various linker issues. See +# https://github.com/rust-lang/rust/issues/45599 +test_linking_hack = [] [dependencies] libc = "=0.2.39" @@ -27,4 +32,3 @@ path = "../tor_log" name = "protover" path = "lib.rs" crate_type = ["rlib", "staticlib"] - diff --git a/src/rust/protover/errors.rs b/src/rust/protover/errors.rs index d9dc73381f..f26a48b019 100644 --- a/src/rust/protover/errors.rs +++ b/src/rust/protover/errors.rs @@ -25,22 +25,33 @@ pub enum ProtoverError { impl Display for ProtoverError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { - ProtoverError::Overlap - => write!(f, "Two or more (low, high) protover ranges would overlap once expanded."), - ProtoverError::LowGreaterThanHigh - => write!(f, "The low in a (low, high) protover range was greater than high."), - ProtoverError::Unparseable - => write!(f, "The protover string was unparseable."), - ProtoverError::ExceedsMax - => write!(f, "The high in a (low, high) protover range exceeds u32::MAX."), - ProtoverError::ExceedsExpansionLimit - => write!(f, "The protover string would exceed the maximum expansion limit."), - ProtoverError::UnknownProtocol - => write!(f, "A protocol in the protover string we attempted to parse is unknown."), - ProtoverError::ExceedsNameLimit - => write!(f, "An unrecognised protocol name was too long."), - ProtoverError::InvalidProtocol - => write!(f, "A protocol name includes invalid characters."), + ProtoverError::Overlap => write!( + f, + "Two or more (low, high) protover ranges would overlap once expanded." + ), + ProtoverError::LowGreaterThanHigh => write!( + f, + "The low in a (low, high) protover range was greater than high." + ), + ProtoverError::Unparseable => write!(f, "The protover string was unparseable."), + ProtoverError::ExceedsMax => write!( + f, + "The high in a (low, high) protover range exceeds u32::MAX." + ), + ProtoverError::ExceedsExpansionLimit => write!( + f, + "The protover string would exceed the maximum expansion limit." + ), + ProtoverError::UnknownProtocol => write!( + f, + "A protocol in the protover string we attempted to parse is unknown." + ), + ProtoverError::ExceedsNameLimit => { + write!(f, "An unrecognised protocol name was too long.") + } + ProtoverError::InvalidProtocol => { + write!(f, "A protocol name includes invalid characters.") + } } } } diff --git a/src/rust/protover/ffi.rs b/src/rust/protover/ffi.rs index e3e545db75..0c28d032c6 100644 --- a/src/rust/protover/ffi.rs +++ b/src/rust/protover/ffi.rs @@ -1,9 +1,9 @@ -// Copyright (c) 2016-2017, The Tor Project, Inc. */ +// Copyright (c) 2016-2018, The Tor Project, Inc. */ // See LICENSE for licensing information */ //! FFI functions, only to be called from C. //! -//! Equivalent C versions of this api are in `src/or/protover.c` +//! Equivalent C versions of this api are in `protover.c` use libc::{c_char, c_int, uint32_t}; use std::ffi::CStr; @@ -18,7 +18,7 @@ use protover::*; /// Translate C enums to Rust Proto enums, using the integer value of the C /// enum to map to its associated Rust enum. /// -/// C_RUST_COUPLED: src/or/protover.h `protocol_type_t` +/// C_RUST_COUPLED: protover.h `protocol_type_t` fn translate_to_rust(c_proto: uint32_t) -> Result<Protocol, ProtoverError> { match c_proto { 0 => Ok(Protocol::Link), @@ -42,7 +42,6 @@ pub extern "C" fn protover_all_supported( c_relay_version: *const c_char, missing_out: *mut *mut c_char, ) -> c_int { - if c_relay_version.is_null() { return 1; } @@ -58,13 +57,11 @@ pub extern "C" fn protover_all_supported( let relay_proto_entry: UnvalidatedProtoEntry = match UnvalidatedProtoEntry::from_str_any_len(relay_version) { - Ok(n) => n, - Err(_) => return 1, - }; - let maybe_unsupported: Option<UnvalidatedProtoEntry> = relay_proto_entry.all_supported(); + Ok(n) => n, + Err(_) => return 1, + }; - if maybe_unsupported.is_some() { - let unsupported: UnvalidatedProtoEntry = maybe_unsupported.unwrap(); + if let Some(unsupported) = relay_proto_entry.all_supported() { let c_unsupported: CString = match CString::new(unsupported.to_string()) { Ok(n) => n, Err(_) => return 1, @@ -100,23 +97,22 @@ pub extern "C" fn protocol_list_supports_protocol( Err(_) => return 1, }; let proto_entry: UnvalidatedProtoEntry = match protocol_list.parse() { - Ok(n) => n, + Ok(n) => n, Err(_) => return 0, }; let protocol: UnknownProtocol = match translate_to_rust(c_protocol) { Ok(n) => n.into(), Err(_) => return 0, }; - match proto_entry.supports_protocol(&protocol, &version) { - false => return 0, - true => return 1, + if proto_entry.supports_protocol(&protocol, &version) { + 1 + } else { + 0 } } #[no_mangle] -pub extern "C" fn protover_contains_long_protocol_names_( - c_protocol_list: *const c_char -) -> c_int { +pub extern "C" fn protover_contains_long_protocol_names_(c_protocol_list: *const c_char) -> c_int { if c_protocol_list.is_null() { return 1; } @@ -127,13 +123,10 @@ pub extern "C" fn protover_contains_long_protocol_names_( let protocol_list = match c_str.to_str() { Ok(n) => n, - Err(_) => return 1 + Err(_) => return 1, }; - let protocol_entry : Result<UnvalidatedProtoEntry,_> = - protocol_list.parse(); - - match protocol_entry { + match protocol_list.parse::<UnvalidatedProtoEntry>() { Ok(_) => 0, Err(_) => 1, } @@ -166,7 +159,7 @@ pub extern "C" fn protocol_list_supports_protocol_or_later( }; let proto_entry: UnvalidatedProtoEntry = match protocol_list.parse() { - Ok(n) => n, + Ok(n) => n, Err(_) => return 1, }; @@ -196,10 +189,8 @@ pub extern "C" fn protover_compute_vote( threshold: c_int, allow_long_proto_names: bool, ) -> *mut c_char { - if list.is_null() { - let empty = String::new(); - return allocate_and_copy_string(&empty); + return allocate_and_copy_string(""); } // Dereference of raw pointer requires an unsafe block. The pointer is @@ -209,13 +200,16 @@ pub extern "C" fn protover_compute_vote( let mut proto_entries: Vec<UnvalidatedProtoEntry> = Vec::new(); for datum in data { - let entry: UnvalidatedProtoEntry = match allow_long_proto_names { - true => match UnvalidatedProtoEntry::from_str_any_len(datum.as_str()) { - Ok(n) => n, - Err(_) => continue}, - false => match datum.parse() { - Ok(n) => n, - Err(_) => continue}, + let entry: UnvalidatedProtoEntry = if allow_long_proto_names { + match UnvalidatedProtoEntry::from_str_any_len(datum.as_str()) { + Ok(n) => n, + Err(_) => continue, + } + } else { + match datum.parse() { + Ok(n) => n, + Err(_) => continue, + } }; proto_entries.push(entry); } @@ -227,10 +221,7 @@ pub extern "C" fn protover_compute_vote( /// Provide an interface for C to translate arguments and return types for /// protover::is_supported_here #[no_mangle] -pub extern "C" fn protover_is_supported_here( - c_protocol: uint32_t, - version: uint32_t, -) -> c_int { +pub extern "C" fn protover_is_supported_here(c_protocol: uint32_t, version: uint32_t) -> c_int { let protocol = match translate_to_rust(c_protocol) { Ok(n) => n, Err(_) => return 0, diff --git a/src/rust/protover/lib.rs b/src/rust/protover/lib.rs index ce964196fd..9625cb58ad 100644 --- a/src/rust/protover/lib.rs +++ b/src/rust/protover/lib.rs @@ -1,4 +1,4 @@ -//! Copyright (c) 2016-2017, The Tor Project, Inc. */ +//! Copyright (c) 2016-2018, The Tor Project, Inc. */ //! See LICENSE for licensing information */ //! Versioning information for different pieces of the Tor protocol. @@ -22,18 +22,19 @@ //! protocols to develop independently, without having to claim compatibility //! with specific versions of Tor. -#[deny(missing_docs)] +// XXX: add missing docs +//#![deny(missing_docs)] +extern crate external; extern crate libc; extern crate smartlist; -extern crate external; extern crate tor_allocate; #[macro_use] extern crate tor_util; pub mod errors; +pub mod ffi; pub mod protoset; mod protover; -pub mod ffi; pub use protover::*; diff --git a/src/rust/protover/protoset.rs b/src/rust/protover/protoset.rs index 465b8f2850..c447186098 100644 --- a/src/rust/protover/protoset.rs +++ b/src/rust/protover/protoset.rs @@ -55,7 +55,7 @@ impl Default for ProtoSet { fn default() -> Self { let pairs: Vec<(Version, Version)> = Vec::new(); - ProtoSet{ pairs } + ProtoSet { pairs } } } @@ -75,7 +75,7 @@ impl<'a> ProtoSet { pairs.sort_unstable(); pairs.dedup(); - ProtoSet{ pairs }.is_ok() + ProtoSet { pairs }.is_ok() } } @@ -322,7 +322,7 @@ impl FromStr for ProtoSet { /// * there are greater than 2^16 version numbers to expand. /// /// # Examples - /// + /// /// ``` /// use std::str::FromStr; /// @@ -371,10 +371,10 @@ impl FromStr for ProtoSet { } else if p.contains('-') { let mut pair = p.splitn(2, '-'); - let low = pair.next().ok_or(ProtoverError::Unparseable)?; + let low = pair.next().ok_or(ProtoverError::Unparseable)?; let high = pair.next().ok_or(ProtoverError::Unparseable)?; - let lo: Version = low.parse().or(Err(ProtoverError::Unparseable))?; + let lo: Version = low.parse().or(Err(ProtoverError::Unparseable))?; let hi: Version = high.parse().or(Err(ProtoverError::Unparseable))?; if lo == u32::MAX || hi == u32::MAX { @@ -478,11 +478,11 @@ impl From<Vec<Version>> for ProtoSet { if has_range { let first: Version = match v.first() { Some(x) => *x, - None => continue, + None => continue, }; - let last: Version = match v.get(index) { + let last: Version = match v.get(index) { Some(x) => *x, - None => continue, + None => continue, }; debug_assert!(last == end, format!("last = {}, end = {}", last, end)); @@ -495,7 +495,7 @@ impl From<Vec<Version>> for ProtoSet { } else { let last: Version = match v.get(index) { Some(x) => *x, - None => continue, + None => continue, }; version_pairs.push((last, last)); v.remove(index); @@ -519,22 +519,22 @@ mod test { } macro_rules! assert_contains_each { - ($protoset:expr, $versions:expr) => ( + ($protoset:expr, $versions:expr) => { for version in $versions { assert!($protoset.contains(version)); } - ) + }; } macro_rules! test_protoset_contains_versions { - ($list:expr, $str:expr) => ( + ($list:expr, $str:expr) => { let versions: &[Version] = $list; let protoset: Result<ProtoSet, ProtoverError> = ProtoSet::from_str($str); assert!(protoset.is_ok()); let p = protoset.unwrap(); assert_contains_each!(p, versions); - ) + }; } #[test] @@ -594,26 +594,41 @@ mod test { #[test] fn test_versions_from_slice_overlap() { - assert_eq!(Err(ProtoverError::Overlap), ProtoSet::from_slice(&[(1, 3), (2, 4)])); + assert_eq!( + Err(ProtoverError::Overlap), + ProtoSet::from_slice(&[(1, 3), (2, 4)]) + ); } #[test] fn test_versions_from_str_max() { - assert_eq!(Err(ProtoverError::ExceedsMax), ProtoSet::from_str("4294967295")); + assert_eq!( + Err(ProtoverError::ExceedsMax), + ProtoSet::from_str("4294967295") + ); } #[test] fn test_versions_from_slice_max() { - assert_eq!(Err(ProtoverError::ExceedsMax), ProtoSet::from_slice(&[(4294967295, 4294967295)])); + assert_eq!( + Err(ProtoverError::ExceedsMax), + ProtoSet::from_slice(&[(4294967295, 4294967295)]) + ); } #[test] fn test_protoset_contains() { let protoset: ProtoSet = ProtoSet::from_slice(&[(1, 5), (7, 9), (13, 14)]).unwrap(); - for x in 1..6 { assert!(protoset.contains(&x), format!("should contain {}", x)); } - for x in 7..10 { assert!(protoset.contains(&x), format!("should contain {}", x)); } - for x in 13..15 { assert!(protoset.contains(&x), format!("should contain {}", x)); } + for x in 1..6 { + assert!(protoset.contains(&x), format!("should contain {}", x)); + } + for x in 7..10 { + assert!(protoset.contains(&x), format!("should contain {}", x)); + } + for x in 13..15 { + assert!(protoset.contains(&x), format!("should contain {}", x)); + } for x in [6, 10, 11, 12, 15, 42, 43, 44, 45, 1234584].iter() { assert!(!protoset.contains(&x), format!("should not contain {}", x)); @@ -624,7 +639,9 @@ mod test { fn test_protoset_contains_1_3() { let protoset: ProtoSet = ProtoSet::from_slice(&[(1, 3)]).unwrap(); - for x in 1..4 { assert!(protoset.contains(&x), format!("should contain {}", x)); } + for x in 1..4 { + assert!(protoset.contains(&x), format!("should contain {}", x)); + } } macro_rules! assert_protoset_from_vec_contains_all { @@ -650,7 +667,7 @@ mod test { #[test] fn test_protoset_from_vec_unordered() { - let v: Vec<Version> = vec!(2, 3, 8, 4, 3, 9, 7, 2); + let v: Vec<Version> = vec![2, 3, 8, 4, 3, 9, 7, 2]; let ps: ProtoSet = v.into(); assert_eq!(ps.to_string(), "2-4,7-9"); diff --git a/src/rust/protover/protover.rs b/src/rust/protover/protover.rs index 68027056c4..43822a3f15 100644 --- a/src/rust/protover/protover.rs +++ b/src/rust/protover/protover.rs @@ -1,8 +1,8 @@ -// Copyright (c) 2016-2017, The Tor Project, Inc. */ +// Copyright (c) 2016-2018, The Tor Project, Inc. */ // See LICENSE for licensing information */ -use std::collections::HashMap; use std::collections::hash_map; +use std::collections::HashMap; use std::ffi::CStr; use std::fmt; use std::str; @@ -12,28 +12,28 @@ use std::string::String; use external::c_tor_version_as_new_as; use errors::ProtoverError; -use protoset::Version; use protoset::ProtoSet; +use protoset::Version; /// The first version of Tor that included "proto" entries in its descriptors. /// Authorities should use this to decide whether to guess proto lines. /// /// C_RUST_COUPLED: -/// src/or/protover.h `FIRST_TOR_VERSION_TO_ADVERTISE_PROTOCOLS` +/// protover.h `FIRST_TOR_VERSION_TO_ADVERTISE_PROTOCOLS` const FIRST_TOR_VERSION_TO_ADVERTISE_PROTOCOLS: &'static str = "0.2.9.3-alpha"; /// The maximum number of subprotocol version numbers we will attempt to expand /// before concluding that someone is trying to DoS us /// -/// C_RUST_COUPLED: src/or/protover.c `MAX_PROTOCOLS_TO_EXPAND` -const MAX_PROTOCOLS_TO_EXPAND: usize = (1<<16); +/// C_RUST_COUPLED: protover.c `MAX_PROTOCOLS_TO_EXPAND` +const MAX_PROTOCOLS_TO_EXPAND: usize = (1 << 16); /// The maximum size an `UnknownProtocol`'s name may be. pub(crate) const MAX_PROTOCOL_NAME_LENGTH: usize = 100; /// Known subprotocols in Tor. Indicates which subprotocol a relay supports. /// -/// C_RUST_COUPLED: src/or/protover.h `protocol_type_t` +/// C_RUST_COUPLED: protover.h `protocol_type_t` #[derive(Clone, Hash, Eq, PartialEq, Debug)] pub enum Protocol { Cons, @@ -57,7 +57,7 @@ impl fmt::Display for Protocol { /// Translates a string representation of a protocol into a Proto type. /// Error if the string is an unrecognized protocol name. /// -/// C_RUST_COUPLED: src/or/protover.c `PROTOCOL_NAMES` +/// C_RUST_COUPLED: protover.c `PROTOCOL_NAMES` impl FromStr for Protocol { type Err = ProtoverError; @@ -124,6 +124,17 @@ impl From<Protocol> for UnknownProtocol { } } +#[cfg(feature="test_linking_hack")] +fn have_linkauth_v1() -> bool { + true +} + +#[cfg(not(feature="test_linking_hack"))] +fn have_linkauth_v1() -> bool { + use external::c_tor_is_using_nss; + ! c_tor_is_using_nss() +} + /// Get a CStr representation of current supported protocols, for /// passing to C, or for converting to a `&str` for Rust. /// @@ -139,18 +150,33 @@ impl From<Protocol> for UnknownProtocol { /// Rust code can use the `&'static CStr` as a normal `&'a str` by /// calling `protover::get_supported_protocols`. /// -// C_RUST_COUPLED: src/or/protover.c `protover_get_supported_protocols` +// C_RUST_COUPLED: protover.c `protover_get_supported_protocols` pub(crate) fn get_supported_protocols_cstr() -> &'static CStr { - cstr!("Cons=1-2 \ - Desc=1-2 \ - DirCache=1-2 \ - HSDir=1-2 \ - HSIntro=3-4 \ - HSRend=1-2 \ - Link=1-5 \ - LinkAuth=1,3 \ - Microdesc=1-2 \ - Relay=1-2") + if ! have_linkauth_v1() { + cstr!("Cons=1-2 \ + Desc=1-2 \ + DirCache=1-2 \ + HSDir=1-2 \ + HSIntro=3-4 \ + HSRend=1-2 \ + Link=1-5 \ + LinkAuth=3 \ + Microdesc=1-2 \ + Relay=1-2" + ) + } else { + cstr!("Cons=1-2 \ + Desc=1-2 \ + DirCache=1-2 \ + HSDir=1-2 \ + HSIntro=3-4 \ + HSRend=1-2 \ + Link=1-5 \ + LinkAuth=1,3 \ + Microdesc=1-2 \ + Relay=1-2" + ) + } } /// A map of protocol names to the versions of them which are supported. @@ -159,7 +185,7 @@ pub struct ProtoEntry(HashMap<Protocol, ProtoSet>); impl Default for ProtoEntry { fn default() -> ProtoEntry { - ProtoEntry( HashMap::new() ) + ProtoEntry(HashMap::new()) } } @@ -213,9 +239,7 @@ impl FromStr for ProtoEntry { /// /// # Returns /// - /// A `Result` whose `Ok` value is a `ProtoEntry`, where the - /// first element is the subprotocol type (see `protover::Protocol`) and the last - /// element is an ordered set of `(low, high)` unique version numbers which are supported. + /// A `Result` whose `Ok` value is a `ProtoEntry`. /// Otherwise, the `Err` value of this `Result` is a `ProtoverError`. fn from_str(protocol_entry: &str) -> Result<ProtoEntry, ProtoverError> { let mut proto_entry: ProtoEntry = ProtoEntry::default(); @@ -249,7 +273,7 @@ impl FromStr for ProtoEntry { /// Generate an implementation of `ToString` for either a `ProtoEntry` or an /// `UnvalidatedProtoEntry`. macro_rules! impl_to_string_for_proto_entry { - ($t:ty) => ( + ($t:ty) => { impl ToString for $t { fn to_string(&self) -> String { let mut parts: Vec<String> = Vec::new(); @@ -261,7 +285,7 @@ macro_rules! impl_to_string_for_proto_entry { parts.join(" ") } } - ) + }; } impl_to_string_for_proto_entry!(ProtoEntry); @@ -275,7 +299,7 @@ pub struct UnvalidatedProtoEntry(HashMap<UnknownProtocol, ProtoSet>); impl Default for UnvalidatedProtoEntry { fn default() -> UnvalidatedProtoEntry { - UnvalidatedProtoEntry( HashMap::new() ) + UnvalidatedProtoEntry(HashMap::new()) } } @@ -333,7 +357,7 @@ impl UnvalidatedProtoEntry { pub fn all_supported(&self) -> Option<UnvalidatedProtoEntry> { let mut unsupported: UnvalidatedProtoEntry = UnvalidatedProtoEntry::default(); let supported: ProtoEntry = match ProtoEntry::supported() { - Ok(x) => x, + Ok(x) => x, Err(_) => return None, }; @@ -459,11 +483,12 @@ impl UnvalidatedProtoEntry { /// following are true: /// /// * If a protocol name is an empty string, e.g. `"Cons=1,3 =3-5"`. - /// * If a protocol name cannot be parsed as utf-8. - /// * If the version numbers are an empty string, e.g. `"Cons="`. - fn parse_protocol_and_version_str<'a>(protocol_string: &'a str) - -> Result<Vec<(&'a str, &'a str)>, ProtoverError> - { + /// * If an entry has no equals sign, e.g. `"Cons=1,3 Desc"`. + /// * If there is leading or trailing whitespace, e.g. `" Cons=1,3 Link=3"`. + /// * If there is any other extra whitespice, e.g. `"Cons=1,3 Link=3"`. + fn parse_protocol_and_version_str<'a>( + protocol_string: &'a str, + ) -> Result<Vec<(&'a str, &'a str)>, ProtoverError> { let mut protovers: Vec<(&str, &str)> = Vec::new(); for subproto in protocol_string.split(' ') { @@ -499,11 +524,9 @@ impl FromStr for UnvalidatedProtoEntry { /// /// # Returns /// - /// A `Result` whose `Ok` value is a `ProtoSet` holding all of the - /// unique version numbers. + /// A `Result` whose `Ok` value is an `UnvalidatedProtoEntry`. /// - /// The returned `Result`'s `Err` value is an `ProtoverError` whose `Display` - /// impl has a description of the error. + /// The returned `Result`'s `Err` value is an `ProtoverError`. /// /// # Errors /// @@ -530,9 +553,9 @@ impl FromStr for UnvalidatedProtoEntry { impl UnvalidatedProtoEntry { /// Create an `UnknownProtocol`, ignoring whether or not it /// exceeds MAX_PROTOCOL_NAME_LENGTH. - pub(crate) fn from_str_any_len(protocol_string: &str) - -> Result<UnvalidatedProtoEntry, ProtoverError> - { + pub(crate) fn from_str_any_len( + protocol_string: &str, + ) -> Result<UnvalidatedProtoEntry, ProtoverError> { let mut parsed: UnvalidatedProtoEntry = UnvalidatedProtoEntry::default(); let parts: Vec<(&str, &str)> = UnvalidatedProtoEntry::parse_protocol_and_version_str(protocol_string)?; @@ -567,11 +590,11 @@ impl From<ProtoEntry> for UnvalidatedProtoEntry { /// The "protocols" are *not* guaranteed to be known/supported `Protocol`s, in /// order to allow new subprotocols to be introduced even if Directory /// Authorities don't yet know of them. -pub struct ProtoverVote( HashMap<UnknownProtocol, HashMap<Version, usize>> ); +pub struct ProtoverVote(HashMap<UnknownProtocol, HashMap<Version, usize>>); impl Default for ProtoverVote { fn default() -> ProtoverVote { - ProtoverVote( HashMap::new() ) + ProtoverVote(HashMap::new()) } } @@ -585,9 +608,10 @@ impl IntoIterator for ProtoverVote { } impl ProtoverVote { - pub fn entry(&mut self, key: UnknownProtocol) - -> hash_map::Entry<UnknownProtocol, HashMap<Version, usize>> - { + pub fn entry( + &mut self, + key: UnknownProtocol, + ) -> hash_map::Entry<UnknownProtocol, HashMap<Version, usize>> { self.0.entry(key) } @@ -608,8 +632,11 @@ impl ProtoverVote { /// let vote = ProtoverVote::compute(protos, &2); /// assert_eq!("Link=3", vote.to_string()); /// ``` - // C_RUST_COUPLED: /src/or/protover.c protover_compute_vote - pub fn compute(proto_entries: &[UnvalidatedProtoEntry], threshold: &usize) -> UnvalidatedProtoEntry { + // C_RUST_COUPLED: protover.c protover_compute_vote + pub fn compute( + proto_entries: &[UnvalidatedProtoEntry], + threshold: &usize, + ) -> UnvalidatedProtoEntry { let mut all_count: ProtoverVote = ProtoverVote::default(); let mut final_output: UnvalidatedProtoEntry = UnvalidatedProtoEntry::default(); @@ -635,8 +662,7 @@ impl ProtoverVote { all_count.entry(protocol.clone()).or_insert(HashMap::new()); for version in versions.clone().expand() { - let counter: &mut usize = - supported_vers.entry(version).or_insert(0); + let counter: &mut usize = supported_vers.entry(version).or_insert(0); *counter += 1; } } @@ -715,16 +741,22 @@ pub(crate) fn compute_for_old_tor_cstr(version: &str) -> &'static CStr { return empty; } if c_tor_version_as_new_as(version, "0.2.9.1-alpha") { - return cstr!("Cons=1-2 Desc=1-2 DirCache=1 HSDir=1 HSIntro=3 HSRend=1-2 \ - Link=1-4 LinkAuth=1 Microdesc=1-2 Relay=1-2"); + return cstr!( + "Cons=1-2 Desc=1-2 DirCache=1 HSDir=1 HSIntro=3 HSRend=1-2 \ + Link=1-4 LinkAuth=1 Microdesc=1-2 Relay=1-2" + ); } if c_tor_version_as_new_as(version, "0.2.7.5") { - return cstr!("Cons=1-2 Desc=1-2 DirCache=1 HSDir=1 HSIntro=3 HSRend=1 \ - Link=1-4 LinkAuth=1 Microdesc=1-2 Relay=1-2"); + return cstr!( + "Cons=1-2 Desc=1-2 DirCache=1 HSDir=1 HSIntro=3 HSRend=1 \ + Link=1-4 LinkAuth=1 Microdesc=1-2 Relay=1-2" + ); } if c_tor_version_as_new_as(version, "0.2.4.19") { - return cstr!("Cons=1 Desc=1 DirCache=1 HSDir=1 HSIntro=3 HSRend=1 \ - Link=1-4 LinkAuth=1 Microdesc=1 Relay=1-2"); + return cstr!( + "Cons=1 Desc=1 DirCache=1 HSDir=1 HSIntro=3 HSRend=1 \ + Link=1-4 LinkAuth=1 Microdesc=1 Relay=1-2" + ); } empty } @@ -759,7 +791,9 @@ pub(crate) fn compute_for_old_tor_cstr(version: &str) -> &'static CStr { pub fn compute_for_old_tor(version: &str) -> Result<&'static str, ProtoverError> { // .to_str() fails with a Utf8Error if it couldn't validate the // utf-8, so convert that here into an Unparseable ProtoverError. - compute_for_old_tor_cstr(version).to_str().or(Err(ProtoverError::Unparseable)) + compute_for_old_tor_cstr(version) + .to_str() + .or(Err(ProtoverError::Unparseable)) } #[cfg(test)] @@ -793,19 +827,19 @@ mod test { } macro_rules! assert_protoentry_is_parseable { - ($e:expr) => ( + ($e:expr) => { let protoentry: Result<ProtoEntry, ProtoverError> = $e.parse(); assert!(protoentry.is_ok(), format!("{:?}", protoentry.err())); - ) + }; } macro_rules! assert_protoentry_is_unparseable { - ($e:expr) => ( + ($e:expr) => { let protoentry: Result<ProtoEntry, ProtoverError> = $e.parse(); assert!(protoentry.is_err()); - ) + }; } #[test] @@ -891,24 +925,45 @@ mod test { #[test] fn test_contract_protocol_list() { let mut versions = ""; - assert_eq!(String::from(versions), ProtoSet::from_str(&versions).unwrap().to_string()); + assert_eq!( + String::from(versions), + ProtoSet::from_str(&versions).unwrap().to_string() + ); versions = "1"; - assert_eq!(String::from(versions), ProtoSet::from_str(&versions).unwrap().to_string()); + assert_eq!( + String::from(versions), + ProtoSet::from_str(&versions).unwrap().to_string() + ); versions = "1-2"; - assert_eq!(String::from(versions), ProtoSet::from_str(&versions).unwrap().to_string()); + assert_eq!( + String::from(versions), + ProtoSet::from_str(&versions).unwrap().to_string() + ); versions = "1,3"; - assert_eq!(String::from(versions), ProtoSet::from_str(&versions).unwrap().to_string()); + assert_eq!( + String::from(versions), + ProtoSet::from_str(&versions).unwrap().to_string() + ); versions = "1-4"; - assert_eq!(String::from(versions), ProtoSet::from_str(&versions).unwrap().to_string()); + assert_eq!( + String::from(versions), + ProtoSet::from_str(&versions).unwrap().to_string() + ); versions = "1,3,5-7"; - assert_eq!(String::from(versions), ProtoSet::from_str(&versions).unwrap().to_string()); + assert_eq!( + String::from(versions), + ProtoSet::from_str(&versions).unwrap().to_string() + ); versions = "1-3,500"; - assert_eq!(String::from(versions), ProtoSet::from_str(&versions).unwrap().to_string()); + assert_eq!( + String::from(versions), + ProtoSet::from_str(&versions).unwrap().to_string() + ); } } diff --git a/src/rust/protover/tests/protover.rs b/src/rust/protover/tests/protover.rs index 9258d869d7..86e276cf73 100644 --- a/src/rust/protover/tests/protover.rs +++ b/src/rust/protover/tests/protover.rs @@ -1,12 +1,12 @@ -// Copyright (c) 2016-2017, The Tor Project, Inc. */ +// Copyright (c) 2016-2018, The Tor Project, Inc. */ // See LICENSE for licensing information */ extern crate protover; +use protover::errors::ProtoverError; use protover::ProtoEntry; use protover::ProtoverVote; use protover::UnvalidatedProtoEntry; -use protover::errors::ProtoverError; #[test] fn parse_protocol_with_single_proto_and_single_version() { @@ -179,14 +179,16 @@ fn protover_compute_vote_returns_two_protocols_for_two_matching() { #[test] fn protover_compute_vote_returns_one_protocol_when_one_out_of_two_matches() { - let protocols: &[UnvalidatedProtoEntry] = &["Cons=1 Link=2".parse().unwrap(), "Cons=1".parse().unwrap()]; + let protocols: &[UnvalidatedProtoEntry] = + &["Cons=1 Link=2".parse().unwrap(), "Cons=1".parse().unwrap()]; let listed = ProtoverVote::compute(protocols, &2); assert_eq!("Cons=1", listed.to_string()); } #[test] fn protover_compute_vote_returns_protocols_that_it_doesnt_currently_support() { - let protocols: &[UnvalidatedProtoEntry] = &["Foo=1 Cons=2".parse().unwrap(), "Bar=1".parse().unwrap()]; + let protocols: &[UnvalidatedProtoEntry] = + &["Foo=1 Cons=2".parse().unwrap(), "Bar=1".parse().unwrap()]; let listed = ProtoverVote::compute(protocols, &1); assert_eq!("Bar=1 Cons=2 Foo=1", listed.to_string()); } @@ -222,10 +224,12 @@ fn protover_compute_vote_returns_matching_for_longer_mix_with_threshold_two() { #[test] fn protover_compute_vote_handles_duplicated_versions() { - let protocols: &[UnvalidatedProtoEntry] = &["Cons=1".parse().unwrap(), "Cons=1".parse().unwrap()]; + let protocols: &[UnvalidatedProtoEntry] = + &["Cons=1".parse().unwrap(), "Cons=1".parse().unwrap()]; assert_eq!("Cons=1", ProtoverVote::compute(protocols, &2).to_string()); - let protocols: &[UnvalidatedProtoEntry] = &["Cons=1-2".parse().unwrap(), "Cons=1-2".parse().unwrap()]; + let protocols: &[UnvalidatedProtoEntry] = + &["Cons=1-2".parse().unwrap(), "Cons=1-2".parse().unwrap()]; assert_eq!("Cons=1-2", ProtoverVote::compute(protocols, &2).to_string()); } @@ -246,12 +250,18 @@ fn parse_protocol_with_single_protocol_and_two_nonsequential_versions() { #[test] fn protover_is_supported_here_returns_true_for_supported_protocol() { - assert_eq!(true, protover::is_supported_here(&protover::Protocol::Cons, &1)); + assert_eq!( + true, + protover::is_supported_here(&protover::Protocol::Cons, &1) + ); } #[test] fn protover_is_supported_here_returns_false_for_unsupported_protocol() { - assert_eq!(false, protover::is_supported_here(&protover::Protocol::Cons, &5)); + assert_eq!( + false, + protover::is_supported_here(&protover::Protocol::Cons, &5) + ); } #[test] diff --git a/src/rust/smartlist/Cargo.toml b/src/rust/smartlist/Cargo.toml index 6ddcbee8e9..4ecdf50869 100644 --- a/src/rust/smartlist/Cargo.toml +++ b/src/rust/smartlist/Cargo.toml @@ -11,3 +11,9 @@ name = "smartlist" path = "lib.rs" crate_type = ["rlib", "staticlib"] +[features] +# We have to define a feature here because doctests don't get cfg(test), +# and we need to disable some C dependencies when running the doctests +# because of the various linker issues. See +# https://github.com/rust-lang/rust/issues/45599 +test_linking_hack = [] diff --git a/src/rust/smartlist/lib.rs b/src/rust/smartlist/lib.rs index 14a8148315..2716842af2 100644 --- a/src/rust/smartlist/lib.rs +++ b/src/rust/smartlist/lib.rs @@ -1,4 +1,4 @@ -// Copyright (c) 2016-2017, The Tor Project, Inc. */ +// Copyright (c) 2016-2018, The Tor Project, Inc. */ // See LICENSE for licensing information */ extern crate libc; diff --git a/src/rust/smartlist/smartlist.rs b/src/rust/smartlist/smartlist.rs index 2a822d89f4..bce58c0ef9 100644 --- a/src/rust/smartlist/smartlist.rs +++ b/src/rust/smartlist/smartlist.rs @@ -1,9 +1,9 @@ -// Copyright (c) 2016-2017, The Tor Project, Inc. */ +// Copyright (c) 2016-2018, The Tor Project, Inc. */ // See LICENSE for licensing information */ -use std::slice; use libc::{c_char, c_int}; use std::ffi::CStr; +use std::slice; /// Smartlists are a type used in C code in tor to define a collection of a /// generic type, which has a capacity and a number used. Each Smartlist @@ -65,8 +65,8 @@ mod test { fn test_get_list_of_strings() { extern crate libc; - use std::ffi::CString; use libc::c_char; + use std::ffi::CString; use super::Smartlist; use super::Stringlist; @@ -89,13 +89,13 @@ mod test { let args = vec![String::from("a"), String::from("b")]; // for each string, transform it into a CString - let c_strings: Vec<_> = args.iter() + let c_strings: Vec<_> = args + .iter() .map(|arg| CString::new(arg.as_str()).unwrap()) .collect(); // then, collect a pointer for each CString - let p_args: Vec<_> = - c_strings.iter().map(|arg| arg.as_ptr()).collect(); + let p_args: Vec<_> = c_strings.iter().map(|arg| arg.as_ptr()).collect(); let p: *const *const c_char = p_args.as_ptr(); diff --git a/src/rust/tor_allocate/Cargo.toml b/src/rust/tor_allocate/Cargo.toml index 468425f115..7bb3b9887f 100644 --- a/src/rust/tor_allocate/Cargo.toml +++ b/src/rust/tor_allocate/Cargo.toml @@ -11,3 +11,9 @@ name = "tor_allocate" path = "lib.rs" crate_type = ["rlib", "staticlib"] +[features] +# We have to define a feature here because doctests don't get cfg(test), +# and we need to disable some C dependencies when running the doctests +# because of the various linker issues. See +# https://github.com/rust-lang/rust/issues/45599 +test_linking_hack = [] diff --git a/src/rust/tor_allocate/lib.rs b/src/rust/tor_allocate/lib.rs index 937a5dcf63..5a355bc8d6 100644 --- a/src/rust/tor_allocate/lib.rs +++ b/src/rust/tor_allocate/lib.rs @@ -1,4 +1,4 @@ -// Copyright (c) 2016-2017, The Tor Project, Inc. */ +// Copyright (c) 2016-2018, The Tor Project, Inc. */ // See LICENSE for licensing information */ //! Allocation helper functions that allow data to be allocated in Rust diff --git a/src/rust/tor_allocate/tor_allocate.rs b/src/rust/tor_allocate/tor_allocate.rs index 3c0037f139..48351d8482 100644 --- a/src/rust/tor_allocate/tor_allocate.rs +++ b/src/rust/tor_allocate/tor_allocate.rs @@ -1,17 +1,17 @@ -// Copyright (c) 2016-2017, The Tor Project, Inc. */ +// Copyright (c) 2016-2018, The Tor Project, Inc. */ // See LICENSE for licensing information */ // No-op defined purely for testing at the module level use libc::c_char; -#[cfg(not(feature = "testing"))] -use std::{ptr, slice, mem}; use libc::c_void; +#[cfg(not(feature = "testing"))] +use std::{mem, ptr, slice}; // Define a no-op implementation for testing Rust modules without linking to C #[cfg(feature = "testing")] -pub fn allocate_and_copy_string(s: &String) -> *mut c_char { +pub fn allocate_and_copy_string(s: &str) -> *mut c_char { use std::ffi::CString; - CString::new(s.as_str()).unwrap().into_raw() + CString::new(s).unwrap().into_raw() } // Defined only for tests, used for testing purposes, so that we don't need @@ -39,7 +39,7 @@ extern "C" { /// A `*mut c_char` that should be freed by tor_free in C /// #[cfg(not(feature = "testing"))] -pub fn allocate_and_copy_string(src: &String) -> *mut c_char { +pub fn allocate_and_copy_string(src: &str) -> *mut c_char { let bytes: &[u8] = src.as_bytes(); let size = mem::size_of_val::<[u8]>(bytes); @@ -72,16 +72,14 @@ mod test { #[test] fn test_allocate_and_copy_string_with_empty() { + use libc::{c_void, free}; use std::ffi::CStr; - use libc::{free, c_void}; use tor_allocate::allocate_and_copy_string; - let empty = String::new(); - let allocated_empty = allocate_and_copy_string(&empty); + let allocated_empty = allocate_and_copy_string(""); - let allocated_empty_rust = - unsafe { CStr::from_ptr(allocated_empty).to_str().unwrap() }; + let allocated_empty_rust = unsafe { CStr::from_ptr(allocated_empty).to_str().unwrap() }; assert_eq!("", allocated_empty_rust); @@ -90,16 +88,14 @@ mod test { #[test] fn test_allocate_and_copy_string_with_not_empty_string() { + use libc::{c_void, free}; use std::ffi::CStr; - use libc::{free, c_void}; use tor_allocate::allocate_and_copy_string; - let empty = String::from("foo bar biz"); - let allocated_empty = allocate_and_copy_string(&empty); + let allocated_empty = allocate_and_copy_string("foo bar biz"); - let allocated_empty_rust = - unsafe { CStr::from_ptr(allocated_empty).to_str().unwrap() }; + let allocated_empty_rust = unsafe { CStr::from_ptr(allocated_empty).to_str().unwrap() }; assert_eq!("foo bar biz", allocated_empty_rust); diff --git a/src/rust/tor_log/Cargo.toml b/src/rust/tor_log/Cargo.toml index 9d06299c05..1aa9be0612 100644 --- a/src/rust/tor_log/Cargo.toml +++ b/src/rust/tor_log/Cargo.toml @@ -9,6 +9,11 @@ path = "lib.rs" crate_type = ["rlib", "staticlib"] [features] +# We have to define a feature here because doctests don't get cfg(test), +# and we need to disable some C dependencies when running the doctests +# because of the various linker issues. See +# https://github.com/rust-lang/rust/issues/45599 +test_linking_hack = [] [dependencies] libc = "0.2.39" diff --git a/src/rust/tor_log/lib.rs b/src/rust/tor_log/lib.rs index 72f9e38339..21855ae73b 100644 --- a/src/rust/tor_log/lib.rs +++ b/src/rust/tor_log/lib.rs @@ -1,4 +1,4 @@ -//! Copyright (c) 2016-2017, The Tor Project, Inc. */ +//! Copyright (c) 2016-2018, The Tor Project, Inc. */ //! See LICENSE for licensing information */ //! Logging wrapper for Rust to utilize Tor's logger, found at diff --git a/src/rust/tor_log/tor_log.rs b/src/rust/tor_log/tor_log.rs index ad6725f0f2..5231d0c631 100644 --- a/src/rust/tor_log/tor_log.rs +++ b/src/rust/tor_log/tor_log.rs @@ -1,4 +1,4 @@ -// Copyright (c) 2016-2017, The Tor Project, Inc. */ +// Copyright (c) 2016-2018, The Tor Project, Inc. */ // See LICENSE for licensing information */ // Note that these functions are untested due to the fact that there are no @@ -48,12 +48,7 @@ macro_rules! tor_log_msg { } #[inline] -pub fn tor_log_msg_impl( - severity: LogSeverity, - domain: LogDomain, - function: &str, - message: String, -) { +pub fn tor_log_msg_impl(severity: LogSeverity, domain: LogDomain, function: &str, message: String) { use std::ffi::CString; /// Default function name to log in case of errors when converting @@ -63,7 +58,7 @@ pub fn tor_log_msg_impl( /// Default message to log in case of errors when converting a log /// message to a CString const ERR_LOG_MSG: &str = "Unable to log message from Rust \ - module due to error when converting to CString"; + module due to error when converting to CString"; let func = match CString::new(function) { Ok(n) => n, @@ -90,9 +85,9 @@ pub fn tor_log_msg_impl( /// testing. #[cfg(not(test))] pub mod log { - use libc::{c_char, c_int}; use super::LogDomain; use super::LogSeverity; + use libc::{c_char, c_int}; /// Severity log types. These mirror definitions in /src/common/torlog.h /// C_RUST_COUPLED: src/common/log.c, log domain types @@ -129,7 +124,7 @@ pub mod log { } /// The main entry point into Tor's logger. When in non-test mode, this - /// will link directly with `tor_log_string` in /src/or/log.c + /// will link directly with `tor_log_string` in torlog.c extern "C" { pub fn tor_log_string( severity: c_int, @@ -144,9 +139,9 @@ pub mod log { /// without linking to C. #[cfg(test)] pub mod log { - use libc::{c_char, c_int}; use super::LogDomain; use super::LogSeverity; + use libc::{c_char, c_int}; pub static mut LAST_LOGGED_FUNCTION: *mut String = 0 as *mut String; pub static mut LAST_LOGGED_MESSAGE: *mut String = 0 as *mut String; @@ -185,8 +180,8 @@ pub mod log { #[cfg(test)] mod test { - use tor_log::*; use tor_log::log::{LAST_LOGGED_FUNCTION, LAST_LOGGED_MESSAGE}; + use tor_log::*; #[test] fn test_get_log_message() { @@ -198,7 +193,7 @@ mod test { "test_macro", "test log message {}", "a", - ); + ); } test_macro(); @@ -244,21 +239,21 @@ mod test { "test_macro", "{}", "All the world's a stage, and all the men and women \ - merely players: they have their exits and their \ - entrances; and one man in his time plays many parts, his \ - acts being seven ages." + merely players: they have their exits and their \ + entrances; and one man in his time plays many parts, his \ + acts being seven ages." ); } test_macro(); let expected_string = "All the world's a \ - stage, and all the men \ - and women merely players: \ - they have their exits and \ - their entrances; and one man \ - in his time plays many parts, \ - his acts being seven ages."; + stage, and all the men \ + and women merely players: \ + they have their exits and \ + their entrances; and one man \ + in his time plays many parts, \ + his acts being seven ages."; let function = unsafe { Box::from_raw(LAST_LOGGED_FUNCTION) }; assert_eq!("test_macro", *function); diff --git a/src/rust/tor_rust/Cargo.toml b/src/rust/tor_rust/Cargo.toml index 86fad3ee76..1523ee0dd1 100644 --- a/src/rust/tor_rust/Cargo.toml +++ b/src/rust/tor_rust/Cargo.toml @@ -14,3 +14,9 @@ path = "../tor_util" [dependencies.protover] path = "../protover" +[features] +# We have to define a feature here because doctests don't get cfg(test), +# and we need to disable some C dependencies when running the doctests +# because of the various linker issues. See +# https://github.com/rust-lang/rust/issues/45599 +test_linking_hack = [] diff --git a/src/rust/tor_rust/include.am b/src/rust/tor_rust/include.am index 99f3ede653..ce673abbee 100644 --- a/src/rust/tor_rust/include.am +++ b/src/rust/tor_rust/include.am @@ -8,15 +8,15 @@ EXTRA_CARGO_OPTIONS= ( cd "$(abs_top_builddir)/src/rust" ; \ CARGO_TARGET_DIR="$(abs_top_builddir)/src/rust/target" \ $(CARGO) build --release $(EXTRA_CARGO_OPTIONS) \ - $(CARGO_ONLINE) \ - --manifest-path "$(abs_top_srcdir)/src/rust/tor_rust/Cargo.toml" ) + $(CARGO_ONLINE) \ + --manifest-path "$(abs_top_srcdir)/src/rust/tor_rust/Cargo.toml" ) distclean-rust: ( cd "$(abs_top_builddir)/src/rust" ; \ CARGO_TARGET_DIR="$(abs_top_builddir)/src/rust/target" \ $(CARGO) clean $(EXTRA_CARGO_OPTIONS) \ - $(CARGO_ONLINE) \ - --manifest-path "$(abs_top_srcdir)/src/rust/tor_rust/Cargo.toml" ) + $(CARGO_ONLINE) \ + --manifest-path "$(abs_top_srcdir)/src/rust/tor_rust/Cargo.toml" ) rm -rf "$(abs_top_builddir)/src/rust/registry" if USE_RUST diff --git a/src/rust/tor_rust/lib.rs b/src/rust/tor_rust/lib.rs index c1585c0480..18519f8497 100644 --- a/src/rust/tor_rust/lib.rs +++ b/src/rust/tor_rust/lib.rs @@ -1,5 +1,5 @@ -extern crate tor_util; extern crate protover; +extern crate tor_util; -pub use tor_util::*; pub use protover::*; +pub use tor_util::*; diff --git a/src/rust/tor_util/Cargo.toml b/src/rust/tor_util/Cargo.toml index a606a280b2..51e4bd9c5d 100644 --- a/src/rust/tor_util/Cargo.toml +++ b/src/rust/tor_util/Cargo.toml @@ -17,3 +17,9 @@ path = "../tor_log" [dependencies] libc = "=0.2.39" +[features] +# We have to define a feature here because doctests don't get cfg(test), +# and we need to disable some C dependencies when running the doctests +# because of the various linker issues. See +# https://github.com/rust-lang/rust/issues/45599 +test_linking_hack = [] diff --git a/src/rust/tor_util/ffi.rs b/src/rust/tor_util/ffi.rs index 32779ed476..f015590178 100644 --- a/src/rust/tor_util/ffi.rs +++ b/src/rust/tor_util/ffi.rs @@ -1,11 +1,11 @@ -// Copyright (c) 2016-2017, The Tor Project, Inc. */ +// Copyright (c) 2016-2018, The Tor Project, Inc. */ // See LICENSE for licensing information */ //! FFI functions to announce Rust support during tor startup, only to be //! called from C. //! -use tor_log::{LogSeverity, LogDomain}; +use tor_log::{LogDomain, LogSeverity}; /// Returns a short string to announce Rust support during startup. /// @@ -22,6 +22,6 @@ pub extern "C" fn rust_log_welcome_string() { LogDomain::General, "rust_log_welcome_string", "Tor is running with Rust integration. Please report \ - any bugs you encounter." + any bugs you encounter." ); } diff --git a/src/rust/tor_util/lib.rs b/src/rust/tor_util/lib.rs index 94697b6069..4ce5fc9374 100644 --- a/src/rust/tor_util/lib.rs +++ b/src/rust/tor_util/lib.rs @@ -1,4 +1,4 @@ -// Copyright (c) 2016-2017, The Tor Project, Inc. */ +// Copyright (c) 2016-2018, The Tor Project, Inc. */ // See LICENSE for licensing information */ //! Small module to announce Rust support during startup for demonstration diff --git a/src/rust/tor_util/strings.rs b/src/rust/tor_util/strings.rs index 505191d913..d64275e06b 100644 --- a/src/rust/tor_util/strings.rs +++ b/src/rust/tor_util/strings.rs @@ -1,4 +1,4 @@ -// Copyright (c) 2016-2017, The Tor Project, Inc. */ +// Copyright (c) 2016-2018, The Tor Project, Inc. */ // See LICENSE for licensing information */ //! Utilities for working with static strings. @@ -131,10 +131,10 @@ mod test { #[test] fn cstr_macro_bad_input() { - let waving: &'static CStr = cstr!("waving not drowning o/"); + let waving: &'static CStr = cstr!("waving not drowning o/"); let drowning: &'static CStr = cstr!("\0 drowning not waving"); - assert!(waving.to_str().unwrap() == "waving not drowning o/"); + assert!(waving.to_str().unwrap() == "waving not drowning o/"); assert!(drowning.to_str().unwrap() == "") } } |