use once_cell::sync::Lazy;
use regex::Regex;
pub const DANGEROUS_OPERATIONS: &[&str] = &[
"push",
"pop",
"shift",
"unshift",
"splice",
"delete",
"undef",
"srand",
"bless",
"reset",
"system",
"exec",
"fork",
"exit",
"dump",
"kill",
"alarm",
"sleep",
"wait",
"waitpid",
"setpgrp",
"setpriority",
"umask",
"lock",
"qx",
"readpipe",
"syscall",
"open",
"close",
"print",
"say",
"printf",
"sysread",
"syswrite",
"glob",
"readline",
"ioctl",
"fcntl",
"flock",
"select",
"dbmopen",
"dbmclose",
"binmode",
"opendir",
"closedir",
"readdir",
"rewinddir",
"seekdir",
"telldir",
"seek",
"sysseek",
"formline",
"write",
"pipe",
"socketpair",
"mkdir",
"rmdir",
"unlink",
"rename",
"chdir",
"chmod",
"chown",
"chroot",
"truncate",
"utime",
"symlink",
"link",
"eval",
"require",
"do",
"tie",
"untie",
"socket",
"connect",
"bind",
"listen",
"accept",
"send",
"recv",
"shutdown",
"setsockopt",
"msgget",
"msgsnd",
"msgrcv",
"msgctl",
"semget",
"semop",
"semctl",
"shmget",
"shmat",
"shmdt",
"shmctl",
];
pub const ASSIGNMENT_OPERATORS: &[&str] = &[
"=", "+=", "-=", "*=", "/=", "%=", "**=", ".=", "&=", "|=", "^=", "<<=", ">>=", "&&=", "||=",
"//=", "x=",
];
pub static DANGEROUS_OPS_RE: Lazy<Result<Regex, regex::Error>> = Lazy::new(|| {
let pattern = format!(r"\b(?:{})\b", DANGEROUS_OPERATIONS.join("|"));
Regex::new(&pattern)
});
pub static REGEX_MUTATION_RE: Lazy<Result<Regex, regex::Error>> = Lazy::new(|| {
Regex::new(r"\b(?:s|tr|y)[^\w\s]")
});
pub static ASSIGNMENT_OP_TOKENS_RE: Lazy<Result<Regex, regex::Error>> =
Lazy::new(|| Regex::new(r"([!~^&|+\-*/%=<>]+)"));
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_dangerous_ops_regex() {
use perl_tdd_support::must;
let re = must(DANGEROUS_OPS_RE.as_ref());
assert!(re.is_match("system('ls')"));
assert!(re.is_match("eval($code)"));
assert!(re.is_match("print 'hello'"));
}
#[test]
fn test_regex_mutation_regex() {
use perl_tdd_support::must;
let re = must(REGEX_MUTATION_RE.as_ref());
assert!(re.is_match("s/foo/bar/"));
assert!(re.is_match("tr/a-z/A-Z/"));
assert!(re.is_match("y/abc/xyz/"));
}
}