1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
open Core_kernel
open Cwe_checker_core.Main
exception InvalidPathException of string
exception NoOutputFileException of string
exception NoModulesException of string
exception NoConfigException of string
exception NoBinaryPathException of string
exception NoApiFileException of string
let rec get_difference (set_a : 'a list) (set_b: 'a list) : 'a list =
match set_a with
| [] -> []
| element_of_a::remain_a ->
match (Stdlib.List.mem element_of_a set_b) with
| true -> get_difference remain_a set_b
| false -> List.append (get_difference remain_a set_b) [element_of_a]
let get_user_input ?(position=1) (() : unit) : string list =
Array.to_list (Array.sub Sys.argv ~pos:position ~len:(Array.length Sys.argv - position))
let rec find_prefix (input : string list) (prefix : string) : string option =
match input with
| [] -> None
| head::tail ->
match (String.is_prefix head ~prefix:prefix) with
| true -> Some head
| false -> find_prefix tail prefix
let rec replace_element (set : string list) (element : string) (replacement : string) : string list =
match set with
| [] -> []
| head::tail ->
match String.is_prefix ~prefix:element head with
| true -> replacement::tail
| false -> head::replace_element tail element replacement
let rec remove_element (flags : string list) (element: string): string list =
match flags with
| [] -> []
| head::tail ->
match String.is_prefix ~prefix:element head with
| true -> tail
| false -> head::remove_element tail element
let raise_no_content_exception (param : string) : unit =
match param with
| "-config" -> raise (NoConfigException "No config file provided. If -config flag set please provide a config file.")
| "-out" -> raise (NoOutputFileException "No output file provided. If -out flag is set please provide an out file.")
| "-partial" -> raise (NoModulesException "No modules provided. If -partial flag is set, please provide the corresponding modules.")
| "-api" -> raise (NoApiFileException "No header file provided. If -api flag is set, please provide a valid header file.")
| _ -> failwith "Invalid param."
let check_content (input : string) (param : string) : unit =
match Stdlib.List.nth_opt (String.split input ~on:'=') 1 with
| None | Some "" -> raise_no_content_exception param
| Some content -> begin
match param with
| "-partial" -> check_valid_module_list (String.split_on_chars content ~on:[','])
| "-config" | "-api" -> if (Sys.file_exists content) then () else raise (InvalidPathException "Path to config file not valid")
| _ -> ()
end
let check_params (params : string list) (input : string list) : unit =
List.iter params ~f:(fun param ->
match find_prefix input param with
| None -> begin
match (String.equal param "-config") with
| true -> Cwe_checker_core.Log_utils.info "Using standard configuration..."
| false -> ()
end
| Some p -> check_content p param
)
let validate_user_input (input : string list) : unit =
let valid_flags = List.map ~f:(fun x -> "-" ^ fst x) Cwe_checker_core.Main.cmdline_flags in
match get_difference input valid_flags with
| [] -> ()
| invalid -> failwith ("Invalid flags: " ^ String.concat ~sep:", " invalid)
let check_for_help (flags: string list) : bool =
if (Stdlib.List.mem "-h" flags)|| (Stdlib.List.mem "-help" flags) || (Stdlib.List.mem "--help" flags) then (
print_help_message (); true
) else false
let check_for_version (flags:string list) : bool =
if (Stdlib.List.mem "-v" flags) || (Stdlib.List.mem "-version" flags) || (Stdlib.List.mem "--version" flags) then (
print_version (); true
) else false
let check_for_module_versions (flags: string list) : bool =
if Stdlib.List.mem "-module-versions" flags then
let () = Cwe_checker_core.Main.print_module_versions () in
true
else
false
let check_for_no_logging (flags: string list) : unit =
if Stdlib.List.mem "-no-logging" flags then
Cwe_checker_core.Log_utils.turn_off_logging ()
let process_flags (flags : string list) : string list =
match flags with
| [] -> []
| _ -> validate_user_input flags; flags
let rec check_for_binary_path (args : string list) : string =
match args with
| [] -> raise (NoBinaryPathException ("No binary path was provided. If you need help, please call the cwe_checker with the --help or -h flag"))
| head::tail ->(
try
match Sys.is_directory head with
| false -> head
| true -> raise (NoBinaryPathException ("No binary path was provided. If you need help, please call the cwe_checker with the --help or -h flag"))
with
| _ -> check_for_binary_path tail
)
let process_input (() : unit) : string * string list =
match get_user_input () with
| [] -> raise (NoBinaryPathException ("No binary path was provided. If you need help, please call the cwe_checker with the --help or -h flag"))
| input -> (
if check_for_help input then exit 0;
if check_for_version input then exit 0;
if check_for_module_versions input then exit 0;
check_for_no_logging input;
let binary_path = check_for_binary_path input in
let split_flags = List.partition_tf input ~f:(fun x -> (String.is_prefix x ~prefix:"-config") || (String.is_prefix x ~prefix:"-out")
|| (String.is_prefix x ~prefix:"-partial") || (String.is_prefix x ~prefix:"-api")) in
let flags = remove_element (snd split_flags) binary_path in
let input_params = fst split_flags in
let params = List.map cmdline_params ~f:(fun param -> match param with | (p, _) -> "-" ^ p) in
check_params params input_params;
(binary_path, input_params @ process_flags flags)
)
let setup_command (bin_path : string) (args : string list) : string =
let bare_command = "bap " ^ bin_path ^ " --pass=cwe-checker " in
let command_args = String.concat ~sep:" " (List.map args ~f:(fun arg ->
match (String.is_prefix arg ~prefix:"-api") with
| true -> "--api-path=" ^ (Stdlib.List.nth (String.split arg ~on:'=') 1)
| false -> "--cwe-checker" ^ arg)) in
bare_command ^ command_args
let main () : int =
match Array.length Sys.argv with
| 1 -> print_help_message (); 0
| _ ->
let (bin_path, args) = process_input () in
match args with
| [] -> Sys.command ("bap " ^ bin_path ^ " --pass=cwe-checker ")
| _ -> Sys.command (setup_command bin_path args)
let _ = exit (main ())