From 19093a2fa0c775950fb7cab6e74b40463d6b5ac0 Mon Sep 17 00:00:00 2001 From: Artem Pianykh Date: Tue, 3 Mar 2020 03:40:32 -0800 Subject: [PATCH] @update-submodule: facebook-clang-plugins Fix handling of non-literal `offsetof` expressions Summary: Update handling of `OffsetOfExpr` based on the new type definition from updated version of clang-plugin. Together with the change to clang-plugin, this essentially fixes hard crash while analysing C/C++ files with non-literal `offsetof` expression. Fixes GH issues [#1178](https://github.com/facebook/infer/issues/1178), [#1212](https://github.com/facebook/infer/issues/1212) Reviewed By: jvillard Differential Revision: D20159173 fbshipit-source-id: 65fc228a4 --- facebook-clang-plugins | 2 +- infer/src/IR/BUILTINS.ml | 2 + infer/src/IR/BuiltinDecl.ml | 2 + infer/src/biabduction/BuiltinDefn.ml | 3 + infer/src/clang/cTrans.ml | 18 ++++- infer/tests/codetoanalyze/c/errors/issues.exp | 1 + .../c/frontend/offsetof_expr/offsetof_expr.c | 11 ++++ .../offsetof_expr/offsetof_expr.c.dot | 65 +++++++++++++++++++ 8 files changed, 101 insertions(+), 3 deletions(-) diff --git a/facebook-clang-plugins b/facebook-clang-plugins index 0f3c72a62..bab391974 160000 --- a/facebook-clang-plugins +++ b/facebook-clang-plugins @@ -1 +1 @@ -Subproject commit 0f3c72a62f762a98a5c37b7f220b1561430e5b58 +Subproject commit bab39197465689e39b2462f052d2895fe13c1a60 diff --git a/infer/src/IR/BUILTINS.ml b/infer/src/IR/BUILTINS.ml index fa7dfe0ce..3b8b5d540 100644 --- a/infer/src/IR/BUILTINS.ml +++ b/infer/src/IR/BUILTINS.ml @@ -23,6 +23,8 @@ module type S = sig val __builtin_va_start : t + val __builtin_offsetof : t + val __cast : t (** [__cast(val,typ)] implements java's [typ(val)] *) diff --git a/infer/src/IR/BuiltinDecl.ml b/infer/src/IR/BuiltinDecl.ml index a83e5a512..7e82da1a7 100644 --- a/infer/src/IR/BuiltinDecl.ml +++ b/infer/src/IR/BuiltinDecl.ml @@ -42,6 +42,8 @@ let __builtin_va_end = create_procname "__builtin_va_end" let __builtin_va_start = create_procname "__builtin_va_start" +let __builtin_offsetof = create_procname "__builtin_offsetof" + let __cast = create_procname "__cast" let __cxx_typeid = create_procname "__cxx_typeid" diff --git a/infer/src/biabduction/BuiltinDefn.ml b/infer/src/biabduction/BuiltinDefn.ml index d6a859580..2f69067c6 100644 --- a/infer/src/biabduction/BuiltinDefn.ml +++ b/infer/src/biabduction/BuiltinDefn.ml @@ -853,6 +853,9 @@ let __builtin_va_end = Builtin.register BuiltinDecl.__builtin_va_end execute_ski let __builtin_va_start = Builtin.register BuiltinDecl.__builtin_va_start execute_skip +(* Ideally, offsetof needs to be properly handled here, instead of just skipped. *) +let __builtin_offsetof = Builtin.register BuiltinDecl.__builtin_offsetof execute_skip + (* [__cast(val,typ)] implements java's [typ(val)] *) let __cast = Builtin.register BuiltinDecl.__cast execute___cast diff --git a/infer/src/clang/cTrans.ml b/infer/src/clang/cTrans.ml index 110ea8c74..24248a6f1 100644 --- a/infer/src/clang/cTrans.ml +++ b/infer/src/clang/cTrans.ml @@ -3132,6 +3132,19 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s trans_state stmt_info Typ.void stmts + and offsetOf_trans trans_state expr_info offset_of_expr_info stmt_info = + match offset_of_expr_info.Clang_ast_t.ooe_literal with + | Some integer_literal_info -> + integerLiteral_trans trans_state expr_info integer_literal_info + | None -> + (* [offsetof] couldn't be evaluated as integer, return as a call to a builtin *) + let typ = CType_decl.get_type_from_expr_info expr_info trans_state.context.CContext.tenv in + (* We don't provide arguments to the builtin because due to translation we get gibberish. + Ex: offsetof(struct foo, bar[i]) gets only [i] as stmt_list and no mentions of foo or bar. *) + call_function_with_args (Procdesc.Node.Call "offsetof") BuiltinDecl.__builtin_offsetof + trans_state stmt_info typ [] + + and genericSelectionExprUnknown_trans trans_state stmt_info stmts = call_function_with_args Procdesc.Node.GenericSelectionExpr BuiltinDecl.__infer_generic_selection_expr trans_state stmt_info Typ.void stmts @@ -3500,9 +3513,10 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s | CXXStaticCastExpr (stmt_info, stmt_list, expr_info, cast_kind, _, _) | CXXFunctionalCastExpr (stmt_info, stmt_list, expr_info, cast_kind, _) -> cast_exprs_trans trans_state stmt_info stmt_list expr_info cast_kind - | IntegerLiteral (_, _, expr_info, integer_literal_info) - | OffsetOfExpr (_, _, expr_info, integer_literal_info) -> + | IntegerLiteral (_, _, expr_info, integer_literal_info) -> integerLiteral_trans trans_state expr_info integer_literal_info + | OffsetOfExpr (stmt_info, _, expr_info, offset_of_expr_info) -> + offsetOf_trans trans_state expr_info offset_of_expr_info stmt_info | StringLiteral (_, _, expr_info, str_list) -> stringLiteral_trans trans_state expr_info (String.concat ~sep:"" str_list) | GNUNullExpr (_, _, expr_info) -> diff --git a/infer/tests/codetoanalyze/c/errors/issues.exp b/infer/tests/codetoanalyze/c/errors/issues.exp index 581a9bcc6..27206e6d4 100644 --- a/infer/tests/codetoanalyze/c/errors/issues.exp +++ b/infer/tests/codetoanalyze/c/errors/issues.exp @@ -101,5 +101,6 @@ codetoanalyze/c/errors/resource_leaks/leak.c, socketNotClosed, 5, RESOURCE_LEAK, codetoanalyze/c/errors/sizeof/sizeof_706.c, sentinel_bad, 0, DIVIDE_BY_ZERO, no_bucket codetoanalyze/c/frontend/enumeration/other_enum.c, other_enum_test, 4, DIVIDE_BY_ZERO, no_bucket codetoanalyze/c/frontend/offsetof_expr/offsetof_expr.c, test_offsetof_expr, 3, DIVIDE_BY_ZERO, no_bucket +codetoanalyze/c/frontend/offsetof_expr/offsetof_expr.c, test_offsetof_expr_nonlit, 6, DIVIDE_BY_ZERO, no_bucket codetoanalyze/c/frontend/vaarg_expr/vaarg_expr.c, vaarg_foo, 6, DIVIDE_BY_ZERO, no_bucket codetoanalyze/c/frontend/vaarg_expr/vaarg_expr.c, vaarg_foo, 8, DIVIDE_BY_ZERO, no_bucket diff --git a/infer/tests/codetoanalyze/c/frontend/offsetof_expr/offsetof_expr.c b/infer/tests/codetoanalyze/c/frontend/offsetof_expr/offsetof_expr.c index 3e959f355..723a127b6 100644 --- a/infer/tests/codetoanalyze/c/frontend/offsetof_expr/offsetof_expr.c +++ b/infer/tests/codetoanalyze/c/frontend/offsetof_expr/offsetof_expr.c @@ -20,3 +20,14 @@ int test_offsetof_expr() { } return 42; } + +int test_offsetof_expr_nonlit() { + size_t sum = 0; + for (int i = 0; i < 2; i++) { + sum += offsetof(struct address, v1[i]); + } + if (sum == 1) { + return 1 / 0; + } + return 42; +} diff --git a/infer/tests/codetoanalyze/c/frontend/offsetof_expr/offsetof_expr.c.dot b/infer/tests/codetoanalyze/c/frontend/offsetof_expr/offsetof_expr.c.dot index 2d21d2543..6742afae8 100644 --- a/infer/tests/codetoanalyze/c/frontend/offsetof_expr/offsetof_expr.c.dot +++ b/infer/tests/codetoanalyze/c/frontend/offsetof_expr/offsetof_expr.c.dot @@ -36,4 +36,69 @@ digraph cfg { "test_offsetof_expr.8f3e634fd0f68dff5e4bfedc8f65a55f_9" -> "test_offsetof_expr.8f3e634fd0f68dff5e4bfedc8f65a55f_5" ; +"test_offsetof_expr_nonlit.84cbb7cce74551fd659dd824f9839319_1" [label="1: Start test_offsetof_expr_nonlit\nFormals: \nLocals: i:int sum:unsigned long \n " color=yellow style=filled] + + + "test_offsetof_expr_nonlit.84cbb7cce74551fd659dd824f9839319_1" -> "test_offsetof_expr_nonlit.84cbb7cce74551fd659dd824f9839319_16" ; +"test_offsetof_expr_nonlit.84cbb7cce74551fd659dd824f9839319_2" [label="2: Exit test_offsetof_expr_nonlit \n " color=yellow style=filled] + + +"test_offsetof_expr_nonlit.84cbb7cce74551fd659dd824f9839319_3" [label="3: Return Stmt \n *&return:int=42 [line 32, column 3]\n " shape="box"] + + + "test_offsetof_expr_nonlit.84cbb7cce74551fd659dd824f9839319_3" -> "test_offsetof_expr_nonlit.84cbb7cce74551fd659dd824f9839319_2" ; +"test_offsetof_expr_nonlit.84cbb7cce74551fd659dd824f9839319_4" [label="4: + \n " ] + + + "test_offsetof_expr_nonlit.84cbb7cce74551fd659dd824f9839319_4" -> "test_offsetof_expr_nonlit.84cbb7cce74551fd659dd824f9839319_3" ; +"test_offsetof_expr_nonlit.84cbb7cce74551fd659dd824f9839319_5" [label="5: BinaryOperatorStmt: EQ \n n$0=*&sum:unsigned long [line 29, column 7]\n " shape="box"] + + + "test_offsetof_expr_nonlit.84cbb7cce74551fd659dd824f9839319_5" -> "test_offsetof_expr_nonlit.84cbb7cce74551fd659dd824f9839319_6" ; + "test_offsetof_expr_nonlit.84cbb7cce74551fd659dd824f9839319_5" -> "test_offsetof_expr_nonlit.84cbb7cce74551fd659dd824f9839319_7" ; +"test_offsetof_expr_nonlit.84cbb7cce74551fd659dd824f9839319_6" [label="6: Prune (true branch, if) \n PRUNE((n$0 == (unsigned long)1), true); [line 29, column 7]\n " shape="invhouse"] + + + "test_offsetof_expr_nonlit.84cbb7cce74551fd659dd824f9839319_6" -> "test_offsetof_expr_nonlit.84cbb7cce74551fd659dd824f9839319_8" ; +"test_offsetof_expr_nonlit.84cbb7cce74551fd659dd824f9839319_7" [label="7: Prune (false branch, if) \n PRUNE(!(n$0 == (unsigned long)1), false); [line 29, column 7]\n " shape="invhouse"] + + + "test_offsetof_expr_nonlit.84cbb7cce74551fd659dd824f9839319_7" -> "test_offsetof_expr_nonlit.84cbb7cce74551fd659dd824f9839319_4" ; +"test_offsetof_expr_nonlit.84cbb7cce74551fd659dd824f9839319_8" [label="8: Return Stmt \n *&return:int=(1 / 0) [line 30, column 5]\n " shape="box"] + + + "test_offsetof_expr_nonlit.84cbb7cce74551fd659dd824f9839319_8" -> "test_offsetof_expr_nonlit.84cbb7cce74551fd659dd824f9839319_2" ; +"test_offsetof_expr_nonlit.84cbb7cce74551fd659dd824f9839319_9" [label="9: + \n " ] + + + "test_offsetof_expr_nonlit.84cbb7cce74551fd659dd824f9839319_9" -> "test_offsetof_expr_nonlit.84cbb7cce74551fd659dd824f9839319_12" ; +"test_offsetof_expr_nonlit.84cbb7cce74551fd659dd824f9839319_10" [label="10: DeclStmt \n VARIABLE_DECLARED(i:int); [line 26, column 8]\n *&i:int=0 [line 26, column 8]\n " shape="box"] + + + "test_offsetof_expr_nonlit.84cbb7cce74551fd659dd824f9839319_10" -> "test_offsetof_expr_nonlit.84cbb7cce74551fd659dd824f9839319_9" ; +"test_offsetof_expr_nonlit.84cbb7cce74551fd659dd824f9839319_11" [label="11: UnaryOperator \n n$3=*&i:int [line 26, column 26]\n *&i:int=(n$3 + 1) [line 26, column 26]\n " shape="box"] + + + "test_offsetof_expr_nonlit.84cbb7cce74551fd659dd824f9839319_11" -> "test_offsetof_expr_nonlit.84cbb7cce74551fd659dd824f9839319_9" ; +"test_offsetof_expr_nonlit.84cbb7cce74551fd659dd824f9839319_12" [label="12: BinaryOperatorStmt: LT \n n$4=*&i:int [line 26, column 19]\n " shape="box"] + + + "test_offsetof_expr_nonlit.84cbb7cce74551fd659dd824f9839319_12" -> "test_offsetof_expr_nonlit.84cbb7cce74551fd659dd824f9839319_13" ; + "test_offsetof_expr_nonlit.84cbb7cce74551fd659dd824f9839319_12" -> "test_offsetof_expr_nonlit.84cbb7cce74551fd659dd824f9839319_14" ; +"test_offsetof_expr_nonlit.84cbb7cce74551fd659dd824f9839319_13" [label="13: Prune (true branch, for loop) \n PRUNE((n$4 < 2), true); [line 26, column 19]\n " shape="invhouse"] + + + "test_offsetof_expr_nonlit.84cbb7cce74551fd659dd824f9839319_13" -> "test_offsetof_expr_nonlit.84cbb7cce74551fd659dd824f9839319_15" ; +"test_offsetof_expr_nonlit.84cbb7cce74551fd659dd824f9839319_14" [label="14: Prune (false branch, for loop) \n PRUNE(!(n$4 < 2), false); [line 26, column 19]\n " shape="invhouse"] + + + "test_offsetof_expr_nonlit.84cbb7cce74551fd659dd824f9839319_14" -> "test_offsetof_expr_nonlit.84cbb7cce74551fd659dd824f9839319_5" ; +"test_offsetof_expr_nonlit.84cbb7cce74551fd659dd824f9839319_15" [label="15: BinaryOperatorStmt: AddAssign \n n$5=_fun___builtin_offsetof() [line 27, column 12]\n n$6=*&sum:unsigned long [line 27, column 5]\n *&sum:unsigned long=(n$6 + n$5) [line 27, column 5]\n " shape="box"] + + + "test_offsetof_expr_nonlit.84cbb7cce74551fd659dd824f9839319_15" -> "test_offsetof_expr_nonlit.84cbb7cce74551fd659dd824f9839319_11" ; +"test_offsetof_expr_nonlit.84cbb7cce74551fd659dd824f9839319_16" [label="16: DeclStmt \n VARIABLE_DECLARED(sum:unsigned long); [line 25, column 3]\n *&sum:unsigned long=(unsigned long)0 [line 25, column 3]\n " shape="box"] + + + "test_offsetof_expr_nonlit.84cbb7cce74551fd659dd824f9839319_16" -> "test_offsetof_expr_nonlit.84cbb7cce74551fd659dd824f9839319_10" ; }