diff --git a/README.md b/README.md index 23c7ecb0..802d1e4c 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,8 @@ CASR is maintained by: CASR is a set of tools that allows you to collect crash reports in different ways. Use `casr-core` binary to deal with coredumps. Use `casr-san` to analyze -ASAN reports or `casr-ubsan` to analyze UBSAN reports. Try `casr-gdb` to get +ASAN reports or `casr-msan` to analyze +MSAN reports or `casr-ubsan` to analyze UBSAN reports. Try `casr-gdb` to get reports from gdb. Use `casr-python` to analyze python reports and get report from [Atheris](https://github.com/google/atheris). Use `casr-java` to analyze java reports and get report from @@ -74,6 +75,7 @@ crashes. It can analyze crashes from different sources: * AddressSanitizer +* MemorySanitizer * UndefinedBehaviorSanitizer * Gdb output @@ -145,6 +147,11 @@ Create report from AddressSanitizer output: $ clang++ -fsanitize=address -O0 -g casr/tests/casr_tests/test_asan_df.cpp -o test_asan_df $ casr-san -o asan.casrep -- ./test_asan_df +Create report from MemorySanitizer output: + + $ clang++ -fsanitize=memory -O0 casr/tests/casr_tests/test_msan.cpp -o test_msan + $ casr-msan -o msan.casrep -- ./test_msan + Create report from UndefinedBehaviorSanitizer output: $ clang++ -fsanitize=undefined -O0 -g casr/tests/casr_tests/ubsan/test_ubsan.cpp -o test_ubsan diff --git a/casr/src/bin/casr-cli.rs b/casr/src/bin/casr-cli.rs index f7e8a0de..447a27c1 100644 --- a/casr/src/bin/casr-cli.rs +++ b/casr/src/bin/casr-cli.rs @@ -411,6 +411,16 @@ fn build_tree_report( tree.expand_item(row); } + if !report.msan_report.is_empty() { + row = tree + .insert_container_item("MsanReport".to_string(), Placement::After, row) + .unwrap(); + report.msan_report.iter().for_each(|e| { + tree.insert_item(e.clone(), Placement::LastChild, row); + }); + tree.expand_item(row); + } + if !report.ubsan_report.is_empty() { row = tree .insert_container_item("UbsanReport".to_string(), Placement::After, row) @@ -656,6 +666,10 @@ fn build_slider_report( select.add_item("AsanReport", report.asan_report.join("\n")); } + if !report.msan_report.is_empty() { + select.add_item("MsanReport", report.msan_report.join("\n")); + } + if !report.ubsan_report.is_empty() { select.add_item("UbsanReport", report.ubsan_report.join("\n")); } diff --git a/casr/src/bin/casr-msan.rs b/casr/src/bin/casr-msan.rs new file mode 100644 index 00000000..66032f49 --- /dev/null +++ b/casr/src/bin/casr-msan.rs @@ -0,0 +1,290 @@ +use casr::util; +use libcasr::{ + msan::{MsanStacktrace, MsanContext}, + constants::{ + SIGINFO_SIGABRT, SIGINFO_SIGBUS, SIGINFO_SIGILL, SIGINFO_SIGSEGV, SIGINFO_SIGSYS, + SIGINFO_SIGTRAP, + }, + cpp::CppException, + exception::Exception, + execution_class::*, + gdb::*, + init_ignored_frames, + report::CrashReport, + severity::Severity, + stacktrace::*, +}; + +use anyhow::{bail, Context, Result}; +use clap::{Arg, ArgAction, ArgGroup}; +use gdb_command::mappings::{MappedFiles, MappedFilesExt}; +use gdb_command::stacktrace::StacktraceExt; +use gdb_command::*; +use regex::Regex; + +use std::env; +use std::os::unix::process::{CommandExt, ExitStatusExt}; +use std::path::PathBuf; +use std::process::Command; + +fn main() -> Result<()> { + let matches = clap::Command::new("casr-msan") + .version(clap::crate_version!()) + .about("Create CASR reports (.casrep) from MemorySanitizer reports") + .term_width(90) + .arg( + Arg::new("output") + .short('o') + .long("output") + .action(ArgAction::Set) + .value_name("REPORT") + .value_parser(clap::value_parser!(PathBuf)) + .help( + "Path to save report. Path can be a directory, then report name is generated", + ), + ) + .arg( + Arg::new("stdout") + .action(ArgAction::SetTrue) + .long("stdout") + .help("Print CASR report to stdout"), + ) + .group( + ArgGroup::new("out") + .args(["stdout", "output"]) + .required(true), + ) + .arg( + Arg::new("stdin") + .long("stdin") + .action(ArgAction::Set) + .value_name("FILE") + .value_parser(clap::value_parser!(PathBuf)) + .help("Stdin file for program"), + ) + .arg( + Arg::new("timeout") + .short('t') + .long("timeout") + .action(ArgAction::Set) + .default_value("0") + .value_name("SECONDS") + .help("Timeout (in seconds) for target execution, 0 value means that timeout is disabled") + .value_parser(clap::value_parser!(u64)) + ) + .arg( + Arg::new("ignore") + .long("ignore") + .action(ArgAction::Set) + .value_name("FILE") + .value_parser(clap::value_parser!(PathBuf)) + .help("File with regular expressions for functions and file paths that should be ignored"), + ) + .arg( + Arg::new("strip-path") + .long("strip-path") + .env("CASR_STRIP_PATH") + .action(ArgAction::Set) + .value_name("PREFIX") + .help("Path prefix to strip from stacktrace and crash line"), + ) + .arg( + Arg::new("ARGS") + .action(ArgAction::Set) + .num_args(1..) + .last(true) + .required(true) + .help("Add \"-- ./binary \" to run executable"), + ) + .get_matches(); + + // Get program args. + let argv: Vec<&str> = if let Some(argvs) = matches.get_many::("ARGS") { + argvs.map(|s| s.as_str()).collect() + } else { + bail!("Wrong arguments for starting program"); + }; + + init_ignored_frames!("cpp"); + + if let Some(path) = matches.get_one::("ignore") { + util::add_custom_ignored_frames(path)?; + } + // Get stdin for target program. + let stdin_file = util::stdin_from_matches(&matches)?; + + // Get timeout + let timeout = *matches.get_one::("timeout").unwrap(); + + // Set rss limit. + if let Ok(msan_options_str) = env::var("MSAN_OPTIONS") { + let mut msan_options = msan_options_str.clone(); + if !msan_options_str.contains("hard_rss_limit_mb") { + msan_options = [msan_options.as_str(), "hard_rss_limit_mb=2048"].join(","); + } + if msan_options.starts_with(',') { + msan_options.remove(0); + } + msan_options = msan_options.replace("symbolize=0", "symbolize=1"); + unsafe { + std::env::set_var("MSAN_OPTIONS", msan_options); + } + } else { + unsafe { + std::env::set_var("MSAN_OPTIONS", "hard_rss_limit_mb=2048"); + } + } + + // Run program with sanitizers. + let mut sanitizers_cmd = Command::new(argv[0]); + if let Some(ref file) = stdin_file { + sanitizers_cmd.stdin(std::fs::File::open(file).unwrap()); + } + if argv.len() > 1 { + sanitizers_cmd.args(&argv[1..]); + } + #[cfg(target_os = "macos")] + { + sanitizers_cmd.env("DYLD_NO_PIE", "1"); + } + #[cfg(target_os = "linux")] + { + use linux_personality::{Personality, personality}; + + unsafe { + sanitizers_cmd.pre_exec(|| { + if personality(Personality::ADDR_NO_RANDOMIZE).is_err() { + panic!("Cannot set personality"); + } + Ok(()) + }) + }; + } + let sanitizers_result = util::get_output(&mut sanitizers_cmd, timeout, true)?; + let sanitizers_stderr = String::from_utf8_lossy(&sanitizers_result.stderr); + + if sanitizers_stderr.contains("Cannot set personality") { + bail!("Cannot set personality (if you are running docker, allow personality syscall in your seccomp profile)"); + } + + // Create report. + let mut report = CrashReport::new(); + report.executable_path = argv[0].to_string(); + report.proc_cmdline = argv.join(" "); + let _ = report.add_os_info(); + let _ = report.add_proc_environ(); + if let Some(mut file_path) = stdin_file.clone() { + file_path = file_path.canonicalize().unwrap_or(file_path); + report.stdin = file_path.display().to_string(); + } + + let stacktrace: Stacktrace; + + // Get MASAN report. + let msan_stderr_list: Vec = sanitizers_stderr + .split('\n') + .map(|l| l.trim_end().to_string()) + .collect(); + let rmsan_start = + Regex::new(r"==\d+==\s*WARNING: MemorySanitizer:").unwrap(); + if let Some(report_start) = msan_stderr_list + .iter() + .position(|line| rmsan_start.is_match(line)) + { + // Set MASAN report in casr report. + let report_end = msan_stderr_list.iter().rposition(|s| !s.is_empty()).unwrap() + 1; + report.msan_report = Vec::from(&msan_stderr_list[report_start..report_end]); + let context = MsanContext(report.msan_report.clone()); + let severity = context.severity(); + if let Ok(severity) = severity { + report.execution_class = severity; + } else { + eprintln!("Couldn't estimate severity. {}", severity.err().unwrap()); + } + report.stacktrace = MsanStacktrace::extract_stacktrace(&report.msan_report.join("\n"))?; + } else { + // Get termination signal. + if let Some(signal) = sanitizers_result.status.signal() { + // Get stack trace and mappings from gdb. + match signal as u32 { + SIGINFO_SIGILL | SIGINFO_SIGSYS => { + report.execution_class = ExecutionClass::find("BadInstruction").unwrap(); + } + SIGINFO_SIGTRAP => { + report.execution_class = ExecutionClass::find("TrapSignal").unwrap(); + } + SIGINFO_SIGABRT => { + report.execution_class = ExecutionClass::find("AbortSignal").unwrap(); + } + SIGINFO_SIGBUS | SIGINFO_SIGSEGV => { + eprintln!("Segmentation fault occurred, but there is not enough information available to determine \ + exploitability. Try using casr-gdb instead."); + report.execution_class = ExecutionClass::find("AccessViolation").unwrap(); + } + _ => { + // "Undefined" is by default in report. + } + } + + // Get stack trace and mappings from gdb. + let gdb_result = GdbCommand::new(&ExecType::Local(&argv)) + .timeout(timeout) + .stdin(&stdin_file) + .r() + .bt() + .mappings() + .launch() + .with_context(|| "Unable to get results from gdb")?; + + let frame = Regex::new(r"^ *#[0-9]+").unwrap(); + report.stacktrace = gdb_result[0] + .split('\n') + .filter(|x| frame.is_match(x)) + .map(|x| x.to_string()) + .collect::>(); + report.proc_maps = gdb_result[1] + .split('\n') + .skip(4) + .map(|x| x.to_string()) + .collect::>(); + } else { + // Normal termination. + bail!("Program terminated (no crash)"); + } + } + + // Get stacktrace to find crash line. + stacktrace = if !report.msan_report.is_empty() { + MsanStacktrace::parse_stacktrace(&report.stacktrace)? + } else { + let mut parsed_stacktrace = GdbStacktrace::parse_stacktrace(&report.stacktrace)?; + if let Ok(mfiles) = MappedFiles::from_gdb(report.proc_maps.join("\n")) { + parsed_stacktrace.compute_module_offsets(&mfiles); + } + parsed_stacktrace + }; + + // Check for exceptions + if let Some(class) = [CppException::parse_exception] + .iter() + .find_map(|parse| parse(&sanitizers_stderr)) + { + report.execution_class = class; + } + + // Get crash line. + if let Ok(crash_line) = stacktrace.crash_line() { + report.crashline = crash_line.to_string(); + if let CrashLine::Source(debug) = crash_line { + if let Some(sources) = CrashReport::sources(&debug) { + report.source = sources; + } + } + } + + if let Some(path) = matches.get_one::("strip-path") { + util::strip_paths(&mut report, &stacktrace, path); + } + + util::output_report(&report, &matches, &argv) +} \ No newline at end of file diff --git a/casr/tests/casr_tests/test_msan.cpp b/casr/tests/casr_tests/test_msan.cpp new file mode 100644 index 00000000..2fb30129 --- /dev/null +++ b/casr/tests/casr_tests/test_msan.cpp @@ -0,0 +1,15 @@ +#include + +void set_val(bool &b, const int val) { + if (val > 1) { + b = false; + } +} + +int main(const int argc, const char *[]) { + bool b; + set_val(b, argc); + if (b) { + printf("value set\n"); + } +} \ No newline at end of file diff --git a/casr/tests/tests.rs b/casr/tests/tests.rs index 7286931f..a140f535 100644 --- a/casr/tests/tests.rs +++ b/casr/tests/tests.rs @@ -20,6 +20,7 @@ lazy_static::lazy_static! { static ref EXE_CASR_LIBFUZZER: RwLock<&'static str> = RwLock::new(env!("CARGO_BIN_EXE_casr-libfuzzer")); static ref EXE_CASR_CLUSTER: RwLock<&'static str> = RwLock::new(env!("CARGO_BIN_EXE_casr-cluster")); static ref EXE_CASR_SAN: RwLock<&'static str> = RwLock::new(env!("CARGO_BIN_EXE_casr-san")); + static ref EXE_CASR_MSAN: RwLock<&'static str> = RwLock::new(env!("CARGO_BIN_EXE_casr-msan")); static ref EXE_CASR_UBSAN: RwLock<&'static str> = RwLock::new(env!("CARGO_BIN_EXE_casr-ubsan")); static ref EXE_CASR_PYTHON: RwLock<&'static str> = RwLock::new(env!("CARGO_BIN_EXE_casr-python")); static ref EXE_CASR_LUA: RwLock<&'static str> = RwLock::new(env!("CARGO_BIN_EXE_casr-lua")); @@ -3627,6 +3628,79 @@ fn test_casr_san_sigbus() { let _ = std::fs::remove_file(&paths[1]); } + +#[test] +#[cfg(target_arch = "x86_64")] +fn test_casr_msan() { + // Double free test + let paths = [ + abs_path("tests/casr_tests/test_msan.cpp"), + abs_path("tests/tmp_tests_casr/test_msan"), + ]; + + let _ = fs::create_dir(abs_path("tests/tmp_tests_casr")); + + let clang = Command::new("bash") + .arg("-c") + .arg(format!( + "clang++ -fsanitize=memory -O0 {} -o {}", + &paths[0], &paths[1] + )) + .status() + .expect("failed to execute clang++"); + + assert!(clang.success()); + + let output = Command::new(*EXE_CASR_MSAN.read().unwrap()) + .args(["--stdout", "--", &paths[1]]) + .output() + .expect("failed to start casr-san"); + + assert!( + output.status.success(), + "Stdout: {}\n. Stderr: {}", + String::from_utf8_lossy(&output.stdout), + String::from_utf8_lossy(&output.stderr) + ); + + let report: Result = serde_json::from_slice(&output.stdout); + if let Ok(report) = report { + let severity_type = report["CrashSeverity"]["Type"].as_str().unwrap(); + let severity_desc = report["CrashSeverity"]["ShortDescription"] + .as_str() + .unwrap() + .to_string(); + let stacktrace = report["Stacktrace"] + .as_array() + .unwrap() + .iter() + .map(|x| x.to_string()) + .collect::>(); + + assert!(stacktrace.len() == 3); + assert!(stacktrace[0].contains("in main")); + assert_eq!(severity_type, "NOT_EXPLOITABLE"); + assert_eq!(severity_desc, "use-of-uninitialized-value"); + assert!( + report["CrashLine"] + .as_str() + .unwrap() + .eq("tests/casr_tests/test_msan.cpp:12:9") + // We build a test on ubuntu18 and run it on ubuntu20. + // Debug information is broken. + || report["CrashLine"] + .as_str() + .unwrap() + .contains("test_msan+0x499fd8") // We can't hardcode the offset because we rebuild tests every time. + ); + } else { + panic!("Couldn't parse json report file."); + } + let _ = std::fs::remove_file(&paths[1]); + +} + + #[test] fn test_casr_ignore_frames() { let paths = [ diff --git a/docs/usage.md b/docs/usage.md index aced46a3..3471574f 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -1,8 +1,9 @@ # Usage CASR is a set of tools that allows you to collect crash reports in different -ways. Use `casr-core` binary to deal with coredumps. Use `casr-san` to analyze -ASAN reports or `casr-ubsan` to analyze UBSAN reports. Try `casr-gdb` to get +ways. Use `casr-core` binary to deal with coredumps. e `casr-san` to analyze +ASAN reports or `casr-msan` to analyze +MSAN reports or `casr-ubsan` to analyze UBSAN reports. Try `casr-gdb` to get reports from gdb. Use `casr-python` to analyze python reports and get report from [Atheris](https://github.com/google/atheris). Use `casr-java` to analyze java reports and get report from @@ -88,6 +89,37 @@ If you are using casr-san to get CASR report for Rust fuzz target, you can choos ASAN stacktrace or Rust backtrace to analyze. If environment variable `RUST_BACKTRACE=(1|full)` is specified, then Rust backtrace is considered. +## casr-man + +Create CASR reports (.casrep) from MemorySanitizer reports + +Usage: casr-msan [OPTIONS] <--stdout|--output > -- ... + +Arguments: + ... Add "-- ./binary " to run executable + +Options: + -o, --output Path to save report. Path can be a directory, then report + name is generated + --stdout Print CASR report to stdout + --stdin Stdin file for program + -t, --timeout Timeout (in seconds) for target execution, 0 value means that + timeout is disabled [default: 0] + --ignore File with regular expressions for functions and file paths + that should be ignored + --strip-path Path prefix to strip from stacktrace and crash line [env: + CASR_STRIP_PATH=] + -h, --help Print help + -V, --version Print version + +Compile binary with ASAN: + + $ clang++ -fsanitize=memory -O0 casr/tests/casr_tests/test_msan.cpp -o test_msan + +Run casr-msan: + + $ casr-msan -o msan.casrep -- ./test_msan + ## casr-ubsan Triage errors found by UndefinedBehaviorSanitizer and create CASR reports (.casrep) diff --git a/libcasr/src/execution_class.rs b/libcasr/src/execution_class.rs index 9122f6ab..21ecae17 100644 --- a/libcasr/src/execution_class.rs +++ b/libcasr/src/execution_class.rs @@ -40,7 +40,7 @@ pub struct ExecutionClass { /// Instances of `ExecutionClass` structure. /// Add new classes to the end of array. /// TODO: Think about adding some ID for array element. -pub const CLASSES: &[(&str, &str, &str, &str); 74] = &[ +pub const CLASSES: &[(&str, &str, &str, &str); 75] = &[ ( "EXPLOITABLE", "SegFaultOnPc", @@ -485,6 +485,12 @@ pub const CLASSES: &[(&str, &str, &str, &str); 74] = &[ "Attempt to overwrite constant input", "Fuzz target overwrites its constant input.", ), + ( + "NOT_EXPLOITABLE", + "use-of-uninitialized-value", + "Use of uninitialized value", + "The target attempted to access memory that was not initialized." + ), ]; impl ExecutionClass { diff --git a/libcasr/src/lib.rs b/libcasr/src/lib.rs index b6d0fb04..704c72e2 100644 --- a/libcasr/src/lib.rs +++ b/libcasr/src/lib.rs @@ -6,6 +6,7 @@ //! It can analyze crashes from different sources: //! //! * AddressSanitizer +//! * MemorySanitizer //! * UndefinedBehaviorSanitizer //! * Gdb output //! @@ -44,3 +45,4 @@ pub mod sarif; pub mod severity; pub mod stacktrace; pub mod ubsan; +pub mod msan; diff --git a/libcasr/src/msan.rs b/libcasr/src/msan.rs new file mode 100644 index 00000000..a8c546d9 --- /dev/null +++ b/libcasr/src/msan.rs @@ -0,0 +1,44 @@ +//! Msan module implements `ParseStacktrace` and `Severity` traits for MemorySanitizer +//! reports. +use regex::Regex; + +use crate::error::*; +use crate::asan::AsanStacktrace; +use crate::execution_class::ExecutionClass; +use crate::severity::Severity; +use crate::stacktrace::ParseStacktrace; +use crate::stacktrace::*; + +/// Structure provides an interface for processing the stack trace. +pub struct MsanStacktrace; + +impl ParseStacktrace for MsanStacktrace { + fn extract_stacktrace(stream: &str) -> Result> { + return AsanStacktrace::extract_stacktrace(stream) + } + + fn parse_stacktrace_entry(entry: &str) -> Result { + return AsanStacktrace::parse_stacktrace_entry(entry) + } +} + +// Information about sanitizer crash state. +pub struct MsanContext(pub Vec); + +impl Severity for MsanContext { + fn severity(&self) -> Result { + let msan_report = &self.0; + if msan_report.is_empty() { + return Err(Error::Casr( + "Cannot estimate severity: Msan is empty.".to_string(), + )); + } + let summary = Regex::new(r"SUMMARY: *(MemorySanitizer): ([A-Za-z_\-\(\)]+)").unwrap(); + let Some(caps) = msan_report.iter().find_map(|s| summary.captures(s)) else { + return Err(Error::Casr( + "Cannot find SUMMARY in Sanitizer report".to_string(), + )); + }; + return ExecutionClass::find(caps.get(2).unwrap().as_str()); + } +} \ No newline at end of file diff --git a/libcasr/src/report.rs b/libcasr/src/report.rs index 52bd4d5c..dcb7ef8f 100644 --- a/libcasr/src/report.rs +++ b/libcasr/src/report.rs @@ -1,5 +1,6 @@ //! Report contains the main struct `CrashReport` with all information about crash. use crate::asan::AsanStacktrace; +use crate::msan::MsanStacktrace; use crate::csharp::CSharpStacktrace; use crate::error; use crate::error::*; @@ -186,6 +187,13 @@ pub struct CrashReport { )] #[cfg_attr(feature = "serde", serde(default))] pub asan_report: Vec, + /// Msan report. + #[cfg_attr( + feature = "serde", + serde(rename(serialize = "MsanReport", deserialize = "MsanReport")) + )] + #[cfg_attr(feature = "serde", serde(default))] + pub msan_report: Vec, /// Ubsan report. #[cfg_attr( feature = "serde", @@ -586,6 +594,8 @@ impl CrashReport { pub fn filtered_stacktrace(&self) -> Result { let mut rawtrace = if !self.asan_report.is_empty() { AsanStacktrace::parse_stacktrace(&self.stacktrace)? + } else if !self.msan_report.is_empty() { + MsanStacktrace::parse_stacktrace(&self.stacktrace)? } else if !self.python_report.is_empty() { PythonStacktrace::parse_stacktrace(&self.stacktrace)? } else if !self.java_report.is_empty() { @@ -743,6 +753,11 @@ impl fmt::Display for CrashReport { report += &(self.asan_report.join("\n") + "\n"); } + if !self.msan_report.is_empty() { + report += "\n===MsanReport===\n"; + report += &(self.msan_report.join("\n") + "\n"); + } + // UBSANreport if !self.ubsan_report.is_empty() { report += "\n===UbsanReport===\n"; @@ -892,6 +907,9 @@ mod tests { "==363912==ERROR: AddressSanitizer: SEGV on unknown address 0xffffffffffffffe0 (pc 0x0000004ca0e0 bp 0x7fffffff9980 sp 0x7fffffff9928 T0)".to_string(), "==363912==The signal is caused by a READ memory access.".to_string(), ]; + report.msan_report = vec![ + "==26629==WARNING: MemorySanitizer: use-of-uninitialized-value".to_string(), + ]; report.ubsan_report = vec![ "/home/hkctkuy/github/casr/casr/tests/tmp_tests_casr/test_casr_ubsan/test_ubsan.cpp:4:29: runtime error: signed integer overflow: 65535 * 32769 cannot be represented in type 'int'".to_string(), "SUMMARY: UndefinedBehaviorSanitizer: signed-integer-overflow /home/hkctkuy/github/casr/casr/tests/tmp_tests_casr/test_casr_ubsan/test_ubsan.cpp:4:29 in".to_string(), @@ -986,6 +1004,9 @@ mod tests { "==363912==ERROR: AddressSanitizer: SEGV on unknown address 0xffffffffffffffe0 (pc 0x0000004ca0e0 bp 0x7fffffff9980 sp 0x7fffffff9928 T0)".to_string(), "==363912==The signal is caused by a READ memory access.".to_string(), "".to_string(), + "===MsanReport===".to_string(), + "==26629==WARNING: MemorySanitizer: use-of-uninitialized-value".to_string(), + "".to_string(), "===UbsanReport===".to_string(), "/home/hkctkuy/github/casr/casr/tests/tmp_tests_casr/test_casr_ubsan/test_ubsan.cpp:4:29: runtime error: signed integer overflow: 65535 * 32769 cannot be represented in type 'int'".to_string(), "SUMMARY: UndefinedBehaviorSanitizer: signed-integer-overflow /home/hkctkuy/github/casr/casr/tests/tmp_tests_casr/test_casr_ubsan/test_ubsan.cpp:4:29 in".to_string(),