From 8c94ad72e7479cb3d6ec36fddc7a70c56b1caf3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20B=C3=BChler?= <david.buhler@cea.fr> Date: Tue, 3 Mar 2020 18:05:43 +0100 Subject: [PATCH] [Kernel] Cabs2cil: inlines the C offsetof macro before the analyses. In order to avoid an undefined behavior in the C code generated for this macro (conversion from an absolute integer to a pointer). --- src/kernel_internals/parsing/cparser.mly | 9 +++++++- src/kernel_internals/typing/cabs2cil.ml | 22 +++++++++++++++++++ .../ast_printing/cil_printer.ml | 17 ++++++++++++++ src/kernel_services/ast_queries/cil.ml | 13 ----------- tests/misc/oracle/pragma-pack.0.res.oracle | 2 ++ tests/misc/oracle/pragma-pack.1.res.oracle | 2 ++ tests/misc/oracle/pragma-pack.2.res.oracle | 2 ++ .../misc/oracle/pragma_pack_zero.0.res.oracle | 2 ++ .../misc/oracle/pragma_pack_zero.1.res.oracle | 2 ++ tests/syntax/oracle/offsetof.res.oracle | 7 +++--- .../value/oracle/attribute-aligned.res.oracle | 2 ++ 11 files changed, 62 insertions(+), 18 deletions(-) diff --git a/src/kernel_internals/parsing/cparser.mly b/src/kernel_internals/parsing/cparser.mly index 666053a2830..fadfd5c5949 100644 --- a/src/kernel_internals/parsing/cparser.mly +++ b/src/kernel_internals/parsing/cparser.mly @@ -566,7 +566,14 @@ postfix_expression: /*(* 6.5.2 *)*/ { expr_loc = loc2; expr_node = TYPE_SIZEOF(b2,d2)}],[])) } | BUILTIN_OFFSETOF LPAREN type_name COMMA offsetof_member_designator RPAREN - { transformOffsetOf $3 $5 } + { + let loc_f = Cil_datatype.Location.of_lexing_loc (Parsing.rhs_start_pos 1, Parsing.rhs_end_pos 1) in + let arg = transformOffsetOf $3 $5 in + let builtin = { expr_loc = loc_f; + expr_node = VARIABLE "__builtin_offsetof" } + in + make_expr (CALL (builtin, [ arg ], [])) + } | postfix_expression DOT id_or_typename { make_expr (MEMBEROF ($1, $3))} | postfix_expression ARROW id_or_typename { make_expr (MEMBEROFPTR ($1, $3)) } | postfix_expression PLUS_PLUS { make_expr (UNARY (POSINCR, $1)) } diff --git a/src/kernel_internals/typing/cabs2cil.ml b/src/kernel_internals/typing/cabs2cil.ml index 42b88e95e86..39a07c2eb0e 100644 --- a/src/kernel_internals/typing/cabs2cil.ml +++ b/src/kernel_internals/typing/cabs2cil.ml @@ -7026,6 +7026,28 @@ and doExp local_env Kernel.warning ~current:true "Invalid call to builtin_constant_p") end + | "__builtin_offsetof" -> + begin + match !pargs with + | [{ enode = CastE (_, {enode = AddrOf (host, offset)}) } as e] -> + begin + piscall := false; + prestype := Cil.theMachine.Cil.typeOfSizeOf; + try + let typ = Cil.typeOfLhost host in + let start, _width = Cil.bitsOffset typ offset in + if start mod 8 <> 0 then + Kernel.error ~current:true "Using offset of bitfield"; + let kind = Cil.theMachine.kindOfSizeOf in + pres := Cil.kinteger ~loc:e.eloc kind (start / 8); + with SizeOfError _ -> + pres := e; + Kernel.warning ~once:true ~current:true + "Invalid call to builtin_offsetof"; + end + | _ -> + Kernel.abort ~current:true "Invalid call to builtin_offsetof"; + end | "__builtin_types_compatible_p" -> begin (* Constant-fold the argument and see if it is a constant *) diff --git a/src/kernel_services/ast_printing/cil_printer.ml b/src/kernel_services/ast_printing/cil_printer.ml index aef50199843..8bb7a5f20ef 100644 --- a/src/kernel_services/ast_printing/cil_printer.ml +++ b/src/kernel_services/ast_printing/cil_printer.ml @@ -1047,6 +1047,23 @@ class cil_printer () = object (self) "__builtin_types_compatible_p: cabs2cil should have added sizeof to \ the arguments." + | Call(dest, {enode = Lval (Var vi, NoOffset)}, [ arg ], (l, _)) + when vi.vname = "__builtin_offsetof" + && not state.print_cil_as_is -> + begin + match arg.enode with + | CastE (_, { enode = AddrOf (host, offset) }) -> + (* Print the destination *) + Extlib.may (fprintf fmt "%a = " self#lval) dest; + (* Now the call itself *) + fprintf fmt "%a(%a, %a)%s" + self#varname vi.vname + (self#typ None) (Cil.typeOfLhost host) + self#offset offset + instr_terminator + | _ -> Kernel.fatal ~source:l "__builtin_offsetof: invalid argument." + end + | Call(dest,e,args,_) -> pp_call dest e fmt args | Asm(attrs, tmpls, ext_asm, l) -> diff --git a/src/kernel_services/ast_queries/cil.ml b/src/kernel_services/ast_queries/cil.ml index 459570e1be6..91afc7abef7 100644 --- a/src/kernel_services/ast_queries/cil.ml +++ b/src/kernel_services/ast_queries/cil.ml @@ -4509,19 +4509,6 @@ and constFold (machdep: bool) (e: exp) : exp = | AlignOfE _ | AlignOf _ | SizeOfStr _ | SizeOfE _ | SizeOf _ -> e (* Depends on machdep. Do not evaluate in this case*) - (* Special case to handle the C macro 'offsetof' *) - | CastE(it, - { enode = AddrOf (Mem ({enode = CastE(TPtr(bt, _), z)}), off)}) - when machdep && isZero z -> begin - try - let start, _width = bitsOffset bt off in - if start mod 8 <> 0 then - Kernel.error ~current:true "Using offset of bitfield" ; - constFold machdep - (new_exp ~loc (CastE(it, (integer ~loc (start / 8))))) - with SizeOfError _ -> e - end - | CastE (t, e) -> begin Kernel.debug ~dkey "ConstFold CAST to %a@." !pp_typ_ref t ; let e = constFold machdep e in diff --git a/tests/misc/oracle/pragma-pack.0.res.oracle b/tests/misc/oracle/pragma-pack.0.res.oracle index 8688b345c3b..f3f41b911f7 100644 --- a/tests/misc/oracle/pragma-pack.0.res.oracle +++ b/tests/misc/oracle/pragma-pack.0.res.oracle @@ -87,6 +87,8 @@ adding aligned(1) attribute to field 'PACKOVERPOP.j' due to packing pragma [kernel:typing:pragma] tests/misc/pragma-pack.c:88: adding aligned(1) attribute to comp 'PACKOVERPOP' due to packing pragma +[kernel:typing:implicit-function-declaration] tests/misc/pragma-pack.c:104: Warning: + Calling undeclared function __builtin_offsetof. Old style K&R code? [kernel:typing:pragma] tests/misc/pragma-pack.c:133: packing pragma: restoring alignment to default (16) [kernel:typing:pragma] tests/misc/pragma-pack.c:135: diff --git a/tests/misc/oracle/pragma-pack.1.res.oracle b/tests/misc/oracle/pragma-pack.1.res.oracle index 559d8cfaacb..59c543748f2 100644 --- a/tests/misc/oracle/pragma-pack.1.res.oracle +++ b/tests/misc/oracle/pragma-pack.1.res.oracle @@ -1,6 +1,8 @@ [kernel] Parsing tests/misc/pragma-pack.c (with preprocessing) [kernel] tests/misc/pragma-pack.c:87: Warning: ignoring #pragma pack(pop) with empty stack +[kernel:typing:implicit-function-declaration] tests/misc/pragma-pack.c:104: Warning: + Calling undeclared function __builtin_offsetof. Old style K&R code? [eva] Analyzing a complete application starting at main [eva] Computing initial state [eva] Initial state computed diff --git a/tests/misc/oracle/pragma-pack.2.res.oracle b/tests/misc/oracle/pragma-pack.2.res.oracle index ae56a3d1f1a..c2534c76f82 100644 --- a/tests/misc/oracle/pragma-pack.2.res.oracle +++ b/tests/misc/oracle/pragma-pack.2.res.oracle @@ -1,6 +1,8 @@ [kernel] Parsing tests/misc/pragma-pack.c (with preprocessing) [kernel] tests/misc/pragma-pack.c:87: Warning: ignoring #pragma pack(pop) with empty stack +[kernel:typing:implicit-function-declaration] tests/misc/pragma-pack.c:104: Warning: + Calling undeclared function __builtin_offsetof. Old style K&R code? [eva] Analyzing a complete application starting at main [eva] Computing initial state [eva] Initial state computed diff --git a/tests/misc/oracle/pragma_pack_zero.0.res.oracle b/tests/misc/oracle/pragma_pack_zero.0.res.oracle index 6c491d9c591..0137611438a 100644 --- a/tests/misc/oracle/pragma_pack_zero.0.res.oracle +++ b/tests/misc/oracle/pragma_pack_zero.0.res.oracle @@ -1,6 +1,8 @@ [kernel] Parsing tests/misc/pragma_pack_zero.c (with preprocessing) [kernel] tests/misc/pragma_pack_zero.c:35: Warning: GCC accepts pack(0) but does not specify its behavior; considering it equivalent to pack() +[kernel:typing:implicit-function-declaration] tests/misc/pragma_pack_zero.c:47: Warning: + Calling undeclared function __builtin_offsetof. Old style K&R code? [eva] Analyzing a complete application starting at main [eva] Computing initial state [eva] Initial state computed diff --git a/tests/misc/oracle/pragma_pack_zero.1.res.oracle b/tests/misc/oracle/pragma_pack_zero.1.res.oracle index 69b3a971800..672ee382233 100644 --- a/tests/misc/oracle/pragma_pack_zero.1.res.oracle +++ b/tests/misc/oracle/pragma_pack_zero.1.res.oracle @@ -1,6 +1,8 @@ [kernel] Parsing tests/misc/pragma_pack_zero.c (with preprocessing) [kernel] tests/misc/pragma_pack_zero.c:35: Warning: ignoring invalid packing alignment (0) +[kernel:typing:implicit-function-declaration] tests/misc/pragma_pack_zero.c:47: Warning: + Calling undeclared function __builtin_offsetof. Old style K&R code? [eva] Analyzing a complete application starting at main [eva] Computing initial state [eva] Initial state computed diff --git a/tests/syntax/oracle/offsetof.res.oracle b/tests/syntax/oracle/offsetof.res.oracle index ac9886f97c2..0829a102008 100644 --- a/tests/syntax/oracle/offsetof.res.oracle +++ b/tests/syntax/oracle/offsetof.res.oracle @@ -1,13 +1,12 @@ [kernel] Parsing tests/syntax/offsetof.c (with preprocessing) +[kernel:typing:implicit-function-declaration] tests/syntax/offsetof.c:6: Warning: + Calling undeclared function __builtin_offsetof. Old style K&R code? /* Generated by Frama-C */ #include "stddef.h" -struct c { - char ca ; -}; void main(void) { size_t S; - S = (unsigned int)(& ((struct c *)0)->ca); + S = 0U; return; } diff --git a/tests/value/oracle/attribute-aligned.res.oracle b/tests/value/oracle/attribute-aligned.res.oracle index c451f494f10..160214c6a77 100644 --- a/tests/value/oracle/attribute-aligned.res.oracle +++ b/tests/value/oracle/attribute-aligned.res.oracle @@ -1,4 +1,6 @@ [kernel] Parsing tests/value/attribute-aligned.c (with preprocessing) +[kernel:typing:implicit-function-declaration] tests/value/attribute-aligned.c:17: Warning: + Calling undeclared function __builtin_offsetof. Old style K&R code? [eva] Analyzing a complete application starting at main [eva] Computing initial state [eva] Initial state computed -- GitLab