use crate::analysis::utils::fn_info::get_sp_tags_json;
use rustc_middle::mir::Const;
use rustc_middle::mir::Operand;
use std::collections::{HashMap, HashSet};
#[derive(Debug, PartialEq, Eq)]
pub struct Sp {
pub sp_name: String,
pub sank_set: HashSet<usize>,
}
impl std::hash::Hash for Sp {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.sp_name.hash(state);
}
}
#[derive(Debug)]
pub struct UnsafeApi {
pub api_name: String,
pub sps: Vec<HashSet<Sp>>,
}
pub fn parse_unsafe_api(func_name: &str) -> Option<UnsafeApi> {
let json_data = get_sp_tags_json();
let function_info = json_data.get(func_name)?;
let params = function_info.as_object().map(|obj| {
obj.iter()
.filter_map(|(param_idx, props)| {
let param_num: usize = param_idx.parse().ok()?;
let sp_set = props.as_array().map(|arr| {
arr.iter()
.filter_map(|v| v.as_str())
.filter_map(|s| {
let (name, nums) = match s.split_once(':') {
Some((n, ns)) => (n, ns.split(',')),
None => (s, "".split(',')),
};
let sank_set = nums.filter_map(|n| n.trim().parse().ok()).collect();
Some(Sp {
sp_name: name.to_string(),
sank_set,
})
})
.collect::<HashSet<_>>()
})?;
Some((param_num, sp_set))
})
.collect::<HashMap<_, _>>()
})?;
let mut sorted_params: Vec<_> = params.into_iter().collect();
sorted_params.sort_by_key(|(k, _)| *k);
Some(UnsafeApi {
api_name: func_name.to_string(),
sps: sorted_params.into_iter().map(|(_, v)| v).collect(),
})
}
pub fn get_arg_place(arg: &Operand) -> (bool, usize) {
match arg {
Operand::Move(place) | Operand::Copy(place) => return (false, place.local.as_usize()),
Operand::Constant(constant) => {
let mut val = 0;
match constant.const_ {
Const::Ty(_ty, _const_value) => {
rap_warn!("const ty found!");
}
Const::Unevaluated(_unevaluated, _ty) => {}
Const::Val(const_value, _ty) => {
if let Some(scalar) = const_value.try_to_scalar_int() {
val = scalar.to_uint(scalar.size()) as usize;
}
}
}
return (true, val);
}
}
}