rapx/analysis/senryx/
matcher.rs

1use crate::{analysis::utils::fn_info::get_sp_json, rap_warn};
2use rustc_middle::mir::Const;
3use rustc_middle::mir::Operand;
4use std::collections::{HashMap, HashSet};
5
6#[derive(Debug, PartialEq, Eq)]
7pub struct Sp {
8    pub sp_name: String,
9    pub sank_set: HashSet<usize>,
10}
11
12impl std::hash::Hash for Sp {
13    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
14        self.sp_name.hash(state);
15    }
16}
17
18#[derive(Debug)]
19pub struct UnsafeApi {
20    pub api_name: String,
21    pub sps: Vec<HashSet<Sp>>,
22}
23
24pub fn parse_unsafe_api(func_name: &str) -> Option<UnsafeApi> {
25    let json_data = get_sp_json();
26    let function_info = json_data.get(func_name)?;
27
28    let params = function_info.as_object().map(|obj| {
29        obj.iter()
30            .filter_map(|(param_idx, props)| {
31                let param_num: usize = param_idx.parse().ok()?;
32                let sp_set = props.as_array().map(|arr| {
33                    arr.iter()
34                        .filter_map(|v| v.as_str())
35                        .filter_map(|s| {
36                            // split sp_name and sank set
37                            let (name, nums) = match s.split_once(':') {
38                                Some((n, ns)) => (n, ns.split(',')),
39                                None => (s, "".split(',')),
40                            };
41
42                            // parse sank set num
43                            let sank_set = nums.filter_map(|n| n.trim().parse().ok()).collect();
44
45                            Some(Sp {
46                                sp_name: name.to_string(),
47                                sank_set,
48                            })
49                        })
50                        .collect::<HashSet<_>>()
51                })?;
52                Some((param_num, sp_set))
53            })
54            .collect::<HashMap<_, _>>()
55    })?;
56
57    let mut sorted_params: Vec<_> = params.into_iter().collect();
58    sorted_params.sort_by_key(|(k, _)| *k);
59
60    Some(UnsafeApi {
61        api_name: func_name.to_string(),
62        sps: sorted_params.into_iter().map(|(_, v)| v).collect(),
63    })
64}
65
66// (is const, value)
67pub fn get_arg_place(arg: &Operand) -> (bool, usize) {
68    match arg {
69        Operand::Move(place) | Operand::Copy(place) => return (false, place.local.as_usize()),
70        Operand::Constant(constant) => {
71            let mut val = 0;
72            match constant.const_ {
73                Const::Ty(_ty, _const_value) => {
74                    rap_warn!("const ty found!");
75                }
76                Const::Unevaluated(_unevaluated, _ty) => {}
77                Const::Val(const_value, _ty) => {
78                    if let Some(scalar) = const_value.try_to_scalar_int() {
79                        val = scalar.to_uint(scalar.size()) as usize;
80                    }
81                }
82            }
83            return (true, val);
84        }
85    }
86}