From a976cf5a420369362b502cafa47e19adeef3aeb4 Mon Sep 17 00:00:00 2001 From: Apoorv Kothari Date: Tue, 17 Sep 2024 17:05:00 -0700 Subject: [PATCH] auto gen script --- implicit_default_detection/Cargo.toml | 7 ++ implicit_default_detection/src/main.rs | 154 +++++++++++++++++++++++++ 2 files changed, 161 insertions(+) create mode 100644 implicit_default_detection/Cargo.toml create mode 100644 implicit_default_detection/src/main.rs diff --git a/implicit_default_detection/Cargo.toml b/implicit_default_detection/Cargo.toml new file mode 100644 index 00000000000..64ab76e1221 --- /dev/null +++ b/implicit_default_detection/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "implicit_default_detection" +version = "0.1.0" +edition = "2021" + +[dependencies] +regex = "1.10.6" diff --git a/implicit_default_detection/src/main.rs b/implicit_default_detection/src/main.rs new file mode 100644 index 00000000000..98b45570f5e --- /dev/null +++ b/implicit_default_detection/src/main.rs @@ -0,0 +1,154 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +use regex::Regex; +use std::ffi::OsStr; +use std::fs; +use std::fs::read_to_string; +use std::fs::File; +use std::io::Write; +use std::path::PathBuf; +use std::process::Command; + +// TODO: +// +// - s2n_config_new() and then check for comment +// D- compare clang-format command +// D- rename s2n_testing_old_default_security_policy +// + +fn main() { + // get list of all test files + for test_file in fs::read_dir("../tests/unit").unwrap() { + let test_file = test_file.as_ref().unwrap(); + let test_file_path = test_file.path(); + + let is_file = test_file.file_type().unwrap().is_file(); + // filter on .c files + let is_c_file = test_file_path.extension().unwrap_or(OsStr::new("not_c")) == "c"; + + if is_file && is_c_file { + let lines = read_file_to_vec(&test_file_path); + + // TODO rm after testing + // if !test_file_path.ends_with("s2n_client_hello_test.c") { + // if !test_file_path.ends_with("s2n_server_hello_test.c") { + // continue; + // } + + process_test_file(test_file_path, lines); + } + } +} + +fn process_test_file(test_file_path: PathBuf, lines: Vec) { + let test_file_name = test_file_path.file_name().unwrap().to_str().unwrap(); + + // create temp file + let tmp_filename = format!("tmp_{}", test_file_name); + let mut tmp_file = File::create(tmp_filename.clone()).unwrap(); + + let mut line_idx = 0; + while line_idx < lines.len() { + let line = &lines[line_idx]; + + // write the current line + writeln!(tmp_file, "{}", line).unwrap(); + + if match_config_new(line) { + if config_creation_spans_two_lines(&lines, line_idx) { + // config creating spans two lines so write it + let nxt_line = &lines[line_idx + 1]; + writeln!(tmp_file, "{}", nxt_line).unwrap(); + + // increment line since config creation was 2 lines + line_idx += 1; + } + + // insert auto gen + let config_name = get_config_name(line); + let auto_gen = format!( + "EXPECT_SUCCESS(s2n_config_set_cipher_preferences({}, s2n_auto_gen_old_default_security_policy()));", + config_name + ); + writeln!(tmp_file, "{}", auto_gen).unwrap(); + } + + // increment to next line + line_idx += 1; + } + + println!("Amended file: {:?}", test_file_path); + fs::rename(tmp_filename, test_file_path.clone()).unwrap(); + Command::new("clang-format") + .arg("-i") + .arg(test_file_path) + .status() + .unwrap(); +} + +fn match_config_new(line: &str) -> bool { + const S2N_CONFIG_NEW: &str = "s2n_config_new()"; + line.contains(S2N_CONFIG_NEW) +} + +// These are the possible occurances of s2n_config_new() +// +// ``` +// DEFER_CLEANUP(struct s2n_config *config = s2n_config_new(), +// struct s2n_config *config = s2n_config_new(); +// DEFER_CLEANUP(struct s2n_config *config = s2n_config_new(), s2n_config_ptr_free); +// EXPECT_NOT_NULL(config = s2n_config_new()); +// POSIX_GUARD_PTR(server_config = s2n_config_new()); +// POSIX_ENSURE_REF(client_config = s2n_config_new()); +// ``` +fn get_config_name(line: &str) -> String { + // DEFER_CLEANUP(struct s2n_config *config = s2n_config_new(), + // struct s2n_config *config = s2n_config_new(); + // DEFER_CLEANUP(struct s2n_config *config = s2n_config_new(), s2n_config_ptr_free); + let config_name = line.trim(); + let re = Regex::new(r".*struct s2n_config \*").unwrap(); + let config_name: String = re.replace(config_name, "").into_owned(); + + // EXPECT_NOT_NULL(config = s2n_config_new()); + let config_name = config_name.replace("EXPECT_NOT_NULL(", ""); + + // POSIX_GUARD_PTR(server_config = s2n_config_new()); + let config_name = config_name.replace("POSIX_GUARD_PTR(", ""); + + // POSIX_ENSURE_REF(client_config = s2n_config_new()); + let config_name = config_name.replace("POSIX_ENSURE_REF(", ""); + + // remove the end + let re = Regex::new(r" = .*").unwrap(); + let config_name: String = re.replace(&config_name, "").into_owned(); + + // println!("{}", config_name); + config_name +} + +// detect if config creating spans two lines by keying on `s2n_config_ptr_free` +// +// ``` +// DEFER_CLEANUP(struct s2n_config *config = s2n_config_new(), +// s2n_config_ptr_free); +// ``` +fn config_creation_spans_two_lines(lines: &[String], idx: usize) -> bool { + let s2n_config_ptr_free = "s2n_config_ptr_free"; + + if let Some(next_line) = lines.get(idx + 1) { + if next_line.contains(s2n_config_ptr_free) { + return true; + } + } + + false +} + +fn read_file_to_vec(path: &PathBuf) -> Vec { + let mut result = Vec::new(); + for line in read_to_string(path).unwrap().lines() { + result.push(line.to_string()); + } + result +}