diff options
-rw-r--r-- | .gitignore | 5 | ||||
-rw-r--r-- | .gitmodules | 3 | ||||
-rw-r--r-- | Makefile.am | 10 | ||||
-rw-r--r-- | configure.ac | 68 | ||||
-rw-r--r-- | src/common/compat_rust.c | 39 | ||||
-rw-r--r-- | src/common/compat_rust.h | 28 | ||||
-rw-r--r-- | src/common/include.am | 6 | ||||
m--------- | src/ext/rust | 0 | ||||
-rw-r--r-- | src/include.am | 1 | ||||
-rw-r--r-- | src/or/include.am | 3 | ||||
-rw-r--r-- | src/or/main.c | 10 | ||||
-rw-r--r-- | src/rust/.cargo/config.in | 8 | ||||
-rw-r--r-- | src/rust/.rustfmt.toml | 2 | ||||
-rw-r--r-- | src/rust/Cargo.lock | 14 | ||||
-rw-r--r-- | src/rust/Cargo.toml | 7 | ||||
-rw-r--r-- | src/rust/include.am | 6 | ||||
-rw-r--r-- | src/rust/tor_util/Cargo.toml | 13 | ||||
-rw-r--r-- | src/rust/tor_util/ffi.rs | 56 | ||||
-rw-r--r-- | src/rust/tor_util/include.am | 13 | ||||
-rw-r--r-- | src/rust/tor_util/lib.rs | 13 | ||||
-rw-r--r-- | src/rust/tor_util/rust_string.rs | 101 | ||||
-rw-r--r-- | src/rust/tor_util/tests/rust_string.rs | 37 | ||||
-rw-r--r-- | src/test/fuzz/include.am | 3 | ||||
-rw-r--r-- | src/test/include.am | 33 | ||||
-rw-r--r-- | src/test/test.c | 1 | ||||
-rw-r--r-- | src/test/test.h | 1 | ||||
-rw-r--r-- | src/test/test_rust.c | 31 | ||||
-rwxr-xr-x | src/test/test_rust.sh | 13 | ||||
-rw-r--r-- | src/tools/include.am | 14 |
29 files changed, 523 insertions, 16 deletions
diff --git a/.gitignore b/.gitignore index 68bad5f113..0e0640de2d 100644 --- a/.gitignore +++ b/.gitignore @@ -173,6 +173,11 @@ uptime-*.json /src/or/libtor-testing.a /src/or/libtor.lib +# /src/rust +/src/rust/.cargo/config +/src/rust/.cargo/registry +/src/rust/target + # /src/test /src/test/Makefile /src/test/Makefile.in diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000000..7074403c9c --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "src/ext/rust"] + path = src/ext/rust + url = https://git.torproject.org/user/sebastian/tor-rust-dependencies diff --git a/Makefile.am b/Makefile.am index be1dc7f7ef..79d2e78521 100644 --- a/Makefile.am +++ b/Makefile.am @@ -25,6 +25,12 @@ else TESTING_TOR_BINARY=$(top_builddir)/src/or/tor$(EXEEXT) endif +if USE_RUST +rust_ldadd=$(top_builddir)/src/rust/target/release/libtor_util.a +else +rust_ldadd= +endif + include src/include.am include doc/include.am include contrib/include.am @@ -230,3 +236,7 @@ mostlyclean-local: rm -rf $(HTML_COVER_DIR) rm -rf $(top_builddir)/doc/doxygen rm -rf $(TEST_NETWORK_ALL_LOG_DIR) + +clean-local: + rm -rf $(top_builddir)/src/rust/target + rm -rf $(top_builddir)/src/rust/.cargo/registry diff --git a/configure.ac b/configure.ac index aa1eda655e..4c23e47adc 100644 --- a/configure.ac +++ b/configure.ac @@ -55,6 +55,10 @@ AC_ARG_ENABLE(oss-fuzz, AS_HELP_STRING(--enable-oss-fuzz, [build extra fuzzers based on 'oss-fuzz' environment])) AC_ARG_ENABLE(memory-sentinels, AS_HELP_STRING(--disable-memory-sentinels, [disable code that tries to prevent some kinds of memory access bugs. For fuzzing only.])) +AC_ARG_ENABLE(rust, + AS_HELP_STRING(--enable-rust, [enable rust integration])) +AC_ARG_ENABLE(cargo-online-mode, + AS_HELP_STRING(--enable-cargo-online-mode, [Allow cargo to make network requests to fetch crates. For builds with rust only.])) if test "x$enable_coverage" != "xyes" -a "x$enable_asserts_in_tests" = "xno" ; then AC_MSG_ERROR([Can't disable assertions outside of coverage build]) @@ -65,6 +69,7 @@ AM_CONDITIONAL(COVERAGE_ENABLED, test "x$enable_coverage" = "xyes") AM_CONDITIONAL(DISABLE_ASSERTS_IN_UNIT_TESTS, test "x$enable_asserts_in_tests" = "xno") AM_CONDITIONAL(LIBFUZZER_ENABLED, test "x$enable_libfuzzer" = "xyes") AM_CONDITIONAL(OSS_FUZZ_ENABLED, test "x$enable_oss_fuzz" = "xyes") +AM_CONDITIONAL(USE_RUST, test "x$enable_rust" = "xyes") if test "$enable_static_tor" = "yes"; then enable_static_libevent="yes"; @@ -249,6 +254,68 @@ if test "x$PYTHON" = "x"; then fi AM_CONDITIONAL(USEPYTHON, [test "x$PYTHON" != "x"]) +dnl List all external rust crates we depend on here. Include the version +rust_crates="libc-0.2.22" +AC_SUBST(rust_crates) + +if test "x$enable_rust" = "xyes"; then + AC_ARG_VAR([RUSTC], [path to the rustc binary]) + AC_CHECK_PROG([RUSTC], [rustc], [rustc],[no]) + if test "x$RUSTC" = "xno"; then + AC_MSG_ERROR([rustc unavailable but rust integration requested.]) + fi + + AC_ARG_VAR([CARGO], [path to the cargo binary]) + AC_CHECK_PROG([CARGO], [cargo], [cargo],[no]) + if test "x$CARGO" = "xno"; then + AC_MSG_ERROR([cargo unavailable but rust integration requested.]) + fi + + AC_DEFINE([HAVE_RUST], 1, [have Rust]) + if test "x$enable_cargo_online_mode" = "xyes"; then + CARGO_ONLINE= + RUST_DL=# + else + CARGO_ONLINE=--frozen + RUST_DL= + + dnl When we're not allowed to touch the network, we need crate dependencies + dnl locally available. + AC_MSG_CHECKING([rust crate dependencies]) + AC_ARG_VAR([RUST_DEPENDENCIES], [path to directory with local crate mirror]) + if test "x$RUST_DEPENDENCIES" = "x"; then + RUST_DEPENDENCIES="$srcdir/src/ext/rust/" + NEED_MOD=1 + fi + if test ! -d "$RUST_DEPENDENCIES"; then + AC_MSG_ERROR([Rust dependency directory $RUST_DEPENDENCIES does not exist. Specify a dependency directory using the RUST_DEPENDENCIES variable or allow cargo to fetch crates using --enable-cargo-online-mode.]) + fi + for dep in $rust_crates; do + if test ! -d "$RUST_DEPENDENCIES"/"$dep"; then + AC_MSG_ERROR([Failure to find rust dependency $RUST_DEPENDENCIES/$dep. Specify a dependency directory using the RUST_DEPENDENCIES variable or allow cargo to fetch crates using --enable-cargo-online-mode.]) + fi + done + if test "x$NEED_MOD" = "x1"; then + dnl When looking for dependencies from cargo, pick right directory + RUST_DEPENDENCIES="../../src/ext/rust" + fi + fi + + AC_SUBST(CARGO_ONLINE) + AC_SUBST(RUST_DL) + +dnl Let's check the rustc version, too + AC_MSG_CHECKING([rust version]) + RUSTC_VERSION_MAJOR=`$RUSTC --version | cut -d ' ' -f 2 | cut -d '.' -f 1` + RUSTC_VERSION_MINOR=`$RUSTC --version | cut -d ' ' -f 2 | cut -d '.' -f 2` + if test "x$RUSTC_VERSION_MAJOR" = "x" -o "x$RUSTC_VERSION_MINOR" = "x"; then + AC_MSG_ERROR([rustc version couldn't be identified]) + fi + if test "$RUSTC_VERSION_MAJOR" -lt 2 -a "$RUSTC_VERSION_MINOR" -lt 14; then + AC_MSG_ERROR([rustc must be at least version 1.14]) + fi +fi + ifdef([AC_C_FLEXIBLE_ARRAY_MEMBER], [ AC_C_FLEXIBLE_ARRAY_MEMBER ], [ @@ -2026,6 +2093,7 @@ AC_CONFIG_FILES([ contrib/dist/tor.service src/config/torrc.sample src/config/torrc.minimal + src/rust/.cargo/config scripts/maint/checkOptionDocs.pl scripts/maint/updateVersions.pl ]) diff --git a/src/common/compat_rust.c b/src/common/compat_rust.c new file mode 100644 index 0000000000..366fd4037b --- /dev/null +++ b/src/common/compat_rust.c @@ -0,0 +1,39 @@ +/* Copyright (c) 2017, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file rust_compat.c + * \brief Rust FFI compatibility functions and helpers. This file is only built + * if Rust is not used. + **/ + +#include "compat_rust.h" +#include "util.h" + +/** + * Free storage pointed to by <b>str</b>, and itself. + */ +void +rust_str_free(rust_str_t str) +{ + char *s = (char *)str; + tor_free(s); +} + +/** + * Return zero-terminated contained string. + */ +const char * +rust_str_get(const rust_str_t str) +{ + return (const char *)str; +} + +/* If we were using Rust, we'd say so on startup. */ +rust_str_t +rust_welcome_string(void) +{ + char *s = tor_malloc_zero(1); + return (rust_str_t)s; +} + diff --git a/src/common/compat_rust.h b/src/common/compat_rust.h new file mode 100644 index 0000000000..752a29b56c --- /dev/null +++ b/src/common/compat_rust.h @@ -0,0 +1,28 @@ +/* Copyright (c) 2017, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file rust_compat.h + * \brief Headers for rust_compat.c + **/ + +#ifndef TOR_RUST_COMPAT_H +#define TOR_RUST_COMPAT_H + +#include "torint.h" + +/** + * Strings allocated in Rust must be freed from Rust code again. Let's make + * it less likely to accidentally mess up and call tor_free() on it, because + * currently it'll just work but might break at any time. + */ +typedef uintptr_t rust_str_t; + +void rust_str_free(rust_str_t); + +const char *rust_str_get(const rust_str_t); + +rust_str_t rust_welcome_string(void); + +#endif + diff --git a/src/common/include.am b/src/common/include.am index 51b7da65f5..1253888815 100644 --- a/src/common/include.am +++ b/src/common/include.am @@ -100,6 +100,11 @@ LIBOR_A_SRC = \ $(threads_impl_source) \ $(readpassphrase_source) +if USE_RUST +else +LIBOR_A_SRC += src/common/compat_rust.c +endif + src/common/src_common_libor_testing_a-log.$(OBJEXT) \ src/common/log.$(OBJEXT): micro-revision.i @@ -147,6 +152,7 @@ COMMONHEADERS = \ src/common/compat.h \ src/common/compat_libevent.h \ src/common/compat_openssl.h \ + src/common/compat_rust.h \ src/common/compat_threads.h \ src/common/compat_time.h \ src/common/compress.h \ diff --git a/src/ext/rust b/src/ext/rust new file mode 160000 +Subproject 240296800824e40b10cb8c16da0e71156335394 diff --git a/src/include.am b/src/include.am index f78853f50f..90ecf90d45 100644 --- a/src/include.am +++ b/src/include.am @@ -2,6 +2,7 @@ include src/ext/include.am include src/trunnel/include.am include src/common/include.am include src/or/include.am +include src/rust/include.am include src/test/include.am include src/tools/include.am include src/win32/include.am diff --git a/src/or/include.am b/src/or/include.am index 7b031f737b..1ef5afa013 100644 --- a/src/or/include.am +++ b/src/or/include.am @@ -124,7 +124,8 @@ src_or_tor_LDADD = src/or/libtor.a src/common/libor.a src/common/libor-ctime.a \ src/trace/libor-trace.a \ @TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ @TOR_LIBEVENT_LIBS@ @TOR_OPENSSL_LIBS@ \ @TOR_LIB_WS32@ @TOR_LIB_GDI@ @CURVE25519_LIBS@ @TOR_SYSTEMD_LIBS@ \ - @TOR_LZMA_LIBS@ @TOR_ZSTD_LIBS@ + @TOR_LZMA_LIBS@ @TOR_ZSTD_LIBS@ \ + $(rust_ldadd) if COVERAGE_ENABLED src_or_tor_cov_SOURCES = src/or/tor_main.c diff --git a/src/or/main.c b/src/or/main.c index 398c4f63d2..2520a7e21d 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -59,6 +59,7 @@ #include "circuitlist.h" #include "circuituse.h" #include "command.h" +#include "compat_rust.h" #include "compress.h" #include "config.h" #include "confparse.h" @@ -3073,6 +3074,15 @@ tor_init(int argc, char *argv[]) "Expect more bugs than usual."); } + { + rust_str_t rust_str = rust_welcome_string(); + const char *s = rust_str_get(rust_str); + if (strlen(s) > 0) { + log_notice(LD_GENERAL, "%s", s); + } + rust_str_free(rust_str); + } + if (network_init()<0) { log_err(LD_BUG,"Error initializing network; exiting."); return -1; diff --git a/src/rust/.cargo/config.in b/src/rust/.cargo/config.in new file mode 100644 index 0000000000..414b253a57 --- /dev/null +++ b/src/rust/.cargo/config.in @@ -0,0 +1,8 @@ +[source] + +@RUST_DL@ [source.crates-io] +@RUST_DL@ registry = 'https://github.com/rust-lang/crates.io-index' +@RUST_DL@ replace-with = 'vendored-sources' + +@RUST_DL@ [source.vendored-sources] +@RUST_DL@ directory = '@RUST_DEPENDENCIES@' diff --git a/src/rust/.rustfmt.toml b/src/rust/.rustfmt.toml new file mode 100644 index 0000000000..f25bd51883 --- /dev/null +++ b/src/rust/.rustfmt.toml @@ -0,0 +1,2 @@ +max_width = 80 +comment_width = 80 diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock new file mode 100644 index 0000000000..4ac9606ce8 --- /dev/null +++ b/src/rust/Cargo.lock @@ -0,0 +1,14 @@ +[root] +name = "tor_util" +version = "0.0.1" +dependencies = [ + "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libc" +version = "0.2.22" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[metadata] +"checksum libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)" = "babb8281da88cba992fa1f4ddec7d63ed96280a1a53ec9b919fd37b53d71e502" diff --git a/src/rust/Cargo.toml b/src/rust/Cargo.toml new file mode 100644 index 0000000000..fc4377e8b4 --- /dev/null +++ b/src/rust/Cargo.toml @@ -0,0 +1,7 @@ +[workspace] +members = ["tor_util"] + +[profile.release] +debug = true +panic = "abort" + diff --git a/src/rust/include.am b/src/rust/include.am new file mode 100644 index 0000000000..20afc6c4db --- /dev/null +++ b/src/rust/include.am @@ -0,0 +1,6 @@ +include src/rust/tor_util/include.am + +EXTRA_DIST +=\ + src/rust/Cargo.toml \ + src/rust/Cargo.lock \ + src/rust/.cargo/config.in diff --git a/src/rust/tor_util/Cargo.toml b/src/rust/tor_util/Cargo.toml new file mode 100644 index 0000000000..f175fbdfb0 --- /dev/null +++ b/src/rust/tor_util/Cargo.toml @@ -0,0 +1,13 @@ +[package] +authors = ["The Tor Project"] +name = "tor_util" +version = "0.0.1" + +[lib] +name = "tor_util" +path = "lib.rs" +crate_type = ["rlib", "staticlib"] + +[dependencies] +libc = "*" + diff --git a/src/rust/tor_util/ffi.rs b/src/rust/tor_util/ffi.rs new file mode 100644 index 0000000000..af4bfc41af --- /dev/null +++ b/src/rust/tor_util/ffi.rs @@ -0,0 +1,56 @@ +//! FFI functions, only to be called from C. +//! +//! Equivalent C versions of these live in `src/common/compat_rust.c` + +use std::mem::forget; +use std::ffi::CString; + +use libc; +use rust_string::RustString; + +/// Free the passed `RustString` (`rust_str_t` in C), to be used in place of +/// `tor_free`(). +/// +/// # Examples +/// ```c +/// rust_str_t r_s = rust_welcome_string(); +/// rust_str_free(r_s); +/// ``` +#[no_mangle] +#[cfg_attr(feature = "cargo-clippy", allow(needless_pass_by_value))] +pub unsafe extern "C" fn rust_str_free(_str: RustString) { + // Empty body: Just drop _str and we're done (Drop takes care of it). +} + +/// Lends an immutable, NUL-terminated C String. +/// +/// # Examples +/// ```c +/// rust_str_t r_s = rust_welcome_string(); +/// const char *s = rust_str_get(r_s); +/// printf("%s", s); +/// rust_str_free(r_s); +/// ``` +#[no_mangle] +pub unsafe extern "C" fn rust_str_get(str: RustString) -> *const libc::c_char { + let res = str.as_ptr(); + forget(str); + res +} + +/// Returns a short string to announce Rust support during startup. +/// +/// # Examples +/// ```c +/// rust_str_t r_s = rust_welcome_string(); +/// const char *s = rust_str_get(r_s); +/// printf("%s", s); +/// rust_str_free(r_s); +/// ``` +#[no_mangle] +pub extern "C" fn rust_welcome_string() -> RustString { + let s = CString::new("Tor is running with Rust integration. Please report \ + any bugs you encouter.") + .unwrap(); + RustString::from(s) +} diff --git a/src/rust/tor_util/include.am b/src/rust/tor_util/include.am new file mode 100644 index 0000000000..17a755fe09 --- /dev/null +++ b/src/rust/tor_util/include.am @@ -0,0 +1,13 @@ +EXTRA_DIST +=\ + src/rust/tor_util/Cargo.toml \ + src/rust/tor_util/lib.rs \ + src/rust/tor_util/ffi.rs \ + src/rust/tor_util/rust_string.rs + +src/rust/target/release/libtor_util.a: FORCE + ( cd "$(abs_top_srcdir)/src/rust/tor_util" ; \ + CARGO_TARGET_DIR="$(abs_top_builddir)/src/rust/target" \ + HOME="$(abs_top_builddir)/src/rust" \ + $(CARGO) build --release --quiet $(CARGO_ONLINE) ) + +FORCE: diff --git a/src/rust/tor_util/lib.rs b/src/rust/tor_util/lib.rs new file mode 100644 index 0000000000..79d583d1ae --- /dev/null +++ b/src/rust/tor_util/lib.rs @@ -0,0 +1,13 @@ +//! C <-> Rust compatibility helpers and types. +//! +//! Generically useful, small scale helpers should go here. This goes for both +//! the C side (in the form of the ffi module) as well as the Rust side +//! (individual modules per functionality). The corresponding C stuff lives in +//! `src/common/compat_rust.{c,h}`. + +extern crate libc; + +mod rust_string; +pub mod ffi; + +pub use rust_string::*; diff --git a/src/rust/tor_util/rust_string.rs b/src/rust/tor_util/rust_string.rs new file mode 100644 index 0000000000..46ec3fd7a8 --- /dev/null +++ b/src/rust/tor_util/rust_string.rs @@ -0,0 +1,101 @@ +use std::ffi::CString; +use std::mem::forget; +use libc; + +/// Compatibility wrapper for strings allocated in Rust and passed to C. +/// +/// Rust doesn't ensure the safety of freeing memory across an FFI boundary, so +/// we need to take special care to ensure we're not accidentally calling +/// `tor_free`() on any string allocated in Rust. To more easily differentiate +/// between strings that possibly (if Rust support is enabled) were allocated +/// in Rust, C has the `rust_str_t` helper type. The equivalent on the Rust +/// side is `RustString`. +/// +/// Note: This type must not be used for strings allocated in C. +#[repr(C)] +#[derive(Debug)] +pub struct RustString(*mut libc::c_char); + +impl RustString { + /// Returns a pointer to the underlying NUL-terminated byte array. + /// + /// Note that this function is not typically useful for Rust callers, + /// except in a direct FFI context. + /// + /// # Examples + /// ``` + /// # use tor_util::RustString; + /// use std::ffi::CString; + /// + /// let r = RustString::from(CString::new("asdf").unwrap()); + /// let c_str = r.as_ptr(); + /// assert_eq!(b'a', unsafe { *c_str as u8}); + /// ``` + pub fn as_ptr(&self) -> *const libc::c_char { + self.0 as *const libc::c_char + } +} + +impl From<CString> for RustString { + /// Constructs a new `RustString` + /// + /// # Examples + /// ``` + /// # use tor_util::RustString; + /// use std::ffi::CString; + /// + /// let r = RustString::from(CString::new("asdf").unwrap()); + /// ``` + fn from(str: CString) -> RustString { + RustString(str.into_raw()) + } +} + +impl Into<CString> for RustString { + /// Reconstructs a `CString` from this `RustString`. + /// + /// Useful to take ownership back from a `RustString` that was given to C + /// code. + /// + /// # Examples + /// ``` + /// # use tor_util::RustString; + /// use std::ffi::CString; + /// + /// let cs = CString::new("asdf").unwrap(); + /// let r = RustString::from(cs.clone()); + /// let cs2 = r.into(); + /// assert_eq!(cs, cs2); + /// ``` + fn into(self) -> CString { + // Calling from_raw is always OK here: We only construct self using + // valid CStrings and don't expose anything that could mutate it + let ret = unsafe { CString::from_raw(self.0) }; + forget(self); + ret + } +} + +impl Drop for RustString { + fn drop(&mut self) { + // Don't use into() here, because we would need to move out of + // self. Same safety consideration. Immediately drop the created + // CString, which takes care of freeing the wrapped string. + unsafe { CString::from_raw(self.0) }; + } +} + +#[cfg(test)] +mod test { + use std::mem; + use super::*; + + use libc; + + /// Ensures we're not adding overhead by using RustString. + #[test] + fn size_of() { + assert_eq!(mem::size_of::<*mut libc::c_char>(), + mem::size_of::<RustString>()) + } +} diff --git a/src/rust/tor_util/tests/rust_string.rs b/src/rust/tor_util/tests/rust_string.rs new file mode 100644 index 0000000000..1ff605a43c --- /dev/null +++ b/src/rust/tor_util/tests/rust_string.rs @@ -0,0 +1,37 @@ +extern crate tor_util; +extern crate libc; + +use std::ffi::CString; +use tor_util::RustString; + +#[test] +fn rust_string_conversions_preserve_c_string() { + let s = CString::new("asdf foo").unwrap(); + let r = RustString::from(s.clone()); + let r2 = RustString::from(s.clone()); + let c = r2.as_ptr(); + assert_eq!(unsafe { libc::strlen(c) }, 8); + let c_str = r.into(); + assert_eq!(s, c_str); +} + +#[test] +fn empty_string() { + let s = CString::new("").unwrap(); + let r = RustString::from(s.clone()); + let c = r.as_ptr(); + assert_eq!(unsafe { libc::strlen(c) }, 0); + let c_str = r.into(); + assert_eq!(s, c_str); +} + +#[test] +fn c_string_with_unicode() { + // The euro sign is three bytes + let s = CString::new("asd€asd").unwrap(); + let r = RustString::from(s.clone()); + let c = r.as_ptr(); + assert_eq!(unsafe { libc::strlen(c) }, 9); + let c_str = r.into(); + assert_eq!(s, c_str); +} diff --git a/src/test/fuzz/include.am b/src/test/fuzz/include.am index 500377f6d7..6008238bba 100644 --- a/src/test/fuzz/include.am +++ b/src/test/fuzz/include.am @@ -20,7 +20,8 @@ FUZZING_LIBS = \ @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@ @CURVE25519_LIBS@ \ @TOR_SYSTEMD_LIBS@ \ @TOR_LZMA_LIBS@ \ - @TOR_ZSTD_LIBS@ + @TOR_ZSTD_LIBS@ \ + $(rust_ldadd) oss-fuzz-prereqs: \ src/or/libtor-testing.a \ diff --git a/src/test/include.am b/src/test/include.am index 4d6215e593..29ba1ce7c9 100644 --- a/src/test/include.am +++ b/src/test/include.am @@ -5,8 +5,11 @@ TESTS_ENVIRONMENT = \ export PYTHON="$(PYTHON)"; \ export SHELL="$(SHELL)"; \ export abs_top_srcdir="$(abs_top_srcdir)"; \ + export abs_top_builddir="$(abs_top_builddir)"; \ export builddir="$(builddir)"; \ - export TESTING_TOR_BINARY="$(TESTING_TOR_BINARY)"; + export TESTING_TOR_BINARY="$(TESTING_TOR_BINARY)"; \ + export CARGO="$(CARGO)"; \ + export CARGO_ONLINE="$(CARGO_ONLINE)"; TESTSCRIPTS = \ src/test/fuzz_static_testcases.sh \ @@ -19,6 +22,11 @@ TESTSCRIPTS = \ src/test/test_workqueue_socketpair.sh \ src/test/test_switch_id.sh +if USE_RUST +TESTSCRIPTS += \ + src/test/test_rust.sh +endif + if USEPYTHON TESTSCRIPTS += src/test/test_ntor.sh src/test/test_hs_ntor.sh src/test/test_bt.sh endif @@ -132,6 +140,7 @@ src_test_test_SOURCES = \ src/test/test_routerkeys.c \ src/test/test_routerlist.c \ src/test/test_routerset.c \ + src/test/test_rust.c \ src/test/test_scheduler.c \ src/test/test_shared_random.c \ src/test/test_socks.c \ @@ -183,7 +192,8 @@ src_test_test_switch_id_LDADD = \ src/common/libor-testing.a \ src/common/libor-ctime-testing.a \ @TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ \ - @TOR_LZMA_LIBS@ @TOR_ZSTD_LIBS@ + @TOR_LZMA_LIBS@ @TOR_ZSTD_LIBS@ \ + $(rust_ldadd) src_test_test_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ \ @TOR_LDFLAGS_libevent@ @@ -198,7 +208,8 @@ src_test_test_LDADD = src/or/libtor-testing.a \ src/trace/libor-trace.a \ @TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ @TOR_LIBEVENT_LIBS@ \ @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@ @CURVE25519_LIBS@ \ - @TOR_SYSTEMD_LIBS@ @TOR_LZMA_LIBS@ @TOR_ZSTD_LIBS@ + @TOR_SYSTEMD_LIBS@ @TOR_LZMA_LIBS@ @TOR_ZSTD_LIBS@ \ + $(rust_ldadd) src_test_test_slow_CPPFLAGS = $(src_test_test_CPPFLAGS) src_test_test_slow_CFLAGS = $(src_test_test_CFLAGS) @@ -222,7 +233,8 @@ src_test_bench_LDADD = src/or/libtor.a src/common/libor.a \ src/trace/libor-trace.a \ @TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ @TOR_LIBEVENT_LIBS@ \ @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@ @CURVE25519_LIBS@ \ - @TOR_SYSTEMD_LIBS@ @TOR_LZMA_LIBS@ @TOR_ZSTD_LIBS@ + @TOR_SYSTEMD_LIBS@ @TOR_LZMA_LIBS@ @TOR_ZSTD_LIBS@ \ + $(rust_ldadd) src_test_test_workqueue_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ \ @TOR_LDFLAGS_libevent@ @@ -234,7 +246,8 @@ src_test_test_workqueue_LDADD = src/or/libtor-testing.a \ src/trace/libor-trace.a \ @TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ @TOR_LIBEVENT_LIBS@ \ @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@ @CURVE25519_LIBS@ \ - @TOR_LZMA_LIBS@ @TOR_ZSTD_LIBS@ + @TOR_LZMA_LIBS@ @TOR_ZSTD_LIBS@ \ + $(rust_ldadd) src_test_test_timers_CPPFLAGS = $(src_test_test_CPPFLAGS) src_test_test_timers_CFLAGS = $(src_test_test_CFLAGS) @@ -245,7 +258,8 @@ src_test_test_timers_LDADD = \ src/common/libor-crypto-testing.a $(LIBKECCAK_TINY) $(LIBDONNA) \ @TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ @TOR_LIBEVENT_LIBS@ \ @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@ @CURVE25519_LIBS@ \ - @TOR_LZMA_LIBS@ + @TOR_LZMA_LIBS@ \ + $(rust_ldadd) src_test_test_timers_LDFLAGS = $(src_test_test_LDFLAGS) noinst_HEADERS+= \ @@ -273,7 +287,8 @@ src_test_test_ntor_cl_LDADD = src/or/libtor.a src/common/libor.a \ src/trace/libor-trace.a \ @TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ \ @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@ @CURVE25519_LIBS@ \ - @TOR_LZMA_LIBS@ + @TOR_LZMA_LIBS@ \ + $(rust_ldadd) src_test_test_ntor_cl_AM_CPPFLAGS = \ -I"$(top_srcdir)/src/or" @@ -294,7 +309,8 @@ src_test_test_bt_cl_LDADD = src/common/libor-testing.a \ src/common/libor-ctime-testing.a \ src/trace/libor-trace.a \ @TOR_LIB_MATH@ \ - @TOR_LIB_WS32@ @TOR_LIB_GDI@ + @TOR_LIB_WS32@ @TOR_LIB_GDI@ \ + $(rust_ldadd) src_test_test_bt_cl_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS) src_test_test_bt_cl_CPPFLAGS= $(src_test_AM_CPPFLAGS) $(TEST_CPPFLAGS) @@ -309,6 +325,7 @@ EXTRA_DIST += \ src/test/test_zero_length_keys.sh \ src/test/test_ntor.sh src/test/test_hs_ntor.sh src/test/test_bt.sh \ src/test/test-network.sh \ + src/test/test_rust.sh \ src/test/test_switch_id.sh \ src/test/test_workqueue_cancel.sh \ src/test/test_workqueue_efd.sh \ diff --git a/src/test/test.c b/src/test/test.c index 30944d805d..68f5f90fd7 100644 --- a/src/test/test.c +++ b/src/test/test.c @@ -1234,6 +1234,7 @@ struct testgroup_t testgroups[] = { { "routerkeys/", routerkeys_tests }, { "routerlist/", routerlist_tests }, { "routerset/" , routerset_tests }, + { "rust/", rust_tests }, { "scheduler/", scheduler_tests }, { "socks/", socks_tests }, { "shared-random/", sr_tests }, diff --git a/src/test/test.h b/src/test/test.h index 0ba91fb3f6..6abaf39e6f 100644 --- a/src/test/test.h +++ b/src/test/test.h @@ -232,6 +232,7 @@ extern struct testcase_t router_tests[]; extern struct testcase_t routerkeys_tests[]; extern struct testcase_t routerlist_tests[]; extern struct testcase_t routerset_tests[]; +extern struct testcase_t rust_tests[]; extern struct testcase_t scheduler_tests[]; extern struct testcase_t storagedir_tests[]; extern struct testcase_t socks_tests[]; diff --git a/src/test/test_rust.c b/src/test/test_rust.c new file mode 100644 index 0000000000..6ad57d6fcb --- /dev/null +++ b/src/test/test_rust.c @@ -0,0 +1,31 @@ +/* Copyright (c) 2017, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#include "orconfig.h" +#include "compat_rust.h" +#include "test.h" +#include "util.h" + +static void +test_welcome_string(void *arg) +{ + (void)arg; + rust_str_t s = rust_welcome_string(); + const char *c_str = rust_str_get(s); + tt_assert(c_str); + size_t len = strlen(c_str); +#ifdef HAVE_RUST + tt_assert(len > 0); +#else + tt_assert(len == 0); +#endif + + done: + rust_str_free(s); +} + +struct testcase_t rust_tests[] = { + { "welcome_string", test_welcome_string, 0, NULL, NULL }, + END_OF_TESTCASES +}; + diff --git a/src/test/test_rust.sh b/src/test/test_rust.sh new file mode 100755 index 0000000000..4427c70f13 --- /dev/null +++ b/src/test/test_rust.sh @@ -0,0 +1,13 @@ +#!/bin/sh +# Test all the Rust crates we're using + +crates=tor_util + +exitcode=0 + +for crate in $crates; do + cd "${abs_top_srcdir:-.}/src/rust/${crate}" + CARGO_TARGET_DIR="${abs_top_builddir}/src/rust/target" HOME="${abs_top_builddir}/src/rust" "${CARGO:-cargo}" test ${CARGO_ONLINE-"--frozen"} || exitcode=1 +done + +exit $exitcode diff --git a/src/tools/include.am b/src/tools/include.am index 5eadb03a05..717af9e2ae 100644 --- a/src/tools/include.am +++ b/src/tools/include.am @@ -8,7 +8,8 @@ src_tools_tor_resolve_SOURCES = src/tools/tor-resolve.c src_tools_tor_resolve_LDFLAGS = src_tools_tor_resolve_LDADD = src/common/libor.a \ src/common/libor-ctime.a \ - @TOR_LIB_MATH@ @TOR_LIB_WS32@ + @TOR_LIB_MATH@ @TOR_LIB_WS32@ \ + $(rust_ldadd) if COVERAGE_ENABLED src_tools_tor_cov_resolve_SOURCES = src/tools/tor-resolve.c @@ -22,11 +23,12 @@ endif src_tools_tor_gencert_SOURCES = src/tools/tor-gencert.c src_tools_tor_gencert_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ src_tools_tor_gencert_LDADD = src/common/libor.a src/common/libor-crypto.a \ - src/common/libor-ctime.a \ - $(LIBKECCAK_TINY) \ - $(LIBDONNA) \ - @TOR_LIB_MATH@ @TOR_ZLIB_LIBS@ @TOR_OPENSSL_LIBS@ \ - @TOR_LIB_WS32@ @TOR_LIB_GDI@ @CURVE25519_LIBS@ + src/common/libor-ctime.a \ + $(LIBKECCAK_TINY) \ + $(LIBDONNA) \ + @TOR_LIB_MATH@ @TOR_ZLIB_LIBS@ @TOR_OPENSSL_LIBS@ \ + @TOR_LIB_WS32@ @TOR_LIB_GDI@ @CURVE25519_LIBS@ \ + $(rust_ldadd) if COVERAGE_ENABLED src_tools_tor_cov_gencert_SOURCES = src/tools/tor-gencert.c |