From 8fc44564d35fb6ba10d54fab2ba8b5cbfed2f2e3 Mon Sep 17 00:00:00 2001 From: Virgile Prevosto <virgile.prevosto@m4x.org> Date: Thu, 27 Aug 2020 16:53:30 +0200 Subject: [PATCH] [rte] refined condition for generating pointer value alarms presence of an offset does not mean that we could write a spurious value through a union. --- src/plugins/rte/rte.ml | 7 ++++++- tests/rte/invalid_fptr.i | 15 +++++++++++++++ tests/rte/oracle/invalid_fptr.res.oracle | 20 ++++++++++++++++++++ 3 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 tests/rte/invalid_fptr.i create mode 100644 tests/rte/oracle/invalid_fptr.res.oracle diff --git a/src/plugins/rte/rte.ml b/src/plugins/rte/rte.ml index 16845eed8d5..bc526753f36 100644 --- a/src/plugins/rte/rte.ml +++ b/src/plugins/rte/rte.ml @@ -451,13 +451,18 @@ let finite_float_assertion ~remove_trivial:_ ~on_alarm (fkind, exp) = let pointer_call ~remove_trivial:_ ~on_alarm (e, args) = on_alarm ~invalid:false (Alarms.Function_pointer (e, Some args)) +let rec is_safe_offset = function + | NoOffset -> true + | Field(fi,o) -> fi.fcomp.cstruct && not fi.faddrof && is_safe_offset o + | Index(_,o) -> is_safe_offset o + let is_safe_pointer_value = function | Lval (Var vi, offset) -> (* Reading a pointer variable must emit an alarm if an invalid pointer value could have been written without previous alarm, through: - an union type, in which case [offset] is not NoOffset; - an untyped write, in which case the address of [vi] is taken. *) - not vi.vaddrof && offset = NoOffset + not vi.vaddrof && is_safe_offset offset | AddrOf (_, NoOffset) | StartOf (_, NoOffset) -> true | CastE (_typ, e) -> (* 0 can always be converted into a NULL pointer. *) diff --git a/tests/rte/invalid_fptr.i b/tests/rte/invalid_fptr.i new file mode 100644 index 00000000000..45f779e17a2 --- /dev/null +++ b/tests/rte/invalid_fptr.i @@ -0,0 +1,15 @@ +/* run.config +OPT: -rte -warn-invalid-pointer -print +*/ + +struct S { void (*f)(void); } s; + +void (*p)(void); + +void f(void) { + if (p) return; // should not warn + if (p+2) return; // should warn + if (s.f) return; //should not warn + if (s.f+2) return; // should warn + return; +} diff --git a/tests/rte/oracle/invalid_fptr.res.oracle b/tests/rte/oracle/invalid_fptr.res.oracle new file mode 100644 index 00000000000..d8e8029a754 --- /dev/null +++ b/tests/rte/oracle/invalid_fptr.res.oracle @@ -0,0 +1,20 @@ +[kernel] Parsing tests/rte/invalid_fptr.i (no preprocessing) +[rte] annotating function f +/* Generated by Frama-C */ +struct S { + void (*f)(void) ; +}; +struct S s; +void (*p)(void); +void f(void) +{ + if (p) goto return_label; + /*@ assert rte: pointer_value: \valid_function(p + 2); */ + if (p + 2) goto return_label; + if (s.f) goto return_label; + /*@ assert rte: pointer_value: \valid_function(s.f + 2); */ + if (s.f + 2) goto return_label; + return_label: return; +} + + -- GitLab