From f163e72721a0259beb90ce41fbba036d558b5727 Mon Sep 17 00:00:00 2001 From: Andre Maroneze <andre.maroneze@cea.fr> Date: Tue, 4 May 2021 17:39:06 +0200 Subject: [PATCH] [Kernel] fix several crashes related to very large integers --- src/kernel_internals/typing/cabs2cil.ml | 55 ++++++++++++++++++++++--- src/kernel_services/ast_queries/cil.ml | 19 ++++++--- src/kernel_services/ast_queries/cil.mli | 5 ++- 3 files changed, 66 insertions(+), 13 deletions(-) diff --git a/src/kernel_internals/typing/cabs2cil.ml b/src/kernel_internals/typing/cabs2cil.ml index 0b61835de9d..5f17a26c2b7 100644 --- a/src/kernel_internals/typing/cabs2cil.ml +++ b/src/kernel_internals/typing/cabs2cil.ml @@ -3348,7 +3348,14 @@ let rec setOneInit this o preinit = let idx, (* Index in the current comp *) restoff (* Rest offset *) = match o with - | Index({enode = Const(CInt64(i,_,_))}, off) -> Integer.to_int i, off + | Index({enode = Const(CInt64(i,_,_))}, off) -> + begin + match Integer.to_int_opt i with + | Some i' -> i', off + | None -> Kernel.fatal ~current:true + "integer too large: %a" + (Integer.pretty ~hexa:true) i + end | Field (f, off) -> (* Find the index of the field *) let rec loop (idx: int) = function @@ -3428,7 +3435,14 @@ let rec collectInitializer | Some len -> begin match constFoldToInt len with | Some ni when Integer.ge ni Integer.zero -> - (Integer.to_int ni), false + begin + match Integer.to_int_opt ni with + | Some ni' -> ni', false + | None -> + Kernel.fatal ~current:true + "Array length %a overflows int, cannot use initializer." + Cil_printer.pp_exp len + end | _ -> Kernel.fatal ~current:true "Array length %a is not a compile-time constant: \ @@ -5701,7 +5715,14 @@ and isIntegerConstant ghost (aexp) : int option = match doExp (ghost_local_env ghost) CMayConst aexp (AExp None) with | (_, c, e, _) when isEmpty c -> begin match Cil.constFoldToInt e with - | Some n -> (try Some (Integer.to_int n) with Z.Overflow -> None) + | Some n -> + begin + match Integer.to_int_opt n with + | Some n' -> Some n' + | None -> Kernel.fatal ~current:true + "integer constant too large in expression: %a" + Cil_printer.pp_exp e + end | _ -> None end | _ -> None @@ -8467,7 +8488,13 @@ and doInit local_env asconst add_implicit_ensures preinit so acc initl = let doidx = add_reads ~ghost idxe'.eloc r doidx in match constFoldToInt idxe', isNotEmpty doidx with - | Some x, false -> Integer.to_int x, doidx + | Some x, false -> + begin + match Integer.to_int_opt x with + | Some x' -> x', doidx + | None -> abort_context + "INDEX initialization designator overflows" + end | _ -> abort_context "INDEX initialization designator is not a constant" @@ -8505,7 +8532,14 @@ and doInit local_env asconst add_implicit_ensures preinit so acc initl = Kernel.fatal ~current:true "Range designators are not constants"; let first, last = match constFoldToInt idxs', constFoldToInt idxe' with - | Some s, Some e -> Integer.to_int s, Integer.to_int e + | Some s, Some e -> + begin + match Integer.to_int_opt s, Integer.to_int_opt e with + | Some s', Some e' -> s', e' + | _, _ -> + Kernel.fatal ~current:true + "INDEX_RANGE initialization designator overflows" + end | _ -> Kernel.fatal ~current:true "INDEX_RANGE initialization designator is not a constant" @@ -10062,7 +10096,16 @@ and doStatement local_env (s : Cabs.statement) : chunk = "Case statement with a non-constant"; let il, ih = match constFoldToInt el', constFoldToInt eh' with - | Some il, Some ih -> Integer.to_int il, Integer.to_int ih + | Some il, Some ih -> + begin + match Integer.to_int_opt il, Integer.to_int_opt ih with + | Some il', Some ih' -> il', ih' + | _, _ -> + Kernel.fatal ~current:true + "constant(s) in case range too large: %a ... %a" + (Integer.pretty ~hexa:false) il + (Integer.pretty ~hexa:false) ih + end | _ -> Kernel.fatal ~current:true "Cannot understand the constants in case range" diff --git a/src/kernel_services/ast_queries/cil.ml b/src/kernel_services/ast_queries/cil.ml index b7b405e03e2..25de3a7c644 100644 --- a/src/kernel_services/ast_queries/cil.ml +++ b/src/kernel_services/ast_queries/cil.ml @@ -4102,7 +4102,13 @@ and alignOfField (fi: fieldinfo) = and intOfAttrparam (a:attrparam) : int option = let rec doit a : int = match a with - | AInt(n) -> Integer.to_int n + | AInt(n) -> + begin + match Integer.to_int_opt n with + | Some n' -> n' + | None -> + raise (SizeOfError ("Overflow in integer attribute.", voidType)) + end | ABinOp(PlusA, a1, a2) -> doit a1 + doit a2 | ABinOp(MinusA, a1, a2) -> doit a1 - doit a2 | ABinOp(Mult, a1, a2) -> doit a1 * doit a2 @@ -4410,9 +4416,9 @@ and bitsSizeOf t = Const(CInt64(l,_,_)) -> let sz = Integer.mul (Integer.of_int (bitsSizeOf bt)) l in let sz' = - try - Integer.to_int sz - with Z.Overflow -> + match Integer.to_int_opt sz with + | Some i -> i + | None -> raise (SizeOfError ("Array is so long that its size can't be " @@ -5996,7 +6002,10 @@ let lenOfArray64 eo = ni | _ -> raise LenOfArray end -let lenOfArray eo = Integer.to_int (lenOfArray64 eo) +let lenOfArray eo = + match Integer.to_int_opt (lenOfArray64 eo) with + | None -> raise LenOfArray + | Some l -> l (*** Make an initializer for zeroing a data type ***) let rec makeZeroInit ~loc (t: typ) : init = diff --git a/src/kernel_services/ast_queries/cil.mli b/src/kernel_services/ast_queries/cil.mli index 094edf99428..7e24ee1a47a 100644 --- a/src/kernel_services/ast_queries/cil.mli +++ b/src/kernel_services/ast_queries/cil.mli @@ -606,8 +606,9 @@ val isArrayType: typ -> bool (** True if the argument is a struct of union type *) val isStructOrUnionType: typ -> bool -(** Raised when {!Cil.lenOfArray} fails either because the length is [None] - * or because it is a non-constant expression *) +(** Raised when {!Cil.lenOfArray} fails either because the length is [None], + * because it is a non-constant expression, or because it overflows an int. +*) exception LenOfArray (** Call to compute the array length as present in the array type, to an -- GitLab