libs: Move cstr!() into its own crate
Make the macro host_supported, for unittests.
This overshadows the homonymous crate from crates.io [1] but importing
and depending on an external crate for <10 lines of code seems overkill.
[1]: https://crates.io/crates/cstr
Bug: 308694211
Test: atest libcstr.tests
Test: m libcstr
Test: m pvmfw_bin rialto_bin vmbase_example_bin
Change-Id: If1bf37034fc004a380b3ba528b9d76393a865d3e
diff --git a/libs/cstr/Android.bp b/libs/cstr/Android.bp
new file mode 100644
index 0000000..4ea87df
--- /dev/null
+++ b/libs/cstr/Android.bp
@@ -0,0 +1,36 @@
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+rust_library_rlib {
+ name: "libcstr",
+ crate_name: "cstr",
+ defaults: ["avf_build_flags_rust"],
+ srcs: ["src/lib.rs"],
+ edition: "2021",
+ host_supported: true,
+ prefer_rlib: true,
+ target: {
+ android: {
+ no_stdlibs: true,
+ stdlibs: [
+ "libcompiler_builtins.rust_sysroot",
+ "libcore.rust_sysroot",
+ ],
+ },
+ },
+ apex_available: [
+ "//apex_available:platform",
+ "//apex_available:anyapex",
+ ],
+}
+
+rust_test {
+ name: "libcstr.tests",
+ crate_name: "libcstr_test",
+ defaults: ["avf_build_flags_rust"],
+ srcs: ["src/lib.rs"],
+ test_suites: ["general-tests"],
+ prefer_rlib: true,
+ rustlibs: ["libcstr"],
+}
diff --git a/libs/cstr/src/lib.rs b/libs/cstr/src/lib.rs
new file mode 100644
index 0000000..ddf20fc
--- /dev/null
+++ b/libs/cstr/src/lib.rs
@@ -0,0 +1,50 @@
+// Copyright 2023, The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! Provide a safe const-compatible no_std macro for readable &'static CStr.
+
+#![no_std]
+
+/// Create &CStr out of &str literal
+#[macro_export]
+macro_rules! cstr {
+ ($str:literal) => {{
+ const S: &str = concat!($str, "\0");
+ const C: &::core::ffi::CStr = match ::core::ffi::CStr::from_bytes_with_nul(S.as_bytes()) {
+ Ok(v) => v,
+ Err(_) => panic!("string contains interior NUL"),
+ };
+ C
+ }};
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use std::ffi::CString;
+
+ #[test]
+ fn valid_input_string() {
+ let expected = CString::new("aaa").unwrap();
+ assert_eq!(cstr!("aaa"), expected.as_c_str());
+ }
+
+ #[test]
+ fn valid_empty_string() {
+ let expected = CString::new("").unwrap();
+ assert_eq!(cstr!(""), expected.as_c_str());
+ }
+
+ // As cstr!() panics at compile time, tests covering invalid inputs fail to compile!
+}
diff --git a/libs/libfdt/Android.bp b/libs/libfdt/Android.bp
index b889ee5..5920d5d 100644
--- a/libs/libfdt/Android.bp
+++ b/libs/libfdt/Android.bp
@@ -37,6 +37,7 @@
"libcore.rust_sysroot",
],
rustlibs: [
+ "libcstr",
"liblibfdt_bindgen",
"libzerocopy_nostd",
],
@@ -61,6 +62,7 @@
],
prefer_rlib: true,
rustlibs: [
+ "libcstr",
"liblibfdt",
],
}
diff --git a/libs/libfdt/src/lib.rs b/libs/libfdt/src/lib.rs
index b369390..6cfe5f7 100644
--- a/libs/libfdt/src/lib.rs
+++ b/libs/libfdt/src/lib.rs
@@ -31,15 +31,9 @@
use core::ops::Range;
use core::ptr;
use core::result;
+use cstr::cstr;
use zerocopy::AsBytes as _;
-// TODO(b/308694211): Use cstr!() from vmbase
-macro_rules! cstr {
- ($str:literal) => {{
- core::ffi::CStr::from_bytes_with_nul(concat!($str, "\0").as_bytes()).unwrap()
- }};
-}
-
/// Error type corresponding to libfdt error codes.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum FdtError {
diff --git a/libs/libfdt/tests/api_test.rs b/libs/libfdt/tests/api_test.rs
index d76b1a4..63cbdee 100644
--- a/libs/libfdt/tests/api_test.rs
+++ b/libs/libfdt/tests/api_test.rs
@@ -17,23 +17,12 @@
//! Integration tests of the library libfdt.
use core::ffi::CStr;
+use cstr::cstr;
use libfdt::{Fdt, FdtError, FdtNodeMut, Phandle};
use std::ffi::CString;
use std::fs;
use std::ops::Range;
-// TODO(b/308694211): Use cstr!() from vmbase
-macro_rules! cstr {
- ($str:literal) => {{
- const S: &str = concat!($str, "\0");
- const C: &::core::ffi::CStr = match ::core::ffi::CStr::from_bytes_with_nul(S.as_bytes()) {
- Ok(v) => v,
- Err(_) => panic!("string contains interior NUL"),
- };
- C
- }};
-}
-
const TEST_TREE_WITH_ONE_MEMORY_RANGE_PATH: &str = "data/test_tree_one_memory_range.dtb";
const TEST_TREE_WITH_MULTIPLE_MEMORY_RANGES_PATH: &str =
"data/test_tree_multiple_memory_ranges.dtb";
diff --git a/pvmfw/Android.bp b/pvmfw/Android.bp
index b7b5900..b6f3940 100644
--- a/pvmfw/Android.bp
+++ b/pvmfw/Android.bp
@@ -16,6 +16,7 @@
"libbssl_ffi_nostd",
"libciborium_nostd",
"libciborium_io_nostd",
+ "libcstr",
"libdiced_open_dice_nostd",
"libfdtpci",
"libhyp",
@@ -55,6 +56,7 @@
unit_test: true,
},
rustlibs: [
+ "libcstr",
"libzeroize",
],
}
@@ -90,6 +92,7 @@
},
prefer_rlib: true,
rustlibs: [
+ "libcstr",
"liblibfdt",
"liblog_rust",
"libpvmfw_fdt_template",
diff --git a/pvmfw/src/bootargs.rs b/pvmfw/src/bootargs.rs
index a089a67..aacd8e0 100644
--- a/pvmfw/src/bootargs.rs
+++ b/pvmfw/src/bootargs.rs
@@ -108,19 +108,7 @@
#[cfg(test)]
mod tests {
use super::*;
-
- // TODO(b/308694211): Use cstr!() from vmbase
- macro_rules! cstr {
- ($str:literal) => {{
- const S: &str = concat!($str, "\0");
- const C: &::core::ffi::CStr = match ::core::ffi::CStr::from_bytes_with_nul(S.as_bytes())
- {
- Ok(v) => v,
- Err(_) => panic!("string contains interior NUL"),
- };
- C
- }};
- }
+ use cstr::cstr;
fn check(raw: &CStr, expected: Result<&[(&str, Option<&str>)], ()>) {
let actual = BootArgsIterator::new(raw);
diff --git a/pvmfw/src/crypto.rs b/pvmfw/src/crypto.rs
index 2b3d921..8f31553 100644
--- a/pvmfw/src/crypto.rs
+++ b/pvmfw/src/crypto.rs
@@ -33,7 +33,7 @@
use bssl_ffi::EVP_aead_aes_256_gcm_randnonce;
use bssl_ffi::EVP_AEAD;
use bssl_ffi::EVP_AEAD_CTX;
-use vmbase::cstr;
+use cstr::cstr;
#[derive(Debug)]
pub struct Error {
diff --git a/pvmfw/src/dice.rs b/pvmfw/src/dice.rs
index cc31f34..112c24c 100644
--- a/pvmfw/src/dice.rs
+++ b/pvmfw/src/dice.rs
@@ -17,12 +17,12 @@
use core::ffi::c_void;
use core::mem::size_of;
use core::slice;
+use cstr::cstr;
use diced_open_dice::{
bcc_format_config_descriptor, bcc_handover_main_flow, hash, Config, DiceConfigValues, DiceMode,
Hash, InputValues, HIDDEN_SIZE,
};
use pvmfw_avb::{DebugLevel, Digest, VerifiedBootData};
-use vmbase::cstr;
use vmbase::memory::flushed_zeroize;
fn to_dice_mode(debug_level: DebugLevel) -> DiceMode {
diff --git a/pvmfw/src/fdt.rs b/pvmfw/src/fdt.rs
index 7655614..4fe2c34 100644
--- a/pvmfw/src/fdt.rs
+++ b/pvmfw/src/fdt.rs
@@ -28,6 +28,7 @@
use core::fmt;
use core::mem::size_of;
use core::ops::Range;
+use cstr::cstr;
use fdtpci::PciMemoryFlags;
use fdtpci::PciRangeType;
use libfdt::AddressRange;
@@ -41,7 +42,6 @@
use log::info;
use log::warn;
use tinyvec::ArrayVec;
-use vmbase::cstr;
use vmbase::fdt::SwiotlbInfo;
use vmbase::layout::{crosvm::MEM_START, MAX_VIRT_ADDR};
use vmbase::memory::SIZE_4KB;
diff --git a/rialto/Android.bp b/rialto/Android.bp
index 326f6fc..12d6e7b 100644
--- a/rialto/Android.bp
+++ b/rialto/Android.bp
@@ -13,6 +13,7 @@
"libbssl_ffi_nostd",
"libciborium_io_nostd",
"libciborium_nostd",
+ "libcstr",
"libdiced_open_dice_nostd",
"libdiced_sample_inputs_nostd",
"libhyp",
diff --git a/rialto/src/fdt.rs b/rialto/src/fdt.rs
index 8bb40c3..09cdd36 100644
--- a/rialto/src/fdt.rs
+++ b/rialto/src/fdt.rs
@@ -15,8 +15,8 @@
//! High-level FDT functions.
use core::ops::Range;
+use cstr::cstr;
use libfdt::{Fdt, FdtError};
-use vmbase::cstr;
/// Reads the DICE data range from the given `fdt`.
pub fn read_dice_range_from(fdt: &Fdt) -> libfdt::Result<Range<usize>> {
diff --git a/vmbase/Android.bp b/vmbase/Android.bp
index b2b1549..e682773 100644
--- a/vmbase/Android.bp
+++ b/vmbase/Android.bp
@@ -76,6 +76,7 @@
rustlibs: [
"libaarch64_paging",
"libbuddy_system_allocator",
+ "libcstr",
"libfdtpci",
"libhyp",
"liblibfdt",
diff --git a/vmbase/example/Android.bp b/vmbase/example/Android.bp
index ae1a593..fe9de44 100644
--- a/vmbase/example/Android.bp
+++ b/vmbase/example/Android.bp
@@ -9,6 +9,7 @@
srcs: ["src/main.rs"],
rustlibs: [
"libaarch64_paging",
+ "libcstr",
"libdiced_open_dice_nostd",
"libfdtpci",
"liblibfdt",
diff --git a/vmbase/example/src/main.rs b/vmbase/example/src/main.rs
index ebd981c..6f513ee 100644
--- a/vmbase/example/src/main.rs
+++ b/vmbase/example/src/main.rs
@@ -28,11 +28,12 @@
use aarch64_paging::paging::MemoryRegion;
use aarch64_paging::MapError;
use alloc::{vec, vec::Vec};
+use cstr::cstr;
use fdtpci::PciInfo;
use libfdt::Fdt;
use log::{debug, error, info, trace, warn, LevelFilter};
use vmbase::{
- bionic, configure_heap, cstr,
+ bionic, configure_heap,
layout::{dtb_range, rodata_range, scratch_range, text_range},
linker, logger, main,
memory::{PageTable, SIZE_64KB},
diff --git a/vmbase/src/bionic.rs b/vmbase/src/bionic.rs
index f8db1fe..a049616 100644
--- a/vmbase/src/bionic.rs
+++ b/vmbase/src/bionic.rs
@@ -22,11 +22,12 @@
use core::str;
use crate::console;
-use crate::cstr;
use crate::eprintln;
use crate::rand::fill_with_entropy;
use crate::read_sysreg;
+use cstr::cstr;
+
const EOF: c_int = -1;
const EIO: c_int = 5;
diff --git a/vmbase/src/fdt.rs b/vmbase/src/fdt.rs
index 537ca03..4101f7e 100644
--- a/vmbase/src/fdt.rs
+++ b/vmbase/src/fdt.rs
@@ -14,8 +14,8 @@
//! High-level FDT functions.
-use crate::cstr;
use core::ops::Range;
+use cstr::cstr;
use libfdt::{self, Fdt, FdtError};
/// Represents information about a SWIOTLB buffer.
diff --git a/vmbase/src/util.rs b/vmbase/src/util.rs
index 25586bc..8c230a1 100644
--- a/vmbase/src/util.rs
+++ b/vmbase/src/util.rs
@@ -16,19 +16,6 @@
use core::ops::Range;
-/// Create &CStr out of &str literal
-#[macro_export]
-macro_rules! cstr {
- ($str:literal) => {{
- const S: &str = concat!($str, "\0");
- const C: &::core::ffi::CStr = match ::core::ffi::CStr::from_bytes_with_nul(S.as_bytes()) {
- Ok(v) => v,
- Err(_) => panic!("string contains interior NUL"),
- };
- C
- }};
-}
-
/// Flatten [[T; N]] into &[T]
/// TODO: use slice::flatten when it graduates from experimental
pub fn flatten<T, const N: usize>(original: &[[T; N]]) -> &[T] {