{"record":{"id":"897d93f321424af3","repo":"nautechsystems/nautilus_trader","slug":"cstring-new-failed","errorCode":null,"errorMessage":"CString::new failed","messagePattern":"CString::new failed","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/core/src/ffi/string.rs","lineNumber":159,"sourceCode":"/// Panics if `ptr` is not null but contains invalid UTF-8.\n#[must_use]\npub unsafe fn optional_cstr_to_str<'a>(ptr: *const c_char) -> Option<&'a str> {\n    if ptr.is_null() {\n        None\n    } else {\n        // SAFETY: Caller guarantees ptr is valid per function contract\n        Some(unsafe { cstr_as_str(ptr) })\n    }\n}\n\n/// Create a C string pointer to newly allocated memory from a [`&str`].\n///\n/// # Panics\n///\n/// Panics if the input string contains interior null bytes.\n#[must_use]\npub fn str_to_cstr(s: &str) -> *const c_char {\n    CString::new(s).expect(\"CString::new failed\").into_raw()\n}\n\n/// Drops the C string memory at the pointer.\n///\n/// # Safety\n///\n/// Assumes `ptr` is a valid C string pointer.\n///\n/// # Panics\n///\n/// Panics if `ptr` is null.\n#[unsafe(no_mangle)]\npub unsafe extern \"C\" fn cstr_drop(ptr: *const c_char) {\n    abort_on_panic(|| {\n        assert!(!ptr.is_null(), \"`ptr` was NULL\");\n        // SAFETY: Caller guarantees ptr was allocated by str_to_cstr\n        let cstring = unsafe { CString::from_raw(ptr.cast_mut()) };\n        drop(cstring);","sourceCodeStart":141,"sourceCodeEnd":177,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/core/src/ffi/string.rs#L141-L177","documentation":"str_to_cstr in crates/core/src/ffi/string.rs:159 allocates a Rust String as a C string with CString::new(s).expect(\"CString::new failed\") and leaks it as a raw pointer. CString::new fails only when the input contains an interior NUL ('\\0') byte, since C strings cannot contain embedded nulls, so the expect panics in exactly that case.","triggerScenarios":"Calling str_to_cstr (directly or via unix_nanos_to_iso8601_cstr, bar_specification_to_cstr, bar_type_to_cstr) with a &str containing a '\\0': a string sliced out of a fixed-size byte buffer that includes padding nulls, or user input containing literal NULs.","commonSituations":"Converting a fixed-size C char array (e.g. 20-byte symbol field) to &str without trimming at the first NUL; binary-ish payloads mistaken for text; timestamps or bar specs assembled from buffers with trailing zero padding.","solutions":["Strip everything from the first NUL before converting: s.split('\\0').next().unwrap() then pass that slice.","Use CStr::from_bytes_until_n (or CString::new on trimmed bytes) instead of raw buffer-to-str conversion.","Trim padding from fixed-size fields based on the field's documented length, not the full buffer.","If you control both sides, pass lengths explicitly instead of relying on C-string semantics."],"exampleFix":"// before\nlet ptr = str_to_cstr(std::str::from_utf8(&symbol_buf)?);  // symbol_buf = b\"AAPL\\0\\0...\"\n// after\nlet s = std::str::from_utf8(&symbol_buf)?.split('\\0').next().unwrap();\nlet ptr = str_to_cstr(s);","handlingStrategy":"validation","validationCode":"let s = std::str::from_utf8(&buf)?;\nassert!(!s.contains('\\0'), \"interior NUL would panic str_to_cstr\");\nlet ptr = str_to_cstr(s);","typeGuard":"fn is_cstring_safe(s: &str) -> bool {\n    !s.contains('\\0')\n}","tryCatchPattern":"// Avoid the panic entirely by using the Result-returning API\nlet c = CString::new(s).map_err(|_| \"interior NUL byte in input\")?;","preventionTips":["When converting fixed-size char buffers, cut at the first NUL (split('\\0').next()).","Never pass raw buffer-backed strings directly to C-string conversion without trimming padding.","Prefer CStr::from_bytes_until_n for buffer-to-CString conversions."],"tags":["ffi","cstring","null-byte","panic"],"backgroundTag":"invalid-argument-value","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}