diff options
Diffstat (limited to 'src/rust')
-rw-r--r-- | src/rust/Cargo.lock | 1 | ||||
-rw-r--r-- | src/rust/Cargo.toml | 10 | ||||
-rw-r--r-- | src/rust/crypto/Cargo.toml | 7 | ||||
-rw-r--r-- | src/rust/external/Cargo.toml | 12 | ||||
-rw-r--r-- | src/rust/external/external.rs | 9 | ||||
-rw-r--r-- | src/rust/external/lib.rs | 2 | ||||
-rw-r--r-- | src/rust/protover/Cargo.toml | 7 | ||||
-rw-r--r-- | src/rust/protover/errors.rs | 4 | ||||
-rw-r--r-- | src/rust/protover/ffi.rs | 22 | ||||
-rw-r--r-- | src/rust/protover/protoset.rs | 100 | ||||
-rw-r--r-- | src/rust/protover/protover.rs | 92 | ||||
-rw-r--r-- | src/rust/protover/tests/protover.rs | 14 | ||||
-rw-r--r-- | src/rust/smartlist/Cargo.toml | 7 | ||||
-rw-r--r-- | src/rust/smartlist/lib.rs | 9 | ||||
-rw-r--r-- | src/rust/tor_allocate/Cargo.toml | 7 | ||||
-rw-r--r-- | src/rust/tor_allocate/lib.rs | 5 | ||||
-rw-r--r-- | src/rust/tor_log/Cargo.toml | 6 | ||||
-rw-r--r-- | src/rust/tor_log/tor_log.rs | 8 | ||||
-rw-r--r-- | src/rust/tor_rust/Cargo.toml | 8 | ||||
-rw-r--r-- | src/rust/tor_util/Cargo.toml | 7 |
20 files changed, 230 insertions, 107 deletions
diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 1d2a7359aa..7d6a6635c5 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -26,6 +26,7 @@ version = "0.0.1" dependencies = [ "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", "smartlist 0.0.1", + "tor_allocate 0.0.1", ] [[package]] diff --git a/src/rust/Cargo.toml b/src/rust/Cargo.toml index 4bbadbe535..83f9629660 100644 --- a/src/rust/Cargo.toml +++ b/src/rust/Cargo.toml @@ -13,13 +13,3 @@ members = [ [profile.release] 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", -] diff --git a/src/rust/crypto/Cargo.toml b/src/rust/crypto/Cargo.toml index d68ac48e28..a7ff7f78d9 100644 --- a/src/rust/crypto/Cargo.toml +++ b/src/rust/crypto/Cargo.toml @@ -9,7 +9,6 @@ build = "../build.rs" [lib] name = "crypto" path = "lib.rs" -crate_type = ["rlib", "staticlib"] [dependencies] libc = "=0.2.39" @@ -30,3 +29,9 @@ rand_core = { version = "=0.2.0-pre.0", default-features = false } # 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/external/Cargo.toml b/src/rust/external/Cargo.toml index 60ec03be40..5f443645bb 100644 --- a/src/rust/external/Cargo.toml +++ b/src/rust/external/Cargo.toml @@ -5,12 +5,16 @@ name = "external" [dependencies] libc = "=0.2.39" - -[dependencies.smartlist] -path = "../smartlist" +smartlist = { path = "../smartlist" } +tor_allocate = { path = "../tor_allocate" } [lib] 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/external.rs b/src/rust/external/external.rs index 874c7c3153..aa43d2a928 100644 --- a/src/rust/external/external.rs +++ b/src/rust/external/external.rs @@ -26,3 +26,12 @@ pub fn c_tor_version_as_new_as(platform: &str, cutoff: &str) -> bool { 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/external/lib.rs b/src/rust/external/lib.rs index b72a4f6e4c..d68036fcad 100644 --- a/src/rust/external/lib.rs +++ b/src/rust/external/lib.rs @@ -8,7 +8,7 @@ //! module implementing this functionality repeatedly. extern crate libc; - +extern crate tor_allocate; extern crate smartlist; pub mod crypto_digest; diff --git a/src/rust/protover/Cargo.toml b/src/rust/protover/Cargo.toml index a8480e142a..84a7c71c1a 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" @@ -26,5 +31,3 @@ path = "../tor_log" [lib] name = "protover" path = "lib.rs" -crate_type = ["rlib", "staticlib"] - diff --git a/src/rust/protover/errors.rs b/src/rust/protover/errors.rs index 71fbc53e17..f26a48b019 100644 --- a/src/rust/protover/errors.rs +++ b/src/rust/protover/errors.rs @@ -18,6 +18,7 @@ pub enum ProtoverError { ExceedsExpansionLimit, UnknownProtocol, ExceedsNameLimit, + InvalidProtocol, } /// Descriptive error messages for `ProtoverError` variants. @@ -48,6 +49,9 @@ impl Display for ProtoverError { 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 0c28d032c6..ac149fbbbc 100644 --- a/src/rust/protover/ffi.rs +++ b/src/rust/protover/ffi.rs @@ -62,6 +62,9 @@ pub extern "C" fn protover_all_supported( }; if let Some(unsupported) = relay_proto_entry.all_supported() { + if missing_out.is_null() { + return 0; + } let c_unsupported: CString = match CString::new(unsupported.to_string()) { Ok(n) => n, Err(_) => return 1, @@ -184,11 +187,7 @@ pub extern "C" fn protover_get_supported_protocols() -> *const c_char { // // Why is the threshold a signed integer? —isis #[no_mangle] -pub extern "C" fn protover_compute_vote( - list: *const Stringlist, - threshold: c_int, - allow_long_proto_names: bool, -) -> *mut c_char { +pub extern "C" fn protover_compute_vote(list: *const Stringlist, threshold: c_int) -> *mut c_char { if list.is_null() { return allocate_and_copy_string(""); } @@ -200,16 +199,9 @@ pub extern "C" fn protover_compute_vote( let mut proto_entries: Vec<UnvalidatedProtoEntry> = Vec::new(); for datum in data { - 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, - } + let entry: UnvalidatedProtoEntry = match datum.parse() { + Ok(n) => n, + Err(_) => continue, }; proto_entries.push(entry); } diff --git a/src/rust/protover/protoset.rs b/src/rust/protover/protoset.rs index db33592f95..aa8d243bad 100644 --- a/src/rust/protover/protoset.rs +++ b/src/rust/protover/protoset.rs @@ -4,6 +4,8 @@ //! Sets for lazily storing ordered, non-overlapping ranges of integers. +use std::cmp; +use std::iter; use std::slice; use std::str::FromStr; use std::u32; @@ -174,7 +176,7 @@ impl ProtoSet { if low == u32::MAX || high == u32::MAX { return Err(ProtoverError::ExceedsMax); } - if low < last_high { + if low <= last_high { return Err(ProtoverError::Overlap); } else if low > high { return Err(ProtoverError::LowGreaterThanHigh); @@ -240,8 +242,8 @@ impl ProtoSet { false } - /// Retain only the `Version`s in this `ProtoSet` for which the predicate - /// `F` returns `true`. + /// Returns all the `Version`s in `self` which are not also in the `other` + /// `ProtoSet`. /// /// # Examples /// @@ -250,25 +252,45 @@ impl ProtoSet { /// use protover::protoset::ProtoSet; /// /// # fn do_test() -> Result<bool, ProtoverError> { - /// let mut protoset: ProtoSet = "1,3-5,9".parse()?; + /// let protoset: ProtoSet = "1,3-6,10-12,15-16".parse()?; + /// let other: ProtoSet = "2,5-7,9-11,14-20".parse()?; /// - /// // Keep only versions less than or equal to 8: - /// protoset.retain(|x| x <= &8); + /// let subset: ProtoSet = protoset.and_not_in(&other); /// - /// assert_eq!(protoset.expand(), vec![1, 3, 4, 5]); + /// assert_eq!(subset.expand(), vec![1, 3, 4, 12]); /// # /// # Ok(true) /// # } /// # fn main() { do_test(); } // wrap the test so we can use the ? operator /// ``` - // XXX we could probably do something more efficient here. —isis - pub fn retain<F>(&mut self, f: F) - where - F: FnMut(&Version) -> bool, - { - let mut expanded: Vec<Version> = self.clone().expand(); - expanded.retain(f); - *self = expanded.into(); + pub fn and_not_in(&self, other: &Self) -> Self { + if self.is_empty() || other.is_empty() { + return self.clone(); + } + + let pairs = self.iter().flat_map(|&(lo, hi)| { + let the_end = (hi + 1, hi + 1); // special case to mark the end of the range. + let excluded_ranges = other + .iter() + .cloned() // have to be owned tuples, to match iter::once(the_end). + .skip_while(move|&(_, hi2)| hi2 < lo) // skip the non-overlapping ranges. + .take_while(move|&(lo2, _)| lo2 <= hi) // take all the overlapping ones. + .chain(iter::once(the_end)); + + let mut nextlo = lo; + excluded_ranges.filter_map(move |(excluded_lo, excluded_hi)| { + let pair = if nextlo < excluded_lo { + Some((nextlo, excluded_lo - 1)) + } else { + None + }; + nextlo = cmp::min(excluded_hi, u32::MAX - 1) + 1; + pair + }) + }); + + let pairs = pairs.collect(); + ProtoSet::is_ok(ProtoSet { pairs }).expect("should be already sorted") } } @@ -330,23 +352,25 @@ impl FromStr for ProtoSet { /// assert_eq!(Err(ProtoverError::Unparseable), ProtoSet::from_str("3-")); /// assert_eq!(Err(ProtoverError::Unparseable), ProtoSet::from_str("1-,4")); /// - /// // Things which would get parsed into an _empty_ `ProtoSet` are, - /// // however, legal, and result in an empty `ProtoSet`: + /// // An empty string is, however, legal, and results in an + /// // empty `ProtoSet`: /// assert_eq!(Ok(ProtoSet::default()), ProtoSet::from_str("")); - /// assert_eq!(Ok(ProtoSet::default()), ProtoSet::from_str(",,,")); /// # /// # Ok(protoset) /// # } /// # fn main() { do_test(); } // wrap the test so we can use the ? operator /// ``` fn from_str(version_string: &str) -> Result<Self, Self::Err> { + // If we were passed in an empty string, then return an empty ProtoSet. + if version_string.is_empty() { + return Ok(Self::default()); + } + let mut pairs: Vec<(Version, Version)> = Vec::new(); let pieces: ::std::str::Split<char> = version_string.split(','); for p in pieces { - if p.is_empty() { - continue; - } else if p.contains('-') { + if p.contains('-') { let mut pair = p.splitn(2, '-'); let low = pair.next().ok_or(ProtoverError::Unparseable)?; @@ -355,24 +379,14 @@ impl FromStr for ProtoSet { 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 { - return Err(ProtoverError::ExceedsMax); - } pairs.push((lo, hi)); } else { let v: u32 = p.parse().or(Err(ProtoverError::Unparseable))?; - if v == u32::MAX { - return Err(ProtoverError::ExceedsMax); - } pairs.push((v, v)); } } - // If we were passed in an empty string, or - // simply a comma, or a pile of commas, then return an empty ProtoSet. - if pairs.len() == 0 { - return Ok(ProtoSet::default()); - } + ProtoSet::from_slice(&pairs[..]) } } @@ -521,7 +535,6 @@ mod test { test_protoset_contains_versions!(&[1], "1"); test_protoset_contains_versions!(&[1, 2], "1,2"); test_protoset_contains_versions!(&[1, 2, 3], "1-3"); - test_protoset_contains_versions!(&[0, 1], "0-1"); test_protoset_contains_versions!(&[1, 2, 5], "1-2,5"); test_protoset_contains_versions!(&[1, 3, 4, 5], "1,3-5"); test_protoset_contains_versions!(&[42, 55, 56, 57, 58], "42,55-58"); @@ -538,6 +551,13 @@ mod test { } #[test] + fn test_versions_from_str_commas() { + assert_eq!(Err(ProtoverError::Unparseable), ProtoSet::from_str(",")); + assert_eq!(Err(ProtoverError::Unparseable), ProtoSet::from_str("1,,2")); + assert_eq!(Err(ProtoverError::Unparseable), ProtoSet::from_str("1,2,")); + } + + #[test] fn test_versions_from_str_hyphens() { assert_eq!(Err(ProtoverError::Unparseable), ProtoSet::from_str("--1")); assert_eq!(Err(ProtoverError::Unparseable), ProtoSet::from_str("-1-2")); @@ -597,9 +617,9 @@ mod test { #[test] fn test_protoset_contains() { - let protoset: ProtoSet = ProtoSet::from_slice(&[(0, 5), (7, 9), (13, 14)]).unwrap(); + let protoset: ProtoSet = ProtoSet::from_slice(&[(1, 5), (7, 9), (13, 14)]).unwrap(); - for x in 0..6 { + for x in 1..6 { assert!(protoset.contains(&x), format!("should contain {}", x)); } for x in 7..10 { @@ -615,10 +635,10 @@ mod test { } #[test] - fn test_protoset_contains_0_3() { - let protoset: ProtoSet = ProtoSet::from_slice(&[(0, 3)]).unwrap(); + fn test_protoset_contains_1_3() { + let protoset: ProtoSet = ProtoSet::from_slice(&[(1, 3)]).unwrap(); - for x in 0..4 { + for x in 1..4 { assert!(protoset.contains(&x), format!("should contain {}", x)); } } @@ -640,8 +660,8 @@ mod test { } #[test] - fn test_protoset_from_vec_0_315() { - assert_protoset_from_vec_contains_all!(0, 1, 2, 3, 15); + fn test_protoset_from_vec_1_315() { + assert_protoset_from_vec_contains_all!(1, 2, 3, 15); } #[test] diff --git a/src/rust/protover/protover.rs b/src/rust/protover/protover.rs index 157027750f..8624afeafa 100644 --- a/src/rust/protover/protover.rs +++ b/src/rust/protover/protover.rs @@ -89,11 +89,17 @@ impl fmt::Display for UnknownProtocol { } } +fn is_valid_proto(s: &str) -> bool { + s.chars().all(|c| c.is_ascii_alphanumeric() || c == '-') +} + impl FromStr for UnknownProtocol { type Err = ProtoverError; fn from_str(s: &str) -> Result<Self, Self::Err> { - if s.len() <= MAX_PROTOCOL_NAME_LENGTH { + if !is_valid_proto(s) { + Err(ProtoverError::InvalidProtocol) + } else if s.len() <= MAX_PROTOCOL_NAME_LENGTH { Ok(UnknownProtocol(s.to_string())) } else { Err(ProtoverError::ExceedsNameLimit) @@ -105,6 +111,9 @@ impl UnknownProtocol { /// Create an `UnknownProtocol`, ignoring whether or not it /// exceeds MAX_PROTOCOL_NAME_LENGTH. fn from_str_any_len(s: &str) -> Result<Self, ProtoverError> { + if !is_valid_proto(s) { + return Err(ProtoverError::InvalidProtocol); + } Ok(UnknownProtocol(s.to_string())) } } @@ -115,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. /// @@ -132,18 +152,33 @@ impl From<Protocol> for UnknownProtocol { /// // 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. @@ -345,7 +380,6 @@ impl UnvalidatedProtoEntry { let maybe_supported_versions: Option<&ProtoSet> = supported.get(&supported_protocol); let supported_versions: &ProtoSet; - let mut unsupported_versions: ProtoSet; // If the protocol wasn't in the map, then we don't know about it // and don't support any of its versions. Add its versions to the @@ -358,8 +392,7 @@ impl UnvalidatedProtoEntry { } else { supported_versions = maybe_supported_versions.unwrap(); } - unsupported_versions = versions.clone(); - unsupported_versions.retain(|x| !supported_versions.contains(x)); + let unsupported_versions = versions.and_not_in(supported_versions); if !unsupported_versions.is_empty() { unsupported.insert(protocol.clone(), unsupported_versions); @@ -772,6 +805,29 @@ mod test { use super::*; + macro_rules! parse_proto { + ($e:expr) => {{ + let proto: Result<UnknownProtocol, _> = $e.parse(); + let proto2 = UnknownProtocol::from_str_any_len($e); + assert_eq!(proto, proto2); + proto + }}; + } + + #[test] + fn test_protocol_from_str() { + assert!(parse_proto!("Cons").is_ok()); + assert!(parse_proto!("123").is_ok()); + assert!(parse_proto!("1-2-3").is_ok()); + + let err = Err(ProtoverError::InvalidProtocol); + assert_eq!(err, parse_proto!("a_b_c")); + assert_eq!(err, parse_proto!("a b")); + assert_eq!(err, parse_proto!("a,")); + assert_eq!(err, parse_proto!("b.")); + assert_eq!(err, parse_proto!("é")); + } + macro_rules! assert_protoentry_is_parseable { ($e:expr) => { let protoentry: Result<ProtoEntry, ProtoverError> = $e.parse(); @@ -862,10 +918,10 @@ mod test { #[test] fn test_protoentry_all_supported_unsupported_low_version() { - let protocols: UnvalidatedProtoEntry = "Cons=0-1".parse().unwrap(); + let protocols: UnvalidatedProtoEntry = "HSIntro=2-3".parse().unwrap(); let unsupported: Option<UnvalidatedProtoEntry> = protocols.all_supported(); assert_eq!(true, unsupported.is_some()); - assert_eq!("Cons=0", &unsupported.unwrap().to_string()); + assert_eq!("HSIntro=2", &unsupported.unwrap().to_string()); } #[test] diff --git a/src/rust/protover/tests/protover.rs b/src/rust/protover/tests/protover.rs index a091e692d6..86e276cf73 100644 --- a/src/rust/protover/tests/protover.rs +++ b/src/rust/protover/tests/protover.rs @@ -106,10 +106,10 @@ fn protocol_all_supported_with_unsupported_versions() { #[test] fn protocol_all_supported_with_unsupported_low_version() { - let protocols: UnvalidatedProtoEntry = "Cons=0-1".parse().unwrap(); + let protocols: UnvalidatedProtoEntry = "HSIntro=2-3".parse().unwrap(); let unsupported: Option<UnvalidatedProtoEntry> = protocols.all_supported(); assert_eq!(true, unsupported.is_some()); - assert_eq!("Cons=0", &unsupported.unwrap().to_string()); + assert_eq!("HSIntro=2", &unsupported.unwrap().to_string()); } #[test] @@ -364,18 +364,18 @@ fn protover_all_supported_should_exclude_some_versions_and_entire_protocols() { #[test] fn protover_all_supported_should_not_dos_anyones_computer() { - let proto: UnvalidatedProtoEntry = "Sleen=0-2147483648".parse().unwrap(); + let proto: UnvalidatedProtoEntry = "Link=1-2147483648".parse().unwrap(); let result: String = proto.all_supported().unwrap().to_string(); - assert_eq!(result, "Sleen=0-2147483648".to_string()); + assert_eq!(result, "Link=6-2147483648".to_string()); } #[test] fn protover_all_supported_should_not_dos_anyones_computer_max_versions() { - let proto: UnvalidatedProtoEntry = "Sleen=0-4294967294".parse().unwrap(); + let proto: UnvalidatedProtoEntry = "Link=1-4294967294".parse().unwrap(); let result: String = proto.all_supported().unwrap().to_string(); - assert_eq!(result, "Sleen=0-4294967294".to_string()); + assert_eq!(result, "Link=6-4294967294".to_string()); } #[test] @@ -398,7 +398,7 @@ fn protover_unvalidatedprotoentry_should_err_entirely_unparseable_things() { #[test] fn protover_all_supported_over_maximum_limit() { - let proto: Result<UnvalidatedProtoEntry, ProtoverError> = "Sleen=0-4294967295".parse(); + let proto: Result<UnvalidatedProtoEntry, ProtoverError> = "Sleen=1-4294967295".parse(); assert_eq!(Err(ProtoverError::ExceedsMax), proto); } diff --git a/src/rust/smartlist/Cargo.toml b/src/rust/smartlist/Cargo.toml index 6ddcbee8e9..a5afe7bf74 100644 --- a/src/rust/smartlist/Cargo.toml +++ b/src/rust/smartlist/Cargo.toml @@ -9,5 +9,10 @@ libc = "0.2.39" [lib] 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 2716842af2..34d0b907ed 100644 --- a/src/rust/smartlist/lib.rs +++ b/src/rust/smartlist/lib.rs @@ -6,3 +6,12 @@ extern crate libc; mod smartlist; pub use smartlist::*; + +// When testing we may be compiled with sanitizers which are incompatible with +// Rust's default allocator, jemalloc (unsure why at this time). Most crates +// link to `tor_allocate` which switches by default to a non-jemalloc allocator, +// but we don't already depend on `tor_allocate` so make sure that while testing +// we don't use jemalloc. (but rather malloc/free) +#[global_allocator] +#[cfg(test)] +static A: std::alloc::System = std::alloc::System; diff --git a/src/rust/tor_allocate/Cargo.toml b/src/rust/tor_allocate/Cargo.toml index 468425f115..06ac605f17 100644 --- a/src/rust/tor_allocate/Cargo.toml +++ b/src/rust/tor_allocate/Cargo.toml @@ -9,5 +9,10 @@ libc = "=0.2.39" [lib] 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 5a355bc8d6..1cfa0b5178 100644 --- a/src/rust/tor_allocate/lib.rs +++ b/src/rust/tor_allocate/lib.rs @@ -11,5 +11,10 @@ extern crate libc; +use std::alloc::System; + mod tor_allocate; pub use tor_allocate::*; + +#[global_allocator] +static A: System = System; diff --git a/src/rust/tor_log/Cargo.toml b/src/rust/tor_log/Cargo.toml index 9d06299c05..14d9ae803a 100644 --- a/src/rust/tor_log/Cargo.toml +++ b/src/rust/tor_log/Cargo.toml @@ -6,9 +6,13 @@ authors = ["The Tor Project"] [lib] name = "tor_log" 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/tor_log.rs b/src/rust/tor_log/tor_log.rs index 5231d0c631..757c74ff49 100644 --- a/src/rust/tor_log/tor_log.rs +++ b/src/rust/tor_log/tor_log.rs @@ -89,15 +89,15 @@ pub mod log { 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 + /// Severity log types. These mirror definitions in src/lib/log/log.h + /// C_RUST_COUPLED: src/lib/log/log.c, log domain types extern "C" { static LOG_WARN_: c_int; static LOG_NOTICE_: c_int; } - /// Domain log types. These mirror definitions in /src/common/torlog.h - /// C_RUST_COUPLED: src/common/log.c, log severity types + /// Domain log types. These mirror definitions in src/lib/log/log.h + /// C_RUST_COUPLED: src/lib/log/log.c, log severity types extern "C" { static LD_NET_: u32; static LD_GENERAL_: u32; diff --git a/src/rust/tor_rust/Cargo.toml b/src/rust/tor_rust/Cargo.toml index 86fad3ee76..35c629882e 100644 --- a/src/rust/tor_rust/Cargo.toml +++ b/src/rust/tor_rust/Cargo.toml @@ -6,7 +6,7 @@ version = "0.1.0" [lib] name = "tor_rust" path = "lib.rs" -crate_type = ["rlib", "staticlib"] +crate_type = ["staticlib"] [dependencies.tor_util] path = "../tor_util" @@ -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_util/Cargo.toml b/src/rust/tor_util/Cargo.toml index a606a280b2..9ffaeda8a6 100644 --- a/src/rust/tor_util/Cargo.toml +++ b/src/rust/tor_util/Cargo.toml @@ -6,7 +6,6 @@ version = "0.0.1" [lib] name = "tor_util" path = "lib.rs" -crate_type = ["rlib", "staticlib"] [dependencies.tor_allocate] path = "../tor_allocate" @@ -17,3 +16,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 = [] |