Skip to content

Commit 776975e

Browse files
committed
Enhance safety analysis by integrating map declarations into bounds checking. Update check_array_bounds and analyze_statement_bounds functions to utilize known map information for improved safety checks during compilation.
1 parent 087b37f commit 776975e

2 files changed

Lines changed: 57 additions & 26 deletions

File tree

src/main.ml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -537,12 +537,19 @@ let compile_source input_file output_dir _verbose generate_makefile btf_vmlinux_
537537
| _ -> acc
538538
) [] compilation_ast in
539539

540+
(* Extract map declarations from the AST for safety analysis *)
541+
let all_maps = List.fold_left (fun acc decl ->
542+
match decl with
543+
| Ast.MapDecl map_decl -> map_decl :: acc
544+
| _ -> acc
545+
) [] compilation_ast in
546+
540547
(* Create a program structure for safety analysis *)
541548
let safety_program = {
542549
Ast.prog_name = base_name;
543550
prog_type = Xdp; (* Default - not used by safety checker *)
544551
prog_functions = all_functions;
545-
prog_maps = [];
552+
prog_maps = all_maps;
546553
prog_structs = [];
547554
prog_pos = Ast.make_position 1 1 input_file;
548555
} in

src/safety_checker.ml

Lines changed: 49 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -145,23 +145,45 @@ let analyze_function_stack_usage func =
145145
(** Bounds checking analysis *)
146146

147147
(** Check array access bounds *)
148-
let check_array_bounds expr =
148+
let check_array_bounds ?(known_maps : Ast.map_declaration list = []) expr =
149149
let rec check_expr e errors =
150150
match e.expr_desc with
151151
| ArrayAccess (arr_expr, idx_expr) ->
152152
(match arr_expr.expr_desc, idx_expr.expr_desc with
153153
| Identifier arr_name, Literal (IntLit (idx, _)) ->
154-
(* Check if we can determine array size from type *)
155-
(match arr_expr.expr_type with
156-
| Some (Ast.Array (_, size)) ->
157-
if idx >= size || idx < 0 then
158-
ArrayOutOfBounds (arr_name, idx, size) :: errors
159-
else
154+
(* First check if this is a known map *)
155+
if List.exists (fun (map_decl : Ast.map_declaration) -> map_decl.name = arr_name) known_maps then
156+
(* Map access - inherently safe, skip bounds checking *)
157+
errors
158+
else
159+
(* Check if we can determine array size from type *)
160+
(match arr_expr.expr_type with
161+
| Some (Ast.Array (_, size)) ->
162+
if idx >= size || idx < 0 then
163+
ArrayOutOfBounds (arr_name, idx, size) :: errors
164+
else
165+
errors
166+
| Some (Ast.Map (_, _, _)) ->
167+
(* Map access - inherently safe, skip bounds checking *)
160168
errors
161-
| _ -> UnknownBounds arr_name :: errors)
169+
| _ -> UnknownBounds arr_name :: errors)
162170
| Identifier arr_name, _ ->
163-
(* Runtime bounds check needed *)
164-
UnknownBounds arr_name :: errors
171+
(* First check if this is a known map *)
172+
if List.exists (fun (map_decl : Ast.map_declaration) -> map_decl.name = arr_name) known_maps then
173+
(* Map access with dynamic key - inherently safe *)
174+
errors
175+
else
176+
(* Check if this is a map access - maps are safe *)
177+
(match arr_expr.expr_type with
178+
| Some (Ast.Map (_, _, _)) ->
179+
(* Map access with dynamic key - inherently safe *)
180+
errors
181+
| Some (Ast.Array (_, _)) ->
182+
(* Array access with dynamic index - runtime bounds check needed *)
183+
UnknownBounds arr_name :: errors
184+
| _ ->
185+
(* Unknown type - could be array, so flag for safety *)
186+
UnknownBounds arr_name :: errors)
165187
| FieldAccess (_, "data"), Literal (IntLit (idx, _)) when idx >= 1500 ->
166188
(* Unsafe packet access - large index into packet data *)
167189
PointerOutOfBounds ("packet_data") :: errors
@@ -198,42 +220,42 @@ let check_array_declaration name typ =
198220
| _ -> []
199221

200222
(** Analyze bounds checking in statements *)
201-
let analyze_statement_bounds stmt =
223+
let analyze_statement_bounds ?(known_maps : Ast.map_declaration list = []) stmt =
202224
let errors = ref [] in
203225

204226
let rec check_stmt s =
205227
match s.stmt_desc with
206228
| Declaration (name, Some typ, expr_opt) ->
207229
errors := check_array_declaration name typ @ !errors;
208230
(match expr_opt with
209-
| Some expr -> errors := check_array_bounds expr @ !errors
231+
| Some expr -> errors := check_array_bounds ~known_maps expr @ !errors
210232
| None -> ())
211233
| ExprStmt expr | Assignment (_, expr) ->
212-
errors := check_array_bounds expr @ !errors
234+
errors := check_array_bounds ~known_maps expr @ !errors
213235
| CompoundAssignment (_, _, expr) ->
214-
errors := check_array_bounds expr @ !errors
236+
errors := check_array_bounds ~known_maps expr @ !errors
215237
| CompoundIndexAssignment (map_expr, key_expr, _, value_expr) ->
216-
errors := check_array_bounds map_expr @ !errors;
217-
errors := check_array_bounds key_expr @ !errors;
218-
errors := check_array_bounds value_expr @ !errors
238+
errors := check_array_bounds ~known_maps map_expr @ !errors;
239+
errors := check_array_bounds ~known_maps key_expr @ !errors;
240+
errors := check_array_bounds ~known_maps value_expr @ !errors
219241
| FieldAssignment (obj_expr, _, value_expr) ->
220-
errors := check_array_bounds obj_expr @ !errors;
221-
errors := check_array_bounds value_expr @ !errors
242+
errors := check_array_bounds ~known_maps obj_expr @ !errors;
243+
errors := check_array_bounds ~known_maps value_expr @ !errors
222244
| If (cond, then_stmts, else_opt) ->
223-
errors := check_array_bounds cond @ !errors;
245+
errors := check_array_bounds ~known_maps cond @ !errors;
224246
List.iter check_stmt then_stmts;
225247
(match else_opt with
226248
| None -> ()
227249
| Some else_stmts -> List.iter check_stmt else_stmts)
228250
| For (_, start, end_, body) ->
229-
errors := check_array_bounds start @ !errors;
230-
errors := check_array_bounds end_ @ !errors;
251+
errors := check_array_bounds ~known_maps start @ !errors;
252+
errors := check_array_bounds ~known_maps end_ @ !errors;
231253
List.iter check_stmt body
232254
| While (cond, body) ->
233-
errors := check_array_bounds cond @ !errors;
255+
errors := check_array_bounds ~known_maps cond @ !errors;
234256
List.iter check_stmt body
235257
| Return (Some expr) ->
236-
errors := check_array_bounds expr @ !errors
258+
errors := check_array_bounds ~known_maps expr @ !errors
237259
| _ -> ()
238260
in
239261

@@ -364,10 +386,12 @@ let analyze_stack_usage program =
364386
(** Perform bounds checking analysis *)
365387
let analyze_bounds_safety program =
366388
let all_errors = ref [] in
389+
(* Collect map declarations for bounds checking context *)
390+
let known_maps = program.prog_maps in
367391

368392
List.iter (fun func ->
369393
List.iter (fun stmt ->
370-
let errors = analyze_statement_bounds stmt in
394+
let errors = analyze_statement_bounds ~known_maps stmt in
371395
all_errors := errors @ !all_errors
372396
) func.func_body
373397
) program.prog_functions;

0 commit comments

Comments
 (0)