Skip to content
Snippets Groups Projects
Commit dbd447ab authored by Julien Signoles's avatar Julien Signoles Committed by Fonenantsoa Maurica
Browse files

do not monitor variables with incomplete types (fix bts #2406)

parent c3d18692
No related branches found
No related tags found
No related merge requests found
...@@ -19,6 +19,8 @@ ...@@ -19,6 +19,8 @@
# configure configure # configure configure
############################################################################### ###############################################################################
-* E-ACSL [2018/10/23] Fix bug #2406 about monitoring of variables
with incomplete types.
-* E-ACSL [2018/10/04] Fix bug #2386 about incorrect typing when -* E-ACSL [2018/10/04] Fix bug #2386 about incorrect typing when
performing pointer subtraction. performing pointer subtraction.
-* E-ACSL [2018/10/04] Support for \at on purely logic variables. -* E-ACSL [2018/10/04] Support for \at on purely logic variables.
......
...@@ -6,13 +6,15 @@ release. First we list changes of the last release. ...@@ -6,13 +6,15 @@ release. First we list changes of the last release.
\section*{E-ACSL \eacslversion} \section*{E-ACSL \eacslversion}
\begin{itemize} \begin{itemize}
\item \textbf{Introduction}: Improve a bit and reference related papers. \item \textbf{Introduction}: Improve a bit and reference new related papers.
\item \textbf{What the Plug-in Provides}: Highlight that the memory analysis is \item \textbf{What the Plug-in Provides}: Highlight that the memory analysis is
not yet robust. not yet robust.
\item \textbf{What the Plug-in Provides}: Highlight the importance of \item \textbf{What the Plug-in Provides}: Highlight the importance of
\textbf{-e-acsl-prepare}. \textbf{-e-acsl-prepare}.
\item \textbf{Known Limitations}: Replace section ``Limitations of E-ACSL \item \textbf{Known Limitations}: Replace section ``Limitations of E-ACSL
Monitoring Libraries'' by the new section ``Supported Systems''. Monitoring Libraries'' by the new section ``Supported Systems''.
\item \textbf{Known Limitations}: Add limitation about monitoring of variables
with incomplete types.
\end{itemize} \end{itemize}
\section*{E-ACSL Chlorine-20180501} \section*{E-ACSL Chlorine-20180501}
......
...@@ -143,8 +143,8 @@ instrumented code (linked against this main) could print some warnings from the ...@@ -143,8 +143,8 @@ instrumented code (linked against this main) could print some warnings from the
\label{sec:limits:no-code} \label{sec:limits:no-code}
\index{Function!Undefined} \index{Function!Undefined}
The instrumentation in the generated program is partial for a program $p$ if and The instrumentation in the generated program is partial for a program $p$ if $p$
only if $p$ contains a memory-related annotation $a$ and an undefined function contains a memory-related annotation $a$ and an undefined function
$f$ such that: $f$ such that:
\begin{itemize} \begin{itemize}
\item either $f$ has an (even indirect) effect on a left-value occurring in $a$; \item either $f$ has an (even indirect) effect on a left-value occurring in $a$;
...@@ -155,6 +155,15 @@ A violation of such an annotation $a$ is undetected. There is no workaround yet. ...@@ -155,6 +155,15 @@ A violation of such an annotation $a$ is undetected. There is no workaround yet.
Also, the option \optionuse{-}{e-acsl-check} does not verify the annotations of Also, the option \optionuse{-}{e-acsl-check} does not verify the annotations of
undefined functions. There is also no workaround yet. undefined functions. There is also no workaround yet.
\subsection{Incomplete Types}
\index{Type!Incomplete}
The instrumentation in the generated program is partial for a program $p$ if $p$
contains a memory-related annotation $a$ and a variable $v$ with an incomplete
type definition such that $a$ depends on $v$ (even indirectly).
A violation of such an annotation $a$ is undetected. There is no workaround yet.
\section{Recursive Functions} \section{Recursive Functions}
\index{Function!Recursive} \index{Function!Recursive}
......
...@@ -25,6 +25,15 @@ open Cil_datatype ...@@ -25,6 +25,15 @@ open Cil_datatype
module Dataflow = Dataflow2 module Dataflow = Dataflow2
let must_never_monitor vi =
(* extern ghost variables are usually used (by the Frama-C libc) to
represent some internal invisible states in ACSL specifications. They do
not correspond to something concrete *)
(vi.vghost && vi.vstorage = Extern)
||
(* incomplete types cannot be properly monitored. See BTS #2406. *)
not (Cil.isCompleteType vi.vtype)
(* ********************************************************************** *) (* ********************************************************************** *)
(* Backward dataflow analysis to compute a sound over-approximation of what (* Backward dataflow analysis to compute a sound over-approximation of what
left-values must be tracked by the memory model library *) left-values must be tracked by the memory model library *)
...@@ -225,16 +234,20 @@ module rec Transfer ...@@ -225,16 +234,20 @@ module rec Transfer
let extend_to_expr always state lhost e = let extend_to_expr always state lhost e =
let add_vi state vi = let add_vi state vi =
if is_ptr_or_array_exp e && (always || Varinfo.Hptset.mem vi state) then if is_ptr_or_array_exp e && (always || Varinfo.Hptset.mem vi state)
then begin
match base_addr e with match base_addr e with
| None -> state | None -> state
| Some vi_e -> | Some vi_e ->
Options.feedback ~level:4 ~dkey if must_never_monitor vi then state
"monitoring %a from %a." else begin
Printer.pp_varinfo vi_e Options.feedback ~level:4 ~dkey
Printer.pp_lval (lhost, NoOffset); "monitoring %a from %a."
Varinfo.Hptset.add vi_e state Printer.pp_varinfo vi_e
else Printer.pp_lval (lhost, NoOffset);
Varinfo.Hptset.add vi_e state
end
end else
state state
in in
match lhost with match lhost with
...@@ -721,44 +734,70 @@ consolidated_must_model_vi vi ...@@ -721,44 +734,70 @@ consolidated_must_model_vi vi
false false
*) *)
let rec must_model_lval bhv ?kf ?stmt = function let rec apply_on_vi_base_from_lval f bhv ?kf ?stmt = function
| Var vi, _ -> must_model_vi bhv ?kf ?stmt vi | Var vi, _ -> f bhv ?kf ?stmt vi
| Mem e, _ -> must_model_exp bhv ?kf ?stmt e | Mem e, _ -> apply_on_vi_base_from_exp f bhv ?kf ?stmt e
and must_model_exp bhv ?kf ?stmt e = match e.enode with and apply_on_vi_base_from_exp f bhv ?kf ?stmt e = match e.enode with
| Lval lv | AddrOf lv | StartOf lv -> | Lval lv | AddrOf lv | StartOf lv ->
must_model_lval bhv ?kf ?stmt lv apply_on_vi_base_from_lval f bhv ?kf ?stmt lv
| BinOp((PlusPI | IndexPI | MinusPI), e1, _, _) -> | BinOp((PlusPI | IndexPI | MinusPI), e1, _, _) ->
must_model_exp bhv ?kf ?stmt e1 apply_on_vi_base_from_exp f bhv ?kf ?stmt e1
| BinOp(MinusPP, e1, e2, _) -> | BinOp(MinusPP, e1, e2, _) ->
must_model_exp bhv ?kf ?stmt e1 || must_model_exp bhv ?kf ?stmt e2 apply_on_vi_base_from_exp f bhv ?kf ?stmt e1
| Info(e, _) | CastE(_, e) -> must_model_exp bhv ?kf ?stmt e || apply_on_vi_base_from_exp f bhv ?kf ?stmt e2
| Info(e, _) | CastE(_, e) -> apply_on_vi_base_from_exp f bhv ?kf ?stmt e
| BinOp((PlusA | MinusA | Mult | Div | Mod |Shiftlt | Shiftrt | Lt | Gt | Le | BinOp((PlusA | MinusA | Mult | Div | Mod |Shiftlt | Shiftrt | Lt | Gt | Le
| Ge | Eq | Ne | BAnd | BXor | BOr | LAnd | LOr), _, _, _) | Ge | Eq | Ne | BAnd | BXor | BOr | LAnd | LOr), _, _, _)
| Const _ -> (* possible in case of static address *) false | Const _ -> (* possible in case of static address *) false
| UnOp _ | SizeOf _ | SizeOfE _ | SizeOfStr _ | AlignOf _ | AlignOfE _ -> | UnOp _ | SizeOf _ | SizeOfE _ | SizeOfStr _ | AlignOf _ | AlignOfE _ ->
Options.fatal "[pre_analysis] unexpected expression %a" Exp.pretty e Options.fatal "[pre_analysis] unexpected expression %a" Exp.pretty e
let must_model_lval = apply_on_vi_base_from_lval must_model_vi
let must_model_exp = apply_on_vi_base_from_exp must_model_vi
let must_never_monitor_lval bhv ?kf ?stmt lv =
apply_on_vi_base_from_lval
(fun _bhv ?kf:_ ?stmt:_ vi -> must_never_monitor vi)
bhv
?kf
?stmt
lv
let must_never_monitor_exp bhv ?kf ?stmt lv =
apply_on_vi_base_from_exp
(fun _bhv ?kf:_ ?stmt:_ vi -> must_never_monitor vi)
bhv
?kf
?stmt
lv
(* ************************************************************************** *) (* ************************************************************************** *)
(** {1 Public API} *) (** {1 Public API} *)
(* ************************************************************************** *) (* ************************************************************************** *)
let must_model_vi ?bhv ?kf ?stmt vi = let must_model_vi ?bhv ?kf ?stmt vi =
not (vi.vghost && vi.vstorage = Extern) not (must_never_monitor vi)
&& &&
(Options.Full_mmodel.get () (Options.Full_mmodel.get ()
|| Error.generic_handle (must_model_vi bhv ?kf ?stmt) false vi) || Error.generic_handle (must_model_vi bhv ?kf ?stmt) false vi)
let must_model_lval ?bhv ?kf ?stmt lv = let must_model_lval ?bhv ?kf ?stmt lv =
Options.Full_mmodel.get () not (must_never_monitor_lval bhv ?kf ?stmt lv)
|| Error.generic_handle (must_model_lval bhv ?kf ?stmt) false lv &&
(Options.Full_mmodel.get ()
|| Error.generic_handle (must_model_lval bhv ?kf ?stmt) false lv)
let must_model_exp ?bhv ?kf ?stmt exp = let must_model_exp ?bhv ?kf ?stmt exp =
Options.Full_mmodel.get () not (must_never_monitor_exp bhv ?kf ?stmt exp)
|| Error.generic_handle (must_model_exp bhv ?kf ?stmt) false exp &&
(Options.Full_mmodel.get ()
|| Error.generic_handle (must_model_exp bhv ?kf ?stmt) false exp)
let use_model () = not (Env.is_empty ()) || Options.Full_mmodel.get () || let use_model () =
Env.has_heap_allocations () not (Env.is_empty ())
|| Options.Full_mmodel.get ()
|| Env.has_heap_allocations ()
(* (*
Local Variables: Local Variables:
......
/* run.config
COMMENT: bts #2306, do not monitor incomplete types
*/
const char tab[]; /* not monitored */
char t[10]; /* monitored */
int main(void) {
char *p = tab; /* monitored */
/*@ assert !\valid(p+(0..9)); */
/*@ assert \valid(t+(0..9)); */
return 0;
}
[e-acsl] beginning translation.
[e-acsl] translation done in project "e-acsl".
[eva] tests/bts/bts2406.c:5: Warning:
during initialization of variable 'tab', size of type 'char const []'
cannot be computed (Size of array without number of elements.)
/* Generated by Frama-C */
#include "stdio.h"
#include "stdlib.h"
char const tab[];
char t[10];
void __e_acsl_globals_init(void)
{
__e_acsl_store_block((void *)(t),(size_t)10);
__e_acsl_full_init((void *)(& t));
return;
}
int main(void)
{
int __retres;
__e_acsl_memory_init((int *)0,(char ***)0,(size_t)8);
__e_acsl_globals_init();
char *p = (char *)(tab);
__e_acsl_store_block((void *)(& p),(size_t)8);
__e_acsl_full_init((void *)(& p));
/*@ assert ¬\valid(p + (0 .. 9)); */
{
int __gen_e_acsl_valid;
__gen_e_acsl_valid = __e_acsl_valid((void *)(p + 1 * 0),(size_t)9,
(void *)p,(void *)(& p));
__e_acsl_assert(! __gen_e_acsl_valid,(char *)"Assertion",(char *)"main",
(char *)"!\\valid(p + (0 .. 9))",10);
}
/*@ assert \valid(&t[0 .. 9]); */
{
int __gen_e_acsl_valid_2;
__gen_e_acsl_valid_2 = __e_acsl_valid((void *)(& t + 1 * 0),(size_t)9,
(void *)(& t),(void *)0);
__e_acsl_assert(__gen_e_acsl_valid_2,(char *)"Assertion",(char *)"main",
(char *)"\\valid(&t[0 .. 9])",11);
}
__retres = 0;
__e_acsl_delete_block((void *)(t));
__e_acsl_delete_block((void *)(& p));
__e_acsl_memory_clean();
return __retres;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment