@@ -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 *)
365387let 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