diff --git a/src/plugins/e-acsl/.Makefile.lint b/src/plugins/e-acsl/.Makefile.lint new file mode 100644 index 0000000000000000000000000000000000000000..e513a673fa3b459bc4fd6cb0bae46f39f5b5afc9 --- /dev/null +++ b/src/plugins/e-acsl/.Makefile.lint @@ -0,0 +1,45 @@ +ML_LINT_KO+=src/plugins/e-acsl/E_ACSL.mli +ML_LINT_KO+=src/plugins/e-acsl/demo/script.ml +ML_LINT_KO+=src/plugins/e-acsl/src/analyses/exit_points.ml +ML_LINT_KO+=src/plugins/e-acsl/src/analyses/exit_points.mli +ML_LINT_KO+=src/plugins/e-acsl/src/analyses/interval.ml +ML_LINT_KO+=src/plugins/e-acsl/src/analyses/literal_strings.ml +ML_LINT_KO+=src/plugins/e-acsl/src/analyses/lscope.ml +ML_LINT_KO+=src/plugins/e-acsl/src/analyses/lscope.mli +ML_LINT_KO+=src/plugins/e-acsl/src/analyses/mmodel_analysis.ml +ML_LINT_KO+=src/plugins/e-acsl/src/analyses/rte.ml +ML_LINT_KO+=src/plugins/e-acsl/src/analyses/typing.ml +ML_LINT_KO+=src/plugins/e-acsl/src/analyses/typing.mli +ML_LINT_KO+=src/plugins/e-acsl/src/code_generator/at_with_lscope.ml +ML_LINT_KO+=src/plugins/e-acsl/src/code_generator/at_with_lscope.mli +ML_LINT_KO+=src/plugins/e-acsl/src/code_generator/env.ml +ML_LINT_KO+=src/plugins/e-acsl/src/code_generator/env.mli +ML_LINT_KO+=src/plugins/e-acsl/src/code_generator/gmp.ml +ML_LINT_KO+=src/plugins/e-acsl/src/code_generator/label.ml +ML_LINT_KO+=src/plugins/e-acsl/src/code_generator/logic_functions.ml +ML_LINT_KO+=src/plugins/e-acsl/src/code_generator/loops.ml +ML_LINT_KO+=src/plugins/e-acsl/src/code_generator/loops.mli +ML_LINT_KO+=src/plugins/e-acsl/src/code_generator/mmodel_translate.ml +ML_LINT_KO+=src/plugins/e-acsl/src/code_generator/mmodel_translate.mli +ML_LINT_KO+=src/plugins/e-acsl/src/code_generator/quantif.ml +ML_LINT_KO+=src/plugins/e-acsl/src/code_generator/quantif.mli +ML_LINT_KO+=src/plugins/e-acsl/src/code_generator/rational.ml +ML_LINT_KO+=src/plugins/e-acsl/src/code_generator/temporal.ml +ML_LINT_KO+=src/plugins/e-acsl/src/code_generator/temporal.mli +ML_LINT_KO+=src/plugins/e-acsl/src/code_generator/translate.ml +ML_LINT_KO+=src/plugins/e-acsl/src/code_generator/translate.mli +ML_LINT_KO+=src/plugins/e-acsl/src/code_generator/visit.ml +ML_LINT_KO+=src/plugins/e-acsl/src/libraries/builtins.ml +ML_LINT_KO+=src/plugins/e-acsl/src/libraries/error.ml +ML_LINT_KO+=src/plugins/e-acsl/src/libraries/error.mli +ML_LINT_KO+=src/plugins/e-acsl/src/libraries/functions.ml +ML_LINT_KO+=src/plugins/e-acsl/src/libraries/functions.mli +ML_LINT_KO+=src/plugins/e-acsl/src/libraries/misc.ml +ML_LINT_KO+=src/plugins/e-acsl/src/libraries/misc.mli +ML_LINT_KO+=src/plugins/e-acsl/src/main.ml +ML_LINT_KO+=src/plugins/e-acsl/src/options.ml +ML_LINT_KO+=src/plugins/e-acsl/src/project_initializer/dup_functions.ml +ML_LINT_KO+=src/plugins/e-acsl/src/project_initializer/keep_status.ml +ML_LINT_KO+=src/plugins/e-acsl/src/project_initializer/prepare_ast.ml +ML_LINT_KO+=src/plugins/e-acsl/src/project_initializer/prepare_ast.mli +ML_LINT_KO+=src/plugins/e-acsl/top/E_ACSL.mli diff --git a/src/plugins/e-acsl/.gitignore b/src/plugins/e-acsl/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..f5ee39fdfacb148fe2e6ab6c724865925290ea92 --- /dev/null +++ b/src/plugins/e-acsl/.gitignore @@ -0,0 +1,79 @@ +*~ +*.o +*.cm* +*.annot +/*_DEP +/configure +/config.log +/Makefile +/.depend +/local_config.ml +/config.status +/autom4te.cache +/ptests_local_config.ml +/configure.lineno +/share/*.cm* +/share/*.annot +/share/*_DEP +/share/e-acsl/*.cm* +/share/e-acsl/*.annot +/share/e-acsl/*_DEP +/doc/manuals +/doc/code +/doc/refman/*.out +/doc/refman/*.bbl +/doc/refman/*.blg +/doc/refman/*.id* +/doc/refman/*.aux +/doc/refman/*.cb* +/doc/refman/*.toc +/doc/refman/*.lo* +/doc/refman/*.inf +/doc/refman/*.ilg +/doc/refman/e-acsl*.tex +/doc/refman/framacversion.tex +/doc/refman/main.pdf +/doc/refman/*.bnf +/doc/refman/*.cm* +/doc/refman/transf +/doc/refman/transf.ml +/doc/refman/*.ind +/doc/userman/*.aux +/doc/userman/*.bbl +/doc/userman/*.blg +/doc/userman/*.ind +/doc/userman/*.ilg +/doc/userman/*.out +/doc/userman/*.cb* +/doc/userman/*.toc +/doc/userman/*.idx +/doc/userman/*.log +/doc/userman/*.lof +/doc/userman/eacslversion.tex +/tests/*.cm* +/tests/*.annot +/tests/*_DEP +/tests/test_config +/tests/test_config_ci +/tests/test_config_dev +/tests/*/result*/* +/tests/check/obj/* +.frama-c +tests/ptests_config +META.frama-c-e_acsl +.merlin +.Makefile.plugin.generated +E_ACSL.check_mli_exists +top/ +doc/doxygen/doxygen.cfg +doc/doxygen/html +doc/doxygen/warn.log +lib/libeacsl-jemalloc.a +lib/libeacsl-dlmalloc.a +lib/libeacsl-gmp.a +lib/libeacsl-rtl-bittree.a +lib/libeacsl-rtl-segment.a +lib/libeacsl-rtl-bittree-dbg.a +lib/libeacsl-rtl-segment-dbg.a +tests/csrv14/* +src/local_config.ml diff --git a/src/plugins/e-acsl/.gitlab-ci.yml b/src/plugins/e-acsl/.gitlab-ci.yml new file mode 100644 index 0000000000000000000000000000000000000000..b9be114170ac470939c88f545001c63633665d50 --- /dev/null +++ b/src/plugins/e-acsl/.gitlab-ci.yml @@ -0,0 +1,54 @@ +stages: + - git-update + - build + - tests + +variables: + CURRENT: $CI_COMMIT_REF_NAME + DEFAULT: "master" + OCAML: "4_05" + FRAMA_CI_OPT: "--override e-acsl:$CI_COMMIT_REF_NAME,$CI_COMMIT_SHA" + + +#avoid a nix error https://github.com/NixOS/nix/issues/2087 +git-update: + stage: git-update + script: + - nix/frama-ci.sh instantiate --eval -A e-acsl.src.outPath + tags: + - nix + +E-ACSL: + stage: build + script: + - nix/frama-ci.sh build -A e-acsl.installed + tags: + - nix + +CheckHeaders: + stage: build + script: + - nix/frama-ci.sh build -A genassigns.checkHeaders + tags: + - nix + +Tests: + stage: tests + script: + - nix/frama-ci.sh build -A e-acsl.tests + tags: + - nix + +Cfp: + stage: tests + script: + - nix/frama-ci.sh build -A context-from-precondition.tests + tags: + - nix + +Security: + stage: tests + script: + - nix/frama-ci.sh build -A security.tests + tags: + - nix diff --git a/src/plugins/e-acsl/E_ACSL.mli b/src/plugins/e-acsl/E_ACSL.mli new file mode 100644 index 0000000000000000000000000000000000000000..b889109f461ee67f67d95f3b46a0b4aab004edd1 --- /dev/null +++ b/src/plugins/e-acsl/E_ACSL.mli @@ -0,0 +1,48 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C's E-ACSL plug-in. *) +(* *) +(* Copyright (C) 2012-2018 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(** E-ACSL. *) + +open Cil_types + +module Error: sig + exception Typing_error of string + exception Not_yet of string +end + +module Translate: sig + exception No_simple_translation of term + val term_to_exp: typ option -> term -> exp +(** @raise New_typing_error when the given term cannot be typed (something wrong + happened with this term) + @raise Not_yet when the given term contains an unsupported construct. + @raise No_simple_translation when the given term cannot be translated into + a single expression. *) +end + +(** No function is directly exported: they are dynamically registered. *) + +(* +Local Variables: +compile-command: "make" +End: +*) diff --git a/src/plugins/e-acsl/INSTALL b/src/plugins/e-acsl/INSTALL new file mode 100644 index 0000000000000000000000000000000000000000..07ef84963905817bba6eaf3b9ce49f232ccec80f --- /dev/null +++ b/src/plugins/e-acsl/INSTALL @@ -0,0 +1,115 @@ + ------------------------- + INSTALLATION INSTRUCTIONS + ------------------------- + +=============================================================================== + SUMMARY +=============================================================================== + +0) Summary +1) Quick Start +2) Requirements +3) Configuration +4) Compilation +5) Installation +6) Custom Installation +7) Testing the Installation +8) Uninstallation +9) Have Fun with E-ACSL! + +=============================================================================== + QUICK START +=============================================================================== + +1) Install Frama-C if not already installed. + +2a) On Linux-like distribution: + ./configure && make && sudo make install + +2b) On Windows+Cygwin or Windows+MinGW+msys: + ./configure --prefix C:/windows/path/with/direct/slash && make && make install + +4) Optionally, test your installation by running: + frama-c.byte -e-acsl tests/runtime/true.i -then-last -print + frama-c -e-acsl tests/runtime/true.i -then-last -print + +See below for more detailed and specific instructions. + +=============================================================================== + REQUIREMENTS +=============================================================================== + +- Frama-C = Silicon-20161101 + (no warranty that this plug-in works with a more recent version of Frama-C) + +=============================================================================== + CONFIGURATION +=============================================================================== + +The E-ACSL plug-in is configured by "./configure [options]" + +configure is generated by autoconf, so that the standard options for setting +installation directories are available, in particular '--prefix=/path'. + +Under Cygwin or MinGW: +---------------------- +Use "./configure --prefix C:/windows/path/with/direct/slash". + +=============================================================================== + COMPILATION +=============================================================================== + +Type "make". + +Makefile targets of interest are: +- doc generates the API documentation + +=============================================================================== + INSTALLATION +=============================================================================== + +Type "make install" +(depending on the installation directory, may require superuser privileges). + +It is possible to install in a given directory by setting +the DESTDIR variable: "make install DESTDIR=/tmp" installs Frama-C in +sub-directories of /tmp. + +=============================================================================== + CUSTOM INSTALLATION +=============================================================================== + +You can manually move any installed files. However, in such a case, you have to +set specific environment variables in order that Frama-C found the appropriate +objects when required. + +The environment variables are: +------------------------------ +FRAMAC_SHARE: absolute path to the Frama-C share subdirectory +FRAMAC_LIB: absolute path of the Frama-C lib subdirectory +FRAMAC_PLUGIN: absolute path of the Frama-C plug-in directory. + +=============================================================================== + TESTING THE INSTALLATION +=============================================================================== + +This step is optional. + +Test your installation by running: + frama-c.byte -e-acsl tests/runtime/true.i -then-last -print + frama-c -e-acsl tests/runtime/true.i -then-last -print + +The second command only works if native dynamic linking of OCaml is available +on your system. + +=============================================================================== + UNINSTALLATION +=============================================================================== + +Type "make uninstall" to remove Frama-C and all the installed plug-ins. +That works only if you have not manually moved the installed files (see Section +"Custom Installation"). + +=============================================================================== + HAVE FUN WITH E-ACSL! +=============================================================================== diff --git a/src/plugins/e-acsl/Makefile.in b/src/plugins/e-acsl/Makefile.in new file mode 100644 index 0000000000000000000000000000000000000000..d5dc027bf123520b62e0bde012ce6937937f89a1 --- /dev/null +++ b/src/plugins/e-acsl/Makefile.in @@ -0,0 +1,548 @@ +########################################################################## +# # +# This file is part of the Frama-C's E-ACSL plug-in. # +# # +# Copyright (C) 2012-2018 # +# CEA (Commissariat à l'énergie atomique et aux énergies # +# alternatives) # +# # +# you can redistribute it and/or modify it under the terms of the GNU # +# Lesser General Public License as published by the Free Software # +# Foundation, version 2.1. # +# # +# It is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU Lesser General Public License for more details. # +# # +# See the GNU Lesser General Public License version 2.1 # +# for more details (enclosed in the file licenses/LGPLv2.1). # +# # +########################################################################## + +####################### +# Frama-C Environment # +####################### + +# Do not use ?= to initialize both below variables +# (fixed efficiency issue, see GNU Make manual, Section 8.11) +ifndef FRAMAC_SHARE +FRAMAC_SHARE :=$(shell frama-c-config -print-share-path) +endif + +# OCAMLVERSION and HAS_OCAML312 are defined in Frama-C common Makefile but +# cannot be used at this point. Unfortunatly cannot reuse the same variable name +# here without introducing unexpected interaction with Frama-C compilation when +# compiling it with --enable-external=e-acsl. +EACSL_OCAMLVERSION ?=@OCAMLVERSION@ +ifeq ($(findstring 3.12,$(EACSL_OCAMLVERSION)),) +EACSL_HAS_OCAML312 = no +else +EACSL_HAS_OCAML312 = yes +endif + +# Utilities used to create the list of contrib/ files to be included in the +# distribution. In external mode, we can't rely on these variables to be +# set, as we have to build the list before including Makefile.dynamic. +# There is no real alternative to cat and sed anyways, which are both part of +# POSIX, so that the usefulness of the variables is questionable. +CAT?=cat +SED?=sed + +################### +# Plug-in sources # +################### + +# libraries +SRC_LIBRARIES:= \ + error \ + builtins \ + functions \ + misc \ + gmp_types \ + varname +SRC_LIBRARIES:=$(addprefix src/libraries/, $(SRC_LIBRARIES)) + +# analyses +SRC_ANALYSES:= \ + rte \ + literal_strings \ + mmodel_analysis \ + exit_points \ + lscope \ + interval \ + typing +SRC_ANALYSES:=$(addprefix src/analyses/, $(SRC_ANALYSES)) + +# project initializer +SRC_PROJECT_INITIALIZER:= \ + keep_status \ + prepare_ast \ + dup_functions +SRC_PROJECT_INITIALIZER:=\ + $(addprefix src/project_initializer/, $(SRC_PROJECT_INITIALIZER)) + +# code generator +SRC_CODE_GENERATOR:= \ + gmp \ + label \ + env \ + rational \ + loops \ + quantif \ + at_with_lscope \ + mmodel_translate \ + logic_functions \ + translate \ + temporal \ + visit +SRC_CODE_GENERATOR:=$(addprefix src/code_generator/, $(SRC_CODE_GENERATOR)) + +######################### +# Plug-in configuration # +######################### + +PLUGIN_DIR ?=. +PLUGIN_EXTRA_DIRS:=\ + src \ + src/libraries \ + src/analyses \ + src/project_initializer \ + src/code_generator +PLUGIN_ENABLE:=@ENABLE_E_ACSL@ +PLUGIN_DYNAMIC:=@DYNAMIC_E_ACSL@ +PLUGIN_NAME:=E_ACSL +PLUGIN_CMO:= src/local_config \ + src/options \ + $(SRC_LIBRARIES) \ + $(SRC_ANALYSES) \ + $(SRC_PROJECT_INITIALIZER) \ + $(SRC_CODE_GENERATOR) \ + src/main + +PLUGIN_HAS_MLI:=yes +PLUGIN_DISTRIBUTED:=yes + +# We "save" this variable so that it can be used once PLUGIN_DIR has been reset +EACSL_PLUGIN_DIR:=$(PLUGIN_DIR) + +# Suppress a spurious warning with OCaml >= 4.04.0 +$(EACSL_PLUGIN_DIR)/src/analyses/mmodel_analysis.cmo \ +$(EACSL_PLUGIN_DIR)/src/analyses/mmodel_analysis.cmi: E_ACSL_BFLAGS+= -w -60 +$(EACSL_PLUGIN_DIR)/src/analyses/mmodel_analysis.cmx: E_ACSL_OFLAGS+= -w -60 + +############### +# Local Flags # +############### +# Do not edit the line below: it is automatically set by 'make e-acsl-distrib' +IS_DISTRIBUTED:=no + +####################### +# Local configuration # +####################### + +PLUGIN_GENERATED:= $(EACSL_PLUGIN_DIR)/src/local_config.ml + +ifeq ("$(FRAMAC_INTERNAL)","yes") +VERSION_FILE=$(FRAMAC_ROOT_SRCDIR)/VERSION +else +VERSION_FILE=$(EACSL_PLUGIN_DIR)/VERSION +endif + +################ +# Version # +################ + +EACSL_VERSION:=$(shell sed -e 's/\\(.*\\)/\\1/' $(VERSION_FILE)) + +$(EACSL_PLUGIN_DIR)/src/local_config.ml: $(EACSL_PLUGIN_DIR)/Makefile.in $(VERSION_FILE) + $(PRINT_MAKING) $@ + $(RM) $@ + $(ECHO) "(* This file was automatically generated from $<. Don't edit it. *)" >> $@ + $(ECHO) "let version = \""$(EACSL_VERSION)"\"" >> $@ + $(CHMOD_RO) $@ + +########### +# Testing # +########### + +ifeq (@MAY_RUN_TESTS@,yes) + +-include in_frama_ci + +PLUGIN_TESTS_DIRS := \ + examples \ + bts \ + constructs \ + arith \ + memory \ + gmp-only \ + full-mmodel \ + format \ + temporal \ + special +# [JS 2019/02/26] deactivate tests 'builtin' as long as setjmp/longjmp is not +# supported. +# builtin + +PLUGIN_TESTS_LIB := $(EACSL_PLUGIN_DIR)/tests/print.ml + +DEV= +ifeq ("$(DEV)","yes") + EACSL_TEST_CONFIG=dev +else + EACSL_TEST_CONFIG:=ci +endif +PLUGIN_PTESTS_OPTS:=-config $(EACSL_TEST_CONFIG) + +E_ACSL_TESTS E_ACSL_DEFAULT_TESTS: \ + $(EACSL_PLUGIN_DIR)/tests/ptests_config \ + $(EACSL_PLUGIN_DIR)/tests/test_config_$(EACSL_TEST_CONFIG) \ + $(EACSL_PLUGIN_DIR)/tests/print.cmxs \ + $(EACSL_PLUGIN_DIR)/tests/print.cmo + + +$(EACSL_PLUGIN_DIR)/tests/test_config_ci: \ + $(EACSL_PLUGIN_DIR)/tests/test_config_ci.in \ + $(EACSL_PLUGIN_DIR)/Makefile + $(PRINT_MAKING) $@ + $(SED) -e "s|@SEDCMD@|`which sed `|g" $< > $@ + +$(EACSL_PLUGIN_DIR)/tests/test_config_dev: \ + $(EACSL_PLUGIN_DIR)/tests/test_config_dev.in \ + $(EACSL_PLUGIN_DIR)/Makefile + $(PRINT_MAKING) $@ + $(SED) -e "s|@SEDCMD@|`which sed `|g" $< > $@ + +tests:: $(EACSL_PLUGIN_DIR)/tests/ptests_config + +clean:: + for d in $(E_ACSL_EXTRA_DIRS); do \ + $(RM) $$d/*~; \ + done + $(PRINT_RM) cleaning generated test files + $(RM) $(E_ACSL_DIR)/tests/*.cm* $(E_ACSL_DIR)/tests/*.o + $(RM) $(E_ACSL_DIR)/tests/test_config_ci \ + $(E_ACSL_DIR)/tests/test_config_dev + $(RM) $(foreach dir, $(PLUGIN_TESTS_DIRS), tests/$(dir)/result/*) + +endif + +################################################ +# Third-party C libraries # +################################################ + +EACSL_LIBDIR := $(EACSL_PLUGIN_DIR)/lib + +############ +# DLMALLOC # +############ + +EACSL_DLMALLOC_REL_DIR := contrib/libdlmalloc +EACSL_DLMALLOC_DIR := $(EACSL_PLUGIN_DIR)/$(EACSL_DLMALLOC_REL_DIR) +EACSL_DLMALLOC_LIBNAME = libeacsl-dlmalloc.a +EACSL_DLMALLOC_LIB = $(EACSL_LIBDIR)/$(EACSL_DLMALLOC_LIBNAME) +EACSL_DLMALLOC_SRC = $(EACSL_DLMALLOC_DIR)/dlmalloc.c +EACSL_DLMALLOC_OBJ = dlmalloc.o +EACSL_DLMALLOC_FLAGS = \ + -DHAVE_MORECORE=0 \ + -DHAVE_MMAP=1 \ + -DNO_MALLINFO=1 \ + -DNO_MALLOC_STATS=1 \ + -DMSPACES=1 \ + -DONLY_MSPACES \ + -DMALLOC_ALIGNMENT=32 \ + -DMSPACE_PREFIX="__e_acsl_" + +$(EACSL_DLMALLOC_LIB): $(EACSL_DLMALLOC_SRC) + $(MKDIR) $(EACSL_LIBDIR) + echo 'CC $<' + $(CC) $< -c -O2 -g3 -o$(EACSL_DLMALLOC_OBJ) $(EACSL_DLMALLOC_FLAGS) + echo 'AR $@' + $(AR) crus $@ $(EACSL_DLMALLOC_OBJ) + echo 'RANLIB $@' + ranlib $@ + +all:: $(EACSL_DLMALLOC_LIB) + +clean:: + $(RM) $(EACSL_DLMALLOC_LIB) + +############ +# Cleaning # +############ + +EACSL_CLEANFILES = doc/doxygen/doxygen.cfg \ + Makefile config.log config.status configure .depend autom4te.cache/* \ + META.frama-c-e_acsl Makefile.plugin.generated src/local_config.ml top/* + +e-acsl-distclean:: clean + $(PRINT_RM) generated project files + $(RM) $(addprefix $(E_ACSL_DIR)/, $(EACSL_CLEANFILES)) + +################################ +# Building source distribution # +################################ + +EXPORT = e-acsl-$(EACSL_VERSION) + +EACSL_CONTRIB_FILES = \ + $(EACSL_DLMALLOC_REL_DIR)/dlmalloc.c + +EACSL_MANUAL_FILES = doc/manuals/*.pdf + +EACSL_DOC_FILES = \ + $(EACSL_MANUAL_FILES) \ + doc/doxygen/doxygen.cfg.in \ + doc/Changelog \ + man/e-acsl-gcc.sh.1 + +EACSL_TEST_FILES = \ + tests/test_config_dev.in \ + tests/test_config_ci.in \ + tests/gmp-only/test_config_ci \ + tests/gmp-only/test_config_dev \ + tests/full-mmodel/test_config_ci \ + tests/full-mmodel/test_config_dev \ + tests/builtin/test_config_ci \ + tests/builtin/test_config_dev \ + tests/temporal/test_config_ci \ + tests/temporal/test_config_dev \ + tests/format/test_config_ci \ + tests/format/test_config_dev \ + tests/print.ml + +# Test files without header management +EACSL_DISTRIB_TESTS = \ + $(foreach dir, $(addprefix tests/,$(PLUGIN_TESTS_DIRS)), \ + $(dir)/*.[ich] \ + $(dir)/test_config \ + $(dir)/oracle/*.c \ + $(dir)/oracle/*.oracle \ + ) + +EACSL_RTL_FILES = $(EACSL_RTL_SRC) + +EACSL_SCRIPT_FILES = scripts/e-acsl-gcc.sh + +EACSL_LICENSE_FILES = \ + license/CEA_LGPL license/SPARETIMELABS \ + license/headache_config.txt license/LGPLv2.1 + +EACSL_MISC_FILES = \ + configure.ac Makefile.in INSTALL README VERSION + +EACSL_SHARE_FILES = share/e-acsl/*.[ch] share/e-acsl/*/*.[ch] + +EACSL_DISTRIB_EXTERNAL =\ + $(EACSL_SHARE_FILES) \ + $(EACSL_MISC_FILES) \ + $(EACSL_DOC_FILES) \ + $(EACSL_TEST_FILES) \ + $(EACSL_RTL_FILES) \ + $(EACSL_SCRIPT_FILES) \ + $(EACSL_LICENSE_FILES) \ + $(EACSL_CONTRIB_FILES) + +PLUGIN_DISTRIB_EXTERNAL:= $(EACSL_DISTRIB_EXTERNAL) + +# Files of `DISTRIB_FILES` without header and not listed in file +# `headers/header_specs.txt`. +PLUGIN_HEADER_EXCEPTIONS:= + +# Files that are not listed in `DISTRIB_FILES` +# and decicated to distributed tests +PLUGIN_DISTRIB_TESTS:= $(EACSL_DISTRIB_TESTS) + +# for e-csl-distrib target: +EACSL_OCAML_FILES = \ + E_ACSL.mli \ + src/*.mli src/*/*.mli \ + $(patsubst $(EACSL_PLUGIN_DIR)/%, %, \ + $(filter-out $(wildcard $(EACSL_PLUGIN_DIR)/src/*local_config.ml), \ + $(wildcard $(EACSL_PLUGIN_DIR)/src/*.ml) \ + $(EACSL_PLUGIN_DIR/src/*/*.ml)) + +EACSL_DISTRIB_FILES = \ + $(patsubst $(EACSL_PLUGIN_DIR)/%,%,\ + $(wildcard $(addprefix $(EACSL_PLUGIN_DIR)/, \ + $(EACSL_OCAML_FILES) $(EACSL_DISTRIB_EXTERNAL) $(EACSL_DISTRIB_TESTS)))) + +# BE CAREFUL: manually remove all *.ml* files which should not be released! +e-acsl-distrib: + $(PRINT_TAR) tmp-distrib + cd $(EACSL_PLUGIN_DIR); \ + $(TAR) cf tmp.tar $(EACSL_DISTRIB_FILES) + $(PRINT_MAKING) export directories + $(MKDIR) $(EACSL_PLUGIN_DIR)/$(EXPORT) + $(PRINT_UNTAR) tmp-distrib + cd $(EACSL_PLUGIN_DIR)/$(EXPORT); \ + pwd && \ + $(TAR) xf ../tmp.tar && \ + autoconf && \ + $(SED) \ + -i -e 's/IS_DISTRIBUTED:=no/IS_DISTRIBUTED:=yes/' Makefile.in && \ + $(RM) -rf autom4te.cache + $(PRINT_RM) tmp-distrib + $(RM) $(EACSL_PLUGIN_DIR)/tmp.tar + $(PRINT_MAKING) archive $(EACSL_PLUGIN_DIR)/$(EXPORT).tar.gz + cd $(EACSL_PLUGIN_DIR) ; \ + $(TAR) czf $(EXPORT).tar.gz $(EXPORT) + $(PRINT) Cleaning + $(RM) -fr $(EACSL_PLUGIN_DIR)/$(EXPORT) + +WWW ?= /localhome/julien/frama-c/doc/www +e-acsl-install-distrib: e-acsl-distrib + $(PRINT) Copying to website + $(CP) $(EACSL_PLUGIN_DIR)/$(EXPORT).tar.gz \ + $(WWW)/distrib/download/e-acsl + $(CP) $(addprefix $(EACSL_PLUGIN_DIR)/, $(EACSL_DOC_FILES)) \ + $(WWW)/distrib/download/e-acsl +ifneq ("$(EACSL_MANUAL_FILES)","") + $(CP) $(EACSL_PLUGIN_DIR)/doc/manuals/e-acsl-manual.pdf \ + $(WWW)/distrib/download/e-acsl/e-acsl-manual-$(EACSL_VERSION).pdf + $(CP) $(EACSL_PLUGIN_DIR)/doc/manuals/e-acsl.pdf \ + $(WWW)/distrib/download/e-acsl/e-acsl-1.7.pdf + $(CP) $(EACSL_PLUGIN_DIR)/doc/manuals/e-acsl-implementation.pdf \ + $(WWW)/distrib/download/e-acsl/e-acsl-implementation-$(EACSL_VERSION).pdf +endif + +############################## +# Check source distribution # +############################## +e-acsl-distrib-check: + $(RM) -rf $(EXPORT)* + $(MAKE) e-acsl-distrib + $(TAR) -xvf $(EXPORT).tar.gz + unset FRAMAC_LIB && \ + cd $(EXPORT) && \ + ./configure && \ + $(MAKE) && \ + $(MAKE) doc && \ + $(MAKE) tests && \ + cd ../ && \ + $(RM) -rf $(EXPORT)* + +########## +# Header # +########## + +ifneq ("$(FRAMAC_INTERNAL)","yes") + +EACSL_SPARETIMELABS=$(EACSL_PLUGIN_DIR)/share/e-acsl/e_acsl_printf.h + +EACSL_SHARE_BARE= share/e-acsl/*.[ch] share/e-acsl/*/*.[ch] +EACSL_SHARE=$(addprefix $(EACSL_PLUGIN_DIR)/, $(EACSL_SHARE_BARE)) +EACSL_CEA_SHARE=$(filter-out $(EACSL_SPARETIMELABS), $(wildcard $(EACSL_SHARE))) + +EACSL_CEA_LGPL_BARE= src/*.ml src/*/*.ml src/*.mli src/*/*.mli \ + E_ACSL.mli \ + Makefile.in configure.ac \ + scripts/*.sh \ + tests/print.ml \ + man/e-acsl-gcc.sh.1 +EACSL_CEA_LGPL=$(addprefix $(EACSL_PLUGIN_DIR)/, $(EACSL_CEA_LGPL_BARE)) \ + $(EACSL_CEA_SHARE) + +# valid values: open-source, close-source +EACSL_HEADERS?=open-source +headers:: + @echo "Applying $(EACSL_HEADERS) headers..." + headache -c $(EACSL_PLUGIN_DIR)/license/headache_config.txt \ + -h $(EACSL_PLUGIN_DIR)/headers/$(EACSL_HEADERS)/CEA_LGPL_OR_PROPRIETARY.E_ACSL \ + $(EACSL_CEA_LGPL) + headache -c $(EACSL_PLUGIN_DIR)/license/headache_config.txt \ + -h $(EACSL_PLUGIN_DIR)/headers/$(EACSL_HEADERS)/MODIFIED_SPARETIMELABS \ + $(EACSL_SPARETIMELABS) + headache -c $(EACSL_PLUGIN_DIR)/license/headache_config.txt \ + -h $(EACSL_PLUGIN_DIR)/headers/$(EACSL_HEADERS)/MODIFIED_DLMALLOC \ + $(EACSL_PLUGIN_DIR)/contrib/libdlmalloc/dlmalloc.c + +endif + +################ +# Generic part # +################ + +include $(FRAMAC_SHARE)/Makefile.dynamic + +########### +# Install # +########### + +EACSL_INSTALL_MANUAL_FILES=$(wildcard $(addprefix $(EACSL_PLUGIN_DIR)/, $(EACSL_MANUAL_FILES))) + +install:: + $(PRINT_INSTALL) E-ACSL share files + $(MKDIR) $(FRAMAC_DATADIR)/e-acsl + $(CP) $(E_ACSL_DIR)/share/e-acsl/*.[ch] $(FRAMAC_DATADIR)/e-acsl + $(MKDIR) $(FRAMAC_DATADIR)/e-acsl/bittree_model \ + $(FRAMAC_DATADIR)/e-acsl/segment_model + $(CP) $(E_ACSL_DIR)/share/e-acsl/bittree_model/* \ + $(FRAMAC_DATADIR)/e-acsl/bittree_model + $(CP) $(E_ACSL_DIR)/share/e-acsl/segment_model/* \ + $(FRAMAC_DATADIR)/e-acsl/segment_model + # manuals are not present in standard distribution. + # Don't fail because of that. +ifneq ("$(EACSL_INSTALL_MANUAL_FILES)","") + $(PRINT_INSTALL) E-ACSL manuals + $(MKDIR) $(FRAMAC_DATADIR)/manuals + $(CP) $(EACSL_INSTALL_MANUAL_FILES) $(FRAMAC_DATADIR)/manuals; +endif + $(PRINT_INSTALL) E-ACSL libraries + $(MKDIR) $(LIBDIR) + $(CP) $(EACSL_LIBDIR)/libeacsl-*.a $(LIBDIR) + $(PRINT_INSTALL) E-ACSL scripts + $(MKDIR) $(BINDIR) + $(CP) $(E_ACSL_DIR)/scripts/e-acsl-gcc.sh $(BINDIR)/ + $(PRINT_INSTALL) E-ACSL man pages + $(MKDIR) $(MANDIR)/man1 + $(CP) $(E_ACSL_DIR)/man/e-acsl-gcc.sh.1 $(MANDIR)/man1/ + +uninstall:: + $(PRINT_RM) E-ACSL share files + $(RM) -r $(FRAMAC_DATADIR)/e-acsl + $(PRINT_RM) E-ACSL manuals + $(RM) $(FRAMAC_DATADIR)/manuals/*.pdf + $(PRINT_RM) E-ACSL libraries + $(RM) $(LIBDIR)/libeacsl-*.a + $(PRINT_RM) E-ACSL scripts + $(RM) $(BINDIR)/e-acsl-gcc.sh + $(PRINT_RM) E-ACSL man pages + $(RM) $(MANDIR)/man1/e-acsl-gcc.sh.1 + +##################################### +# Regenerating the Makefile on need # +##################################### + +ifeq ("$(FRAMAC_INTERNAL)","yes") +CONFIG_STATUS_DIR:=$(FRAMAC_SRC) +CONFIG_STATUS_DIR_DEP:= +else +CONFIG_STATUS_DIR:=$(E_ACSL_DIR) +CONFIG_STATUS_DIR_DEP:=$(CONFIG_STATUS_DIR)/config.status +endif + +$(E_ACSL_DIR)/Makefile: $(E_ACSL_DIR)/Makefile.in $(CONFIG_STATUS_DIR_DEP) + cd $(CONFIG_STATUS_DIR) && ./config.status + +##################################### +# Doxygen # +##################################### + +DOXYGEN = @DOXYGEN@ +doxygen: + if ! test $(DOXYGEN) = "no"; then \ + $(DOXYGEN) $(E_ACSL_DIR)/doc/doxygen/doxygen.cfg ; \ + else \ + echo "Warning: Skip doxygen documentation: \ +Doxygen executable not found."; \ + fi + +doc:: doxygen + +clean:: + $(PRINT_RM) generated documentation + $(RM) $(E_ACSL_DIR)/doc/doxygen/html/* + $(RM) $(E_ACSL_DIR)/doc/code/* + $(RM) $(E_ACSL_DIR)/doc/doxygen/warn.log diff --git a/src/plugins/e-acsl/README b/src/plugins/e-acsl/README new file mode 100644 index 0000000000000000000000000000000000000000..946e99a3cbf44c3ee788e915ae2418fb51bf999e --- /dev/null +++ b/src/plugins/e-acsl/README @@ -0,0 +1,110 @@ + ------ + README + ------ + +=============================================================================== + SUMMARY +=============================================================================== + +0) Summary +1) What Is +2) Simple usage +3) Examples +5) Compatibility with previous releases +6) Have Fun with E-ACSL! + +=============================================================================== + WHAT IS +=============================================================================== + +This package contains the Frama-C's E-ACSL plug-in. It takes as input an +annotated C program and returns the same program in which annotations have +been converted into C code dedicated to runtime assertion checking: this code +fails at runtime if the annotation is violated at runtime. + +Annotations must be written in a subset of ACSL (ANSI/ISO C Specification +Language), namely E-ACSL (Executable ANSI/ISO C Specification Language). E-ACSL +is fully described in file doc/manuals/e-acsl.pdf. + +This plug-in is still in a preliminary state: some parts of E-ACSL are not yet +implemented. What is supported is described in file +doc/manuals/e-acsl-implementation.pdf. + +Please read file INSTALL for details about the installation procedure of +this plug-in and consult http://frama-c.com and http://frama-c.com/acsl +for information about Frama-C and ACSL. + +The user manual is available at: + http://frama-c.com/download/e-acsl/e-acsl-manual.pdf + +=============================================================================== + SIMPLE USAGE +=============================================================================== + +E-ACSL comes with a convenient script e-acsl-gcc.sh. The standard use is the +following: + +$ e-acsl-gcc.sh -c <files> + +Here the only options is -c in order to compile the generated file which +contains the inline monitor from the input files. It outputs three binaries +./a.out, ./a.out.frama-c and ./a.out.e-acsl. The first one is the binary +produced by gcc from the input files, the second one is the binary produced by +gcc with the file generated by Frama-C from the input files, but without +monitoring any annotation. The third one is the binary produced by gcc with the +file generated by Frama-C from the input files, and monitoring the +annotations. Its execution behaves in the same way than the two other files, +except that it fails if an annotation is violated. + +Please refer to the user manual for details about e-acsl-gcc.sh. + +=============================================================================== + EXAMPLES +=============================================================================== + +1) Consider the following C program: +<true.i> +int main(void) { + /*@ assert \true; */ + return 0; +} + +Since the assertion is always true, the generated code behaves in the same way +that just returning 0: + +$ e-acsl-gcc.sh -c true.i +$ ./a.out.e-acsl +$ echo $? +0 + +Now consider the following C program: + +// false.i +int main(void) { + int x = 0; + /*@ assert x+1 == 0; */ + return 0; +} + +Since the assertion is always false, the generated code fails at runtime: + +$ e-acsl-gcc.sh -c false.i +$ ./a.out.e-acsl +Assertion failed at line 4. +The failing predicate is: +x + 1 == 0. +$ echo $? +1 + +More advanced examples are available in the user manual and in the plug-in +directory tests/e-acsl-runtime. + +=============================================================================== + COMPATIBILITY WITH PREVIOUS RELEASES +=============================================================================== + +Changes are documented in a textual way in file Changelog. + +=============================================================================== + HAVE FUN WITH E-ACSL! +=============================================================================== diff --git a/src/plugins/e-acsl/VERSION b/src/plugins/e-acsl/VERSION new file mode 100644 index 0000000000000000000000000000000000000000..e11f7bd73d436ea620c24e3de5ffc4dafda95064 --- /dev/null +++ b/src/plugins/e-acsl/VERSION @@ -0,0 +1 @@ +19.0+dev diff --git a/src/plugins/e-acsl/configure.ac b/src/plugins/e-acsl/configure.ac new file mode 100644 index 0000000000000000000000000000000000000000..d1376c9639ddaf40bf4fa31568d2fba89efa9822 --- /dev/null +++ b/src/plugins/e-acsl/configure.ac @@ -0,0 +1,147 @@ +########################################################################## +# # +# This file is part of the Frama-C's E-ACSL plug-in. # +# # +# Copyright (C) 2012-2018 # +# CEA (Commissariat à l'énergie atomique et aux énergies # +# alternatives) # +# # +# you can redistribute it and/or modify it under the terms of the GNU # +# Lesser General Public License as published by the Free Software # +# Foundation, version 2.1. # +# # +# It is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU Lesser General Public License for more details. # +# # +# See the GNU Lesser General Public License version 2.1 # +# for more details (enclosed in the file licenses/LGPLv2.1). # +# # +########################################################################## + +######################################## +# E-ACSL as a standard Frama-C plug-in # +######################################## + +m4_define([plugin_file],Makefile.in) + +m4_define([FRAMAC_SHARE_ENV], + [m4_normalize(m4_esyscmd([echo $FRAMAC_SHARE]))]) + +m4_define([FRAMAC_SHARE], + [m4_ifval(FRAMAC_SHARE_ENV,[FRAMAC_SHARE_ENV], + [m4_esyscmd(frama-c -print-path)])]) + +m4_ifndef([FRAMAC_M4_MACROS], [m4_include(FRAMAC_SHARE/configure.ac)]) + +check_plugin(e_acsl,PLUGIN_RELATIVE_PATH(plugin_file), + [support for E-ACSL plug-in],yes) + +plugin_require(e_acsl,rtegen) + +# E-ACSL only works on Linux as of now. Disable it on Mac OS and Windows +AC_CHECK_PROG(UNAME,uname,uname,no) + +if test "$UNAME" = "no"; then + plugin_disable(e_acsl,[Not on a POSIX platform.]) +fi + +HOST_OS=$($UNAME -s) +case $HOST_OS in +Darwin | Linux | DragonFly | FreeBSD | NetBSD | OpenBSD) +# BSDs haven't really be tested, but it should at least compile fine +;; +*) + plugin_disable(e_acsl,[unsupported system $HOST_OS]) +;; +esac + +# perform additional checks when not compiled +# directly with main Frama-C distribution +m4_ifndef([FRAMAC_MAIN_AUTOCONF], +[ + +check_plugin_dependencies + +# Check Frama-C version +####################### + +AC_MSG_CHECKING(for Frama-C version) +AC_MSG_RESULT($FRAMAC_VERSION) + +VERSION_NUMBER=`echo $FRAMAC_VERSION | sed -n -e 's/[[a-zA-Z]]\+-\([[0-9]]\+\).*/\1/p'` +EXTRA_VERSION_NUMBER=`echo $FRAMAC_VERSION | sed -n -e 's/[[a-zA-Z]]\+-[[0-9]]\+-\(.*\)/\1/p'` +REQUIRED_NUMBER=20161101 +REQUIRED_NAME=Silicon + +case $FRAMAC_VERSION in + $REQUIRED_NAME-$REQUIRED_NUMBER+dev*) + # at the time being, must use the Frama-C development version + ;; +# $REQUIRED_NAME-$REQUIRED_NUMBER*) +# if test -n "$EXTRA_VERSION_NUMBER"; then +# AC_MSG_WARN(no guarantee of compatibility with your Frama-C custom \ +# version of $REQUIRED_NAME) +# fi;; + *) + if test $VERSION_NUMBER -lt $REQUIRED_NUMBER; then + AC_MSG_ERROR(Frama-C version must be at least \ +$REQUIRED_NAME-$REQUIRED_NUMBER.) + else + if test $VERSION_NUMBER -gt $REQUIRED_NUMBER; then + AC_MSG_WARN(Frama-C version is more recent than $REQUIRED_NAME: \ +use it at your own risk) + fi + fi;; +esac +], +[]) # end of configuration specific to external compilation mode + +# no need to continue checking other features if E-ACSL is disabled +if test "$ENABLE_E_ACSL" != "no"; then + +############################### +# C specific stuff for E-ACSL # +############################### + +MAY_RUN_TESTS=yes + +# C compiler and stdio.h +######################### + +AC_CHECK_HEADERS([stdio.h],[HAVE_STDIO_H=yes],) + +# not sure it can actually happen: +# looks like configure stops on error if no C compiler detected +if test -z $HAVE_STDIO_H; then + MAY_RUN_TESTS=no + AC_MSG_WARN([stdio.h missing: non-regression tests unavailable.]) +fi + +# Doxygen +######### + +AC_CHECK_PROG(DOXYGEN,doxygen,doxygen,no) +AC_CHECK_PROG(HAVE_DOT,dot,yes,no) +AC_OUTPUT(PLUGIN_RELATIVE_PATH(doc/doxygen/doxygen.cfg), [ ]) + +####################### +# Generating Makefile # +####################### + +AC_SUBST(OPTIMIZED_RTL) +AC_SUBST(MAY_RUN_TESTS) +AC_SUBST(OCAMLVERSION) + +write_plugin_config(Makefile) + +############################### +# Configure contrib libraries # +############################### + +m4_ifndef([plugin_dir], [ + m4_define([plugin_dir],[./]) +]) + +fi diff --git a/src/plugins/e-acsl/contrib/.gitignore b/src/plugins/e-acsl/contrib/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/plugins/e-acsl/contrib/libdlmalloc/dlmalloc.c b/src/plugins/e-acsl/contrib/libdlmalloc/dlmalloc.c new file mode 100644 index 0000000000000000000000000000000000000000..0f9de38fb1e9e22b7351044f7915504cd5c049cd --- /dev/null +++ b/src/plugins/e-acsl/contrib/libdlmalloc/dlmalloc.c @@ -0,0 +1,6379 @@ +/**************************************************************************/ +/* */ +/* This is a version (aka dlmalloc) of malloc/free/realloc written by */ +/* Doug Lea and released to the public domain, as explained at */ +/* http://creativecommons.org/publicdomain/zero/1.0/ Send questions, */ +/* comments, complaints, performance data, etc to dl@cs.oswego.edu */ +/* */ +/* Version 2.8.6 Wed Aug 29 06:57:58 2012 Doug Lea */ +/* Note: There may be an updated version of this malloc obtainable at */ +/* ftp://gee.cs.oswego.edu/pub/misc/malloc.c */ +/* Check before installing! */ +/* */ +/* File modified by CEA (Commissariat à l'énergie atomique et aux */ +/* énergies alternatives). */ +/* */ +/**************************************************************************/ + +/* This file has been modified by CEA for use together with Runtime Library + of the E-ACSL plugin of Frama-C. + The changes introduced by CEA are limited to the following modifications: + * Added declaration/definition of mspace_least_addr function + * Added functionality to modify prefix of `mspace_...` functions. */ + +/* Quickstart + + This library is all in one file to simplify the most common usage: + ftp it, compile it (-O3), and link it into another program. All of + the compile-time options default to reasonable values for use on + most platforms. You might later want to step through various + compile-time and dynamic tuning options. + + For convenience, an include file for code using this malloc is at: + ftp://gee.cs.oswego.edu/pub/misc/malloc-2.8.6.h + You don't really need this .h file unless you call functions not + defined in your system include files. The .h file contains only the + excerpts from this file needed for using this malloc on ANSI C/C++ + systems, so long as you haven't changed compile-time options about + naming and tuning parameters. If you do, then you can create your + own malloc.h that does include all settings by cutting at the point + indicated below. Note that you may already by default be using a C + library containing a malloc that is based on some version of this + malloc (for example in linux). You might still want to use the one + in this file to customize settings or to avoid overheads associated + with library versions. + +* Vital statistics: + + Supported pointer/size_t representation: 4 or 8 bytes + size_t MUST be an unsigned type of the same width as + pointers. (If you are using an ancient system that declares + size_t as a signed type, or need it to be a different width + than pointers, you can use a previous release of this malloc + (e.g. 2.7.2) supporting these.) + + Alignment: 8 bytes (minimum) + This suffices for nearly all current machines and C compilers. + However, you can define MALLOC_ALIGNMENT to be wider than this + if necessary (up to 128bytes), at the expense of using more space. + + Minimum overhead per allocated chunk: 4 or 8 bytes (if 4byte sizes) + 8 or 16 bytes (if 8byte sizes) + Each malloced chunk has a hidden word of overhead holding size + and status information, and additional cross-check word + if FOOTERS is defined. + + Minimum allocated size: 4-byte ptrs: 16 bytes (including overhead) + 8-byte ptrs: 32 bytes (including overhead) + + Even a request for zero bytes (i.e., malloc(0)) returns a + pointer to something of the minimum allocatable size. + The maximum overhead wastage (i.e., number of extra bytes + allocated than were requested in malloc) is less than or equal + to the minimum size, except for requests >= mmap_threshold that + are serviced via mmap(), where the worst case wastage is about + 32 bytes plus the remainder from a system page (the minimal + mmap unit); typically 4096 or 8192 bytes. + + Security: static-safe; optionally more or less + The "security" of malloc refers to the ability of malicious + code to accentuate the effects of errors (for example, freeing + space that is not currently malloc'ed or overwriting past the + ends of chunks) in code that calls malloc. This malloc + guarantees not to modify any memory locations below the base of + heap, i.e., static variables, even in the presence of usage + errors. The routines additionally detect most improper frees + and reallocs. All this holds as long as the static bookkeeping + for malloc itself is not corrupted by some other means. This + is only one aspect of security -- these checks do not, and + cannot, detect all possible programming errors. + + If FOOTERS is defined nonzero, then each allocated chunk + carries an additional check word to verify that it was malloced + from its space. These check words are the same within each + execution of a program using malloc, but differ across + executions, so externally crafted fake chunks cannot be + freed. This improves security by rejecting frees/reallocs that + could corrupt heap memory, in addition to the checks preventing + writes to statics that are always on. This may further improve + security at the expense of time and space overhead. (Note that + FOOTERS may also be worth using with MSPACES.) + + By default detected errors cause the program to abort (calling + "abort()"). You can override this to instead proceed past + errors by defining PROCEED_ON_ERROR. In this case, a bad free + has no effect, and a malloc that encounters a bad address + caused by user overwrites will ignore the bad address by + dropping pointers and indices to all known memory. This may + be appropriate for programs that should continue if at all + possible in the face of programming errors, although they may + run out of memory because dropped memory is never reclaimed. + + If you don't like either of these options, you can define + CORRUPTION_ERROR_ACTION and USAGE_ERROR_ACTION to do anything + else. And if if you are sure that your program using malloc has + no errors or vulnerabilities, you can define INSECURE to 1, + which might (or might not) provide a small performance improvement. + + It is also possible to limit the maximum total allocatable + space, using malloc_set_footprint_limit. This is not + designed as a security feature in itself (calls to set limits + are not screened or privileged), but may be useful as one + aspect of a secure implementation. + + Thread-safety: NOT thread-safe unless USE_LOCKS defined non-zero + When USE_LOCKS is defined, each public call to malloc, free, + etc is surrounded with a lock. By default, this uses a plain + pthread mutex, win32 critical section, or a spin-lock if if + available for the platform and not disabled by setting + USE_SPIN_LOCKS=0. However, if USE_RECURSIVE_LOCKS is defined, + recursive versions are used instead (which are not required for + base functionality but may be needed in layered extensions). + Using a global lock is not especially fast, and can be a major + bottleneck. It is designed only to provide minimal protection + in concurrent environments, and to provide a basis for + extensions. If you are using malloc in a concurrent program, + consider instead using nedmalloc + (http://www.nedprod.com/programs/portable/nedmalloc/) or + ptmalloc (See http://www.malloc.de), which are derived from + versions of this malloc. + + System requirements: Any combination of MORECORE and/or MMAP/MUNMAP + This malloc can use unix sbrk or any emulation (invoked using + the CALL_MORECORE macro) and/or mmap/munmap or any emulation + (invoked using CALL_MMAP/CALL_MUNMAP) to get and release system + memory. On most unix systems, it tends to work best if both + MORECORE and MMAP are enabled. On Win32, it uses emulations + based on VirtualAlloc. It also uses common C library functions + like memset. + + Compliance: I believe it is compliant with the Single Unix Specification + (See http://www.unix.org). Also SVID/XPG, ANSI C, and probably + others as well. + +* Overview of algorithms + + This is not the fastest, most space-conserving, most portable, or + most tunable malloc ever written. However it is among the fastest + while also being among the most space-conserving, portable and + tunable. Consistent balance across these factors results in a good + general-purpose allocator for malloc-intensive programs. + + In most ways, this malloc is a best-fit allocator. Generally, it + chooses the best-fitting existing chunk for a request, with ties + broken in approximately least-recently-used order. (This strategy + normally maintains low fragmentation.) However, for requests less + than 256bytes, it deviates from best-fit when there is not an + exactly fitting available chunk by preferring to use space adjacent + to that used for the previous small request, as well as by breaking + ties in approximately most-recently-used order. (These enhance + locality of series of small allocations.) And for very large requests + (>= 256Kb by default), it relies on system memory mapping + facilities, if supported. (This helps avoid carrying around and + possibly fragmenting memory used only for large chunks.) + + All operations (except malloc_stats and mallinfo) have execution + times that are bounded by a constant factor of the number of bits in + a size_t, not counting any clearing in calloc or copying in realloc, + or actions surrounding MORECORE and MMAP that have times + proportional to the number of non-contiguous regions returned by + system allocation routines, which is often just 1. In real-time + applications, you can optionally suppress segment traversals using + NO_SEGMENT_TRAVERSAL, which assures bounded execution even when + system allocators return non-contiguous spaces, at the typical + expense of carrying around more memory and increased fragmentation. + + The implementation is not very modular and seriously overuses + macros. Perhaps someday all C compilers will do as good a job + inlining modular code as can now be done by brute-force expansion, + but now, enough of them seem not to. + + Some compilers issue a lot of warnings about code that is + dead/unreachable only on some platforms, and also about intentional + uses of negation on unsigned types. All known cases of each can be + ignored. + + For a longer but out of date high-level description, see + http://gee.cs.oswego.edu/dl/html/malloc.html + +* MSPACES + If MSPACES is defined, then in addition to malloc, free, etc., + this file also defines mspace_malloc, mspace_free, etc. These + are versions of malloc routines that take an "mspace" argument + obtained using create_mspace, to control all internal bookkeeping. + If ONLY_MSPACES is defined, only these versions are compiled. + So if you would like to use this allocator for only some allocations, + and your system malloc for others, you can compile with + ONLY_MSPACES and then do something like... + static mspace mymspace = create_mspace(0,0); // for example + #define mymalloc(bytes) mspace_malloc(mymspace, bytes) + + (Note: If you only need one instance of an mspace, you can instead + use "USE_DL_PREFIX" to relabel the global malloc.) + + You can similarly create thread-local allocators by storing + mspaces as thread-locals. For example: + static __thread mspace tlms = 0; + void* tlmalloc(size_t bytes) { + if (tlms == 0) tlms = create_mspace(0, 0); + return mspace_malloc(tlms, bytes); + } + void tlfree(void* mem) { mspace_free(tlms, mem); } + + Unless FOOTERS is defined, each mspace is completely independent. + You cannot allocate from one and free to another (although + conformance is only weakly checked, so usage errors are not always + caught). If FOOTERS is defined, then each chunk carries around a tag + indicating its originating mspace, and frees are directed to their + originating spaces. Normally, this requires use of locks. + + ------------------------- Compile-time options --------------------------- + +Be careful in setting #define values for numerical constants of type +size_t. On some systems, literal values are not automatically extended +to size_t precision unless they are explicitly casted. You can also +use the symbolic values MAX_SIZE_T, SIZE_T_ONE, etc below. + +WIN32 default: defined if _WIN32 defined + Defining WIN32 sets up defaults for MS environment and compilers. + Otherwise defaults are for unix. Beware that there seem to be some + cases where this malloc might not be a pure drop-in replacement for + Win32 malloc: Random-looking failures from Win32 GDI API's (eg; + SetDIBits()) may be due to bugs in some video driver implementations + when pixel buffers are malloc()ed, and the region spans more than + one VirtualAlloc()ed region. Because dlmalloc uses a small (64Kb) + default granularity, pixel buffers may straddle virtual allocation + regions more often than when using the Microsoft allocator. You can + avoid this by using VirtualAlloc() and VirtualFree() for all pixel + buffers rather than using malloc(). If this is not possible, + recompile this malloc with a larger DEFAULT_GRANULARITY. Note: + in cases where MSC and gcc (cygwin) are known to differ on WIN32, + conditions use _MSC_VER to distinguish them. + +DLMALLOC_EXPORT default: extern + Defines how public APIs are declared. If you want to export via a + Windows DLL, you might define this as + #define DLMALLOC_EXPORT extern __declspec(dllexport) + If you want a POSIX ELF shared object, you might use + #define DLMALLOC_EXPORT extern __attribute__((visibility("default"))) + +MALLOC_ALIGNMENT default: (size_t)(2 * sizeof(void *)) + Controls the minimum alignment for malloc'ed chunks. It must be a + power of two and at least 8, even on machines for which smaller + alignments would suffice. It may be defined as larger than this + though. Note however that code and data structures are optimized for + the case of 8-byte alignment. + +MSPACES default: 0 (false) + If true, compile in support for independent allocation spaces. + This is only supported if HAVE_MMAP is true. + +ONLY_MSPACES default: 0 (false) + If true, only compile in mspace versions, not regular versions. + +USE_LOCKS default: 0 (false) + Causes each call to each public routine to be surrounded with + pthread or WIN32 mutex lock/unlock. (If set true, this can be + overridden on a per-mspace basis for mspace versions.) If set to a + non-zero value other than 1, locks are used, but their + implementation is left out, so lock functions must be supplied manually, + as described below. + +USE_SPIN_LOCKS default: 1 iff USE_LOCKS and spin locks available + If true, uses custom spin locks for locking. This is currently + supported only gcc >= 4.1, older gccs on x86 platforms, and recent + MS compilers. Otherwise, posix locks or win32 critical sections are + used. + +USE_RECURSIVE_LOCKS default: not defined + If defined nonzero, uses recursive (aka reentrant) locks, otherwise + uses plain mutexes. This is not required for malloc proper, but may + be needed for layered allocators such as nedmalloc. + +LOCK_AT_FORK default: not defined + If defined nonzero, performs pthread_atfork upon initialization + to initialize child lock while holding parent lock. The implementation + assumes that pthread locks (not custom locks) are being used. In other + cases, you may need to customize the implementation. + +FOOTERS default: 0 + If true, provide extra checking and dispatching by placing + information in the footers of allocated chunks. This adds + space and time overhead. + +INSECURE default: 0 + If true, omit checks for usage errors and heap space overwrites. + +USE_DL_PREFIX default: NOT defined + Causes compiler to prefix all public routines with the string 'dl'. + This can be useful when you only want to use this malloc in one part + of a program, using your regular system malloc elsewhere. + +MALLOC_INSPECT_ALL default: NOT defined + If defined, compiles malloc_inspect_all and mspace_inspect_all, that + perform traversal of all heap space. Unless access to these + functions is otherwise restricted, you probably do not want to + include them in secure implementations. + +ABORT default: defined as abort() + Defines how to abort on failed checks. On most systems, a failed + check cannot die with an "assert" or even print an informative + message, because the underlying print routines in turn call malloc, + which will fail again. Generally, the best policy is to simply call + abort(). It's not very useful to do more than this because many + errors due to overwriting will show up as address faults (null, odd + addresses etc) rather than malloc-triggered checks, so will also + abort. Also, most compilers know that abort() does not return, so + can better optimize code conditionally calling it. + +PROCEED_ON_ERROR default: defined as 0 (false) + Controls whether detected bad addresses cause them to bypassed + rather than aborting. If set, detected bad arguments to free and + realloc are ignored. And all bookkeeping information is zeroed out + upon a detected overwrite of freed heap space, thus losing the + ability to ever return it from malloc again, but enabling the + application to proceed. If PROCEED_ON_ERROR is defined, the + static variable malloc_corruption_error_count is compiled in + and can be examined to see if errors have occurred. This option + generates slower code than the default abort policy. + +DEBUG default: NOT defined + The DEBUG setting is mainly intended for people trying to modify + this code or diagnose problems when porting to new platforms. + However, it may also be able to better isolate user errors than just + using runtime checks. The assertions in the check routines spell + out in more detail the assumptions and invariants underlying the + algorithms. The checking is fairly extensive, and will slow down + execution noticeably. Calling malloc_stats or mallinfo with DEBUG + set will attempt to check every non-mmapped allocated and free chunk + in the course of computing the summaries. + +ABORT_ON_ASSERT_FAILURE default: defined as 1 (true) + Debugging assertion failures can be nearly impossible if your + version of the assert macro causes malloc to be called, which will + lead to a cascade of further failures, blowing the runtime stack. + ABORT_ON_ASSERT_FAILURE cause assertions failures to call abort(), + which will usually make debugging easier. + +MALLOC_FAILURE_ACTION default: sets errno to ENOMEM, or no-op on win32 + The action to take before "return 0" when malloc fails to be able to + return memory because there is none available. + +HAVE_MORECORE default: 1 (true) unless win32 or ONLY_MSPACES + True if this system supports sbrk or an emulation of it. + +MORECORE default: sbrk + The name of the sbrk-style system routine to call to obtain more + memory. See below for guidance on writing custom MORECORE + functions. The type of the argument to sbrk/MORECORE varies across + systems. It cannot be size_t, because it supports negative + arguments, so it is normally the signed type of the same width as + size_t (sometimes declared as "intptr_t"). It doesn't much matter + though. Internally, we only call it with arguments less than half + the max value of a size_t, which should work across all reasonable + possibilities, although sometimes generating compiler warnings. + +MORECORE_CONTIGUOUS default: 1 (true) if HAVE_MORECORE + If true, take advantage of fact that consecutive calls to MORECORE + with positive arguments always return contiguous increasing + addresses. This is true of unix sbrk. It does not hurt too much to + set it true anyway, since malloc copes with non-contiguities. + Setting it false when definitely non-contiguous saves time + and possibly wasted space it would take to discover this though. + +MORECORE_CANNOT_TRIM default: NOT defined + True if MORECORE cannot release space back to the system when given + negative arguments. This is generally necessary only if you are + using a hand-crafted MORECORE function that cannot handle negative + arguments. + +NO_SEGMENT_TRAVERSAL default: 0 + If non-zero, suppresses traversals of memory segments + returned by either MORECORE or CALL_MMAP. This disables + merging of segments that are contiguous, and selectively + releasing them to the OS if unused, but bounds execution times. + +HAVE_MMAP default: 1 (true) + True if this system supports mmap or an emulation of it. If so, and + HAVE_MORECORE is not true, MMAP is used for all system + allocation. If set and HAVE_MORECORE is true as well, MMAP is + primarily used to directly allocate very large blocks. It is also + used as a backup strategy in cases where MORECORE fails to provide + space from system. Note: A single call to MUNMAP is assumed to be + able to unmap memory that may have be allocated using multiple calls + to MMAP, so long as they are adjacent. + +HAVE_MREMAP default: 1 on linux, else 0 + If true realloc() uses mremap() to re-allocate large blocks and + extend or shrink allocation spaces. + +MMAP_CLEARS default: 1 except on WINCE. + True if mmap clears memory so calloc doesn't need to. This is true + for standard unix mmap using /dev/zero and on WIN32 except for WINCE. + +USE_BUILTIN_FFS default: 0 (i.e., not used) + Causes malloc to use the builtin ffs() function to compute indices. + Some compilers may recognize and intrinsify ffs to be faster than the + supplied C version. Also, the case of x86 using gcc is special-cased + to an asm instruction, so is already as fast as it can be, and so + this setting has no effect. Similarly for Win32 under recent MS compilers. + (On most x86s, the asm version is only slightly faster than the C version.) + +malloc_getpagesize default: derive from system includes, or 4096. + The system page size. To the extent possible, this malloc manages + memory from the system in page-size units. This may be (and + usually is) a function rather than a constant. This is ignored + if WIN32, where page size is determined using getSystemInfo during + initialization. + +USE_DEV_RANDOM default: 0 (i.e., not used) + Causes malloc to use /dev/random to initialize secure magic seed for + stamping footers. Otherwise, the current time is used. + +NO_MALLINFO default: 0 + If defined, don't compile "mallinfo". This can be a simple way + of dealing with mismatches between system declarations and + those in this file. + +MALLINFO_FIELD_TYPE default: size_t + The type of the fields in the mallinfo struct. This was originally + defined as "int" in SVID etc, but is more usefully defined as + size_t. The value is used only if HAVE_USR_INCLUDE_MALLOC_H is not set + +NO_MALLOC_STATS default: 0 + If defined, don't compile "malloc_stats". This avoids calls to + fprintf and bringing in stdio dependencies you might not want. + +REALLOC_ZERO_BYTES_FREES default: not defined + This should be set if a call to realloc with zero bytes should + be the same as a call to free. Some people think it should. Otherwise, + since this malloc returns a unique pointer for malloc(0), so does + realloc(p, 0). + +LACKS_UNISTD_H, LACKS_FCNTL_H, LACKS_SYS_PARAM_H, LACKS_SYS_MMAN_H +LACKS_STRINGS_H, LACKS_STRING_H, LACKS_SYS_TYPES_H, LACKS_ERRNO_H +LACKS_STDLIB_H LACKS_SCHED_H LACKS_TIME_H default: NOT defined unless on WIN32 + Define these if your system does not have these header files. + You might need to manually insert some of the declarations they provide. + +DEFAULT_GRANULARITY default: page size if MORECORE_CONTIGUOUS, + system_info.dwAllocationGranularity in WIN32, + otherwise 64K. + Also settable using mallopt(M_GRANULARITY, x) + The unit for allocating and deallocating memory from the system. On + most systems with contiguous MORECORE, there is no reason to + make this more than a page. However, systems with MMAP tend to + either require or encourage larger granularities. You can increase + this value to prevent system allocation functions to be called so + often, especially if they are slow. The value must be at least one + page and must be a power of two. Setting to 0 causes initialization + to either page size or win32 region size. (Note: In previous + versions of malloc, the equivalent of this option was called + "TOP_PAD") + +DEFAULT_TRIM_THRESHOLD default: 2MB + Also settable using mallopt(M_TRIM_THRESHOLD, x) + The maximum amount of unused top-most memory to keep before + releasing via malloc_trim in free(). Automatic trimming is mainly + useful in long-lived programs using contiguous MORECORE. Because + trimming via sbrk can be slow on some systems, and can sometimes be + wasteful (in cases where programs immediately afterward allocate + more large chunks) the value should be high enough so that your + overall system performance would improve by releasing this much + memory. As a rough guide, you might set to a value close to the + average size of a process (program) running on your system. + Releasing this much memory would allow such a process to run in + memory. Generally, it is worth tuning trim thresholds when a + program undergoes phases where several large chunks are allocated + and released in ways that can reuse each other's storage, perhaps + mixed with phases where there are no such chunks at all. The trim + value must be greater than page size to have any useful effect. To + disable trimming completely, you can set to MAX_SIZE_T. Note that the trick + some people use of mallocing a huge space and then freeing it at + program startup, in an attempt to reserve system memory, doesn't + have the intended effect under automatic trimming, since that memory + will immediately be returned to the system. + +DEFAULT_MMAP_THRESHOLD default: 256K + Also settable using mallopt(M_MMAP_THRESHOLD, x) + The request size threshold for using MMAP to directly service a + request. Requests of at least this size that cannot be allocated + using already-existing space will be serviced via mmap. (If enough + normal freed space already exists it is used instead.) Using mmap + segregates relatively large chunks of memory so that they can be + individually obtained and released from the host system. A request + serviced through mmap is never reused by any other request (at least + not directly; the system may just so happen to remap successive + requests to the same locations). Segregating space in this way has + the benefits that: Mmapped space can always be individually released + back to the system, which helps keep the system level memory demands + of a long-lived program low. Also, mapped memory doesn't become + `locked' between other chunks, as can happen with normally allocated + chunks, which means that even trimming via malloc_trim would not + release them. However, it has the disadvantage that the space + cannot be reclaimed, consolidated, and then used to service later + requests, as happens with normal chunks. The advantages of mmap + nearly always outweigh disadvantages for "large" chunks, but the + value of "large" may vary across systems. The default is an + empirically derived value that works well in most systems. You can + disable mmap by setting to MAX_SIZE_T. + +MAX_RELEASE_CHECK_RATE default: 4095 unless not HAVE_MMAP + The number of consolidated frees between checks to release + unused segments when freeing. When using non-contiguous segments, + especially with multiple mspaces, checking only for topmost space + doesn't always suffice to trigger trimming. To compensate for this, + free() will, with a period of MAX_RELEASE_CHECK_RATE (or the + current number of segments, if greater) try to release unused + segments to the OS when freeing chunks that result in + consolidation. The best value for this parameter is a compromise + between slowing down frees with relatively costly checks that + rarely trigger versus holding on to unused memory. To effectively + disable, set to MAX_SIZE_T. This may lead to a very slight speed + improvement at the expense of carrying around more memory. +*/ + +/* Version identifier to allow people to support multiple versions */ +#ifndef DLMALLOC_VERSION +#define DLMALLOC_VERSION 20806 +#endif /* DLMALLOC_VERSION */ + +#ifndef DLMALLOC_EXPORT +#define DLMALLOC_EXPORT extern +#endif + +#ifndef WIN32 +#ifdef _WIN32 +#define WIN32 1 +#endif /* _WIN32 */ +#ifdef _WIN32_WCE +#define LACKS_FCNTL_H +#define WIN32 1 +#endif /* _WIN32_WCE */ +#endif /* WIN32 */ +#ifdef WIN32 +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#include <tchar.h> +#define HAVE_MMAP 1 +#define HAVE_MORECORE 0 +#define LACKS_UNISTD_H +#define LACKS_SYS_PARAM_H +#define LACKS_SYS_MMAN_H +#define LACKS_STRING_H +#define LACKS_STRINGS_H +#define LACKS_SYS_TYPES_H +#define LACKS_ERRNO_H +#define LACKS_SCHED_H +#ifndef MALLOC_FAILURE_ACTION +#define MALLOC_FAILURE_ACTION +#endif /* MALLOC_FAILURE_ACTION */ +#ifndef MMAP_CLEARS +#ifdef _WIN32_WCE /* WINCE reportedly does not clear */ +#define MMAP_CLEARS 0 +#else +#define MMAP_CLEARS 1 +#endif /* _WIN32_WCE */ +#endif /*MMAP_CLEARS */ +#endif /* WIN32 */ + +#if defined(DARWIN) || defined(_DARWIN) +/* Mac OSX docs advise not to use sbrk; it seems better to use mmap */ +#ifndef HAVE_MORECORE +#define HAVE_MORECORE 0 +#define HAVE_MMAP 1 +/* OSX allocators provide 16 byte alignment */ +#ifndef MALLOC_ALIGNMENT +#define MALLOC_ALIGNMENT ((size_t)16U) +#endif +#endif /* HAVE_MORECORE */ +#endif /* DARWIN */ + +#ifndef LACKS_SYS_TYPES_H +#include <sys/types.h> /* For size_t */ +#endif /* LACKS_SYS_TYPES_H */ + +/* The maximum possible size_t value has all bits set */ +#define MAX_SIZE_T (~(size_t)0) + +#ifndef USE_LOCKS /* ensure true if spin or recursive locks set */ +#define USE_LOCKS ((defined(USE_SPIN_LOCKS) && USE_SPIN_LOCKS != 0) || \ + (defined(USE_RECURSIVE_LOCKS) && USE_RECURSIVE_LOCKS != 0)) +#endif /* USE_LOCKS */ + +#if USE_LOCKS /* Spin locks for gcc >= 4.1, older gcc on x86, MSC >= 1310 */ +#if ((defined(__GNUC__) && \ + ((__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)) || \ + defined(__i386__) || defined(__x86_64__))) || \ + (defined(_MSC_VER) && _MSC_VER>=1310)) +#ifndef USE_SPIN_LOCKS +#define USE_SPIN_LOCKS 1 +#endif /* USE_SPIN_LOCKS */ +#elif USE_SPIN_LOCKS +#error "USE_SPIN_LOCKS defined without implementation" +#endif /* ... locks available... */ +#elif !defined(USE_SPIN_LOCKS) +#define USE_SPIN_LOCKS 0 +#endif /* USE_LOCKS */ + +#ifndef ONLY_MSPACES +#define ONLY_MSPACES 0 +#endif /* ONLY_MSPACES */ +#ifndef MSPACES +#if ONLY_MSPACES +#define MSPACES 1 +#else /* ONLY_MSPACES */ +#define MSPACES 0 +#endif /* ONLY_MSPACES */ +#endif /* MSPACES */ +#ifndef MALLOC_ALIGNMENT +#define MALLOC_ALIGNMENT ((size_t)(2 * sizeof(void *))) +#endif /* MALLOC_ALIGNMENT */ +#ifndef FOOTERS +#define FOOTERS 0 +#endif /* FOOTERS */ +#ifndef ABORT +#define ABORT abort() +#endif /* ABORT */ +#ifndef ABORT_ON_ASSERT_FAILURE +#define ABORT_ON_ASSERT_FAILURE 1 +#endif /* ABORT_ON_ASSERT_FAILURE */ +#ifndef PROCEED_ON_ERROR +#define PROCEED_ON_ERROR 0 +#endif /* PROCEED_ON_ERROR */ + +#ifndef INSECURE +#define INSECURE 0 +#endif /* INSECURE */ +#ifndef MALLOC_INSPECT_ALL +#define MALLOC_INSPECT_ALL 0 +#endif /* MALLOC_INSPECT_ALL */ +#ifndef HAVE_MMAP +#define HAVE_MMAP 1 +#endif /* HAVE_MMAP */ +#ifndef MMAP_CLEARS +#define MMAP_CLEARS 1 +#endif /* MMAP_CLEARS */ +#ifndef HAVE_MREMAP +#ifdef linux +#define HAVE_MREMAP 1 +#define _GNU_SOURCE /* Turns on mremap() definition */ +#else /* linux */ +#define HAVE_MREMAP 0 +#endif /* linux */ +#endif /* HAVE_MREMAP */ +#ifndef MALLOC_FAILURE_ACTION +#define MALLOC_FAILURE_ACTION errno = ENOMEM; +#endif /* MALLOC_FAILURE_ACTION */ +#ifndef HAVE_MORECORE +#if ONLY_MSPACES +#define HAVE_MORECORE 0 +#else /* ONLY_MSPACES */ +#define HAVE_MORECORE 1 +#endif /* ONLY_MSPACES */ +#endif /* HAVE_MORECORE */ +#if !HAVE_MORECORE +#define MORECORE_CONTIGUOUS 0 +#else /* !HAVE_MORECORE */ +#define MORECORE_DEFAULT sbrk +#ifndef MORECORE_CONTIGUOUS +#define MORECORE_CONTIGUOUS 1 +#endif /* MORECORE_CONTIGUOUS */ +#endif /* HAVE_MORECORE */ +#ifndef DEFAULT_GRANULARITY +#if (MORECORE_CONTIGUOUS || defined(WIN32)) +#define DEFAULT_GRANULARITY (0) /* 0 means to compute in init_mparams */ +#else /* MORECORE_CONTIGUOUS */ +#define DEFAULT_GRANULARITY ((size_t)64U * (size_t)1024U) +#endif /* MORECORE_CONTIGUOUS */ +#endif /* DEFAULT_GRANULARITY */ +#ifndef DEFAULT_TRIM_THRESHOLD +#ifndef MORECORE_CANNOT_TRIM +#define DEFAULT_TRIM_THRESHOLD ((size_t)2U * (size_t)1024U * (size_t)1024U) +#else /* MORECORE_CANNOT_TRIM */ +#define DEFAULT_TRIM_THRESHOLD MAX_SIZE_T +#endif /* MORECORE_CANNOT_TRIM */ +#endif /* DEFAULT_TRIM_THRESHOLD */ +#ifndef DEFAULT_MMAP_THRESHOLD +#if HAVE_MMAP +#define DEFAULT_MMAP_THRESHOLD ((size_t)256U * (size_t)1024U) +#else /* HAVE_MMAP */ +#define DEFAULT_MMAP_THRESHOLD MAX_SIZE_T +#endif /* HAVE_MMAP */ +#endif /* DEFAULT_MMAP_THRESHOLD */ +#ifndef MAX_RELEASE_CHECK_RATE +#if HAVE_MMAP +#define MAX_RELEASE_CHECK_RATE 4095 +#else +#define MAX_RELEASE_CHECK_RATE MAX_SIZE_T +#endif /* HAVE_MMAP */ +#endif /* MAX_RELEASE_CHECK_RATE */ +#ifndef USE_BUILTIN_FFS +#define USE_BUILTIN_FFS 0 +#endif /* USE_BUILTIN_FFS */ +#ifndef USE_DEV_RANDOM +#define USE_DEV_RANDOM 0 +#endif /* USE_DEV_RANDOM */ +#ifndef NO_MALLINFO +#define NO_MALLINFO 0 +#endif /* NO_MALLINFO */ +#ifndef MALLINFO_FIELD_TYPE +#define MALLINFO_FIELD_TYPE size_t +#endif /* MALLINFO_FIELD_TYPE */ +#ifndef NO_MALLOC_STATS +#define NO_MALLOC_STATS 0 +#endif /* NO_MALLOC_STATS */ +#ifndef NO_SEGMENT_TRAVERSAL +#define NO_SEGMENT_TRAVERSAL 0 +#endif /* NO_SEGMENT_TRAVERSAL */ + +/* + mallopt tuning options. SVID/XPG defines four standard parameter + numbers for mallopt, normally defined in malloc.h. None of these + are used in this malloc, so setting them has no effect. But this + malloc does support the following options. +*/ + +#define M_TRIM_THRESHOLD (-1) +#define M_GRANULARITY (-2) +#define M_MMAP_THRESHOLD (-3) + +/* ------------------------ Mallinfo declarations ------------------------ */ + +#if !NO_MALLINFO +/* + This version of malloc supports the standard SVID/XPG mallinfo + routine that returns a struct containing usage properties and + statistics. It should work on any system that has a + /usr/include/malloc.h defining struct mallinfo. The main + declaration needed is the mallinfo struct that is returned (by-copy) + by mallinfo(). The malloinfo struct contains a bunch of fields that + are not even meaningful in this version of malloc. These fields are + are instead filled by mallinfo() with other numbers that might be of + interest. + + HAVE_USR_INCLUDE_MALLOC_H should be set if you have a + /usr/include/malloc.h file that includes a declaration of struct + mallinfo. If so, it is included; else a compliant version is + declared below. These must be precisely the same for mallinfo() to + work. The original SVID version of this struct, defined on most + systems with mallinfo, declares all fields as ints. But some others + define as unsigned long. If your system defines the fields using a + type of different width than listed here, you MUST #include your + system version and #define HAVE_USR_INCLUDE_MALLOC_H. +*/ + +/* #define HAVE_USR_INCLUDE_MALLOC_H */ + +#ifdef HAVE_USR_INCLUDE_MALLOC_H +#include "/usr/include/malloc.h" +#else /* HAVE_USR_INCLUDE_MALLOC_H */ +#ifndef STRUCT_MALLINFO_DECLARED +/* HP-UX (and others?) redefines mallinfo unless _STRUCT_MALLINFO is defined */ +#define _STRUCT_MALLINFO +#define STRUCT_MALLINFO_DECLARED 1 +struct mallinfo { + MALLINFO_FIELD_TYPE arena; /* non-mmapped space allocated from system */ + MALLINFO_FIELD_TYPE ordblks; /* number of free chunks */ + MALLINFO_FIELD_TYPE smblks; /* always 0 */ + MALLINFO_FIELD_TYPE hblks; /* always 0 */ + MALLINFO_FIELD_TYPE hblkhd; /* space in mmapped regions */ + MALLINFO_FIELD_TYPE usmblks; /* maximum total allocated space */ + MALLINFO_FIELD_TYPE fsmblks; /* always 0 */ + MALLINFO_FIELD_TYPE uordblks; /* total allocated space */ + MALLINFO_FIELD_TYPE fordblks; /* total free space */ + MALLINFO_FIELD_TYPE keepcost; /* releasable (via malloc_trim) space */ +}; +#endif /* STRUCT_MALLINFO_DECLARED */ +#endif /* HAVE_USR_INCLUDE_MALLOC_H */ +#endif /* NO_MALLINFO */ + +/* + Try to persuade compilers to inline. The most critical functions for + inlining are defined as macros, so these aren't used for them. +*/ + +#ifndef FORCEINLINE + #if defined(__GNUC__) +#define FORCEINLINE __inline __attribute__ ((always_inline)) + #elif defined(_MSC_VER) + #define FORCEINLINE __forceinline + #endif +#endif +#ifndef NOINLINE + #if defined(__GNUC__) + #define NOINLINE __attribute__ ((noinline)) + #elif defined(_MSC_VER) + #define NOINLINE __declspec(noinline) + #else + #define NOINLINE + #endif +#endif + +#ifdef __cplusplus +extern "C" { +#ifndef FORCEINLINE + #define FORCEINLINE inline +#endif +#endif /* __cplusplus */ +#ifndef FORCEINLINE + #define FORCEINLINE +#endif + +# define preconcat(x,y) x ## y +# define concat(x,y) preconcat(x,y) + +#ifdef MSPACE_PREFIX +#define mspace_prefix(f) concat(MSPACE_PREFIX,f) +#define mspace_malloc mspace_prefix(mspace_malloc) +#define mspace_free mspace_prefix(mspace_free) +#define mspace_calloc mspace_prefix(mspace_calloc) +#define mspace_realloc mspace_prefix(mspace_realloc) +#define mspace_realloc_in_place mspace_prefix(mspace_realloc_in_place) +#define mspace_memalign mspace_prefix(mspace_memalign) +#define mspace_aligned_alloc mspace_prefix(mspace_aligned_alloc) +#define mspace_posix_memalign mspace_prefix(mspace_posix_memalign) +#define mspace_independent_calloc mspace_prefix(mspace_independent_calloc) +#define mspace_independent_comalloc mspace_prefix(mspace_independent_comalloc) +#define mspace_bulk_free mspace_prefix(mspace_bulk_free) +#define mspace_usable_size mspace_prefix(mspace_usable_size) +#define mspace_malloc_stats mspace_prefix(mspace_malloc_stats) +#define mspace_trim mspace_prefix(mspace_trim) +#define mspace_footprint mspace_prefix(mspace_footprint) +#define mspace_max_footprint mspace_prefix(mspace_max_footprint) +#define mspace_footprint_limit mspace_prefix(mspace_footprint_limit) +#define mspace_set_footprint_limit mspace_prefix(mspace_set_footprint_limit) +#define mspace_inspect_all mspace_prefix(mspace_inspect_all) +#define create_mspace mspace_prefix(create_mspace) +#define create_mspace_with_base mspace_prefix(create_mspace_with_base) +#define destroy_mspace mspace_prefix(destroy_mspace) +#define mspace_least_addr mspace_prefix(mspace_least_addr) +#define mspace_mallopt mspace_prefix(mspace_mallopt) +#define mspace_track_large_chunks mspace_prefix(mspace_track_large_chunks) +#endif + +#if !ONLY_MSPACES + +/* ------------------- Declarations of public routines ------------------- */ + +#ifndef USE_DL_PREFIX +#define dlcalloc calloc +#define dlfree free +#define dlmalloc malloc +#define dlmemalign memalign +#define dlposix_memalign posix_memalign +#define dlaligned_alloc aligned_alloc +#define dlrealloc realloc +#define dlrealloc_in_place realloc_in_place +#define dlvalloc valloc +#define dlpvalloc pvalloc +#define dlmallinfo mallinfo +#define dlmallopt mallopt +#define dlmalloc_trim malloc_trim +#define dlmalloc_stats malloc_stats +#define dlmalloc_usable_size malloc_usable_size +#define dlmalloc_footprint malloc_footprint +#define dlmalloc_max_footprint malloc_max_footprint +#define dlmalloc_footprint_limit malloc_footprint_limit +#define dlmalloc_set_footprint_limit malloc_set_footprint_limit +#define dlmalloc_inspect_all malloc_inspect_all +#define dlindependent_calloc independent_calloc +#define dlindependent_comalloc independent_comalloc +#define dlbulk_free bulk_free +#endif /* USE_DL_PREFIX */ + +/* + malloc(size_t n) + Returns a pointer to a newly allocated chunk of at least n bytes, or + null if no space is available, in which case errno is set to ENOMEM + on ANSI C systems. + + If n is zero, malloc returns a minimum-sized chunk. (The minimum + size is 16 bytes on most 32bit systems, and 32 bytes on 64bit + systems.) Note that size_t is an unsigned type, so calls with + arguments that would be negative if signed are interpreted as + requests for huge amounts of space, which will often fail. The + maximum supported value of n differs across systems, but is in all + cases less than the maximum representable value of a size_t. +*/ +DLMALLOC_EXPORT void* dlmalloc(size_t); + +/* + free(void* p) + Releases the chunk of memory pointed to by p, that had been previously + allocated using malloc or a related routine such as realloc. + It has no effect if p is null. If p was not malloced or already + freed, free(p) will by default cause the current program to abort. +*/ +DLMALLOC_EXPORT void dlfree(void*); + +/* + calloc(size_t n_elements, size_t element_size); + Returns a pointer to n_elements * element_size bytes, with all locations + set to zero. +*/ +DLMALLOC_EXPORT void* dlcalloc(size_t, size_t); + +/* + realloc(void* p, size_t n) + Returns a pointer to a chunk of size n that contains the same data + as does chunk p up to the minimum of (n, p's size) bytes, or null + if no space is available. + + The returned pointer may or may not be the same as p. The algorithm + prefers extending p in most cases when possible, otherwise it + employs the equivalent of a malloc-copy-free sequence. + + If p is null, realloc is equivalent to malloc. + + If space is not available, realloc returns null, errno is set (if on + ANSI) and p is NOT freed. + + if n is for fewer bytes than already held by p, the newly unused + space is lopped off and freed if possible. realloc with a size + argument of zero (re)allocates a minimum-sized chunk. + + The old unix realloc convention of allowing the last-free'd chunk + to be used as an argument to realloc is not supported. +*/ +DLMALLOC_EXPORT void* dlrealloc(void*, size_t); + +/* + realloc_in_place(void* p, size_t n) + Resizes the space allocated for p to size n, only if this can be + done without moving p (i.e., only if there is adjacent space + available if n is greater than p's current allocated size, or n is + less than or equal to p's size). This may be used instead of plain + realloc if an alternative allocation strategy is needed upon failure + to expand space; for example, reallocation of a buffer that must be + memory-aligned or cleared. You can use realloc_in_place to trigger + these alternatives only when needed. + + Returns p if successful; otherwise null. +*/ +DLMALLOC_EXPORT void* dlrealloc_in_place(void*, size_t); + +/* + memalign(size_t alignment, size_t n); + Returns a pointer to a newly allocated chunk of n bytes, aligned + in accord with the alignment argument. + + The alignment argument should be a power of two. If the argument is + not a power of two, the nearest greater power is used. + 8-byte alignment is guaranteed by normal malloc calls, so don't + bother calling memalign with an argument of 8 or less. + + Overreliance on memalign is a sure way to fragment space. +*/ +DLMALLOC_EXPORT void* dlmemalign(size_t, size_t); + +/* + int posix_memalign(void** pp, size_t alignment, size_t n); + Allocates a chunk of n bytes, aligned in accord with the alignment + argument. Differs from memalign only in that it (1) assigns the + allocated memory to *pp rather than returning it, (2) fails and + returns EINVAL if the alignment is not a power of two (3) fails and + returns ENOMEM if memory cannot be allocated. +*/ +DLMALLOC_EXPORT int dlposix_memalign(void**, size_t, size_t); + +/* + aligned_alloc(size_t alignment, size_t size); + The function aligned_alloc() is the same as memalign(), except for the added + restriction that size should be a multiple of alignment. +*/ +DLMALLOC_EXPORT void *dlaligned_alloc(size_t alignment, size_t size); + +/* + valloc(size_t n); + Equivalent to memalign(pagesize, n), where pagesize is the page + size of the system. If the pagesize is unknown, 4096 is used. +*/ +DLMALLOC_EXPORT void* dlvalloc(size_t); + +/* + mallopt(int parameter_number, int parameter_value) + Sets tunable parameters The format is to provide a + (parameter-number, parameter-value) pair. mallopt then sets the + corresponding parameter to the argument value if it can (i.e., so + long as the value is meaningful), and returns 1 if successful else + 0. To workaround the fact that mallopt is specified to use int, + not size_t parameters, the value -1 is specially treated as the + maximum unsigned size_t value. + + SVID/XPG/ANSI defines four standard param numbers for mallopt, + normally defined in malloc.h. None of these are use in this malloc, + so setting them has no effect. But this malloc also supports other + options in mallopt. See below for details. Briefly, supported + parameters are as follows (listed defaults are for "typical" + configurations). + + Symbol param # default allowed param values + M_TRIM_THRESHOLD -1 2*1024*1024 any (-1 disables) + M_GRANULARITY -2 page size any power of 2 >= page size + M_MMAP_THRESHOLD -3 256*1024 any (or 0 if no MMAP support) +*/ +DLMALLOC_EXPORT int dlmallopt(int, int); + +/* + malloc_footprint(); + Returns the number of bytes obtained from the system. The total + number of bytes allocated by malloc, realloc etc., is less than this + value. Unlike mallinfo, this function returns only a precomputed + result, so can be called frequently to monitor memory consumption. + Even if locks are otherwise defined, this function does not use them, + so results might not be up to date. +*/ +DLMALLOC_EXPORT size_t dlmalloc_footprint(void); + +/* + malloc_max_footprint(); + Returns the maximum number of bytes obtained from the system. This + value will be greater than current footprint if deallocated space + has been reclaimed by the system. The peak number of bytes allocated + by malloc, realloc etc., is less than this value. Unlike mallinfo, + this function returns only a precomputed result, so can be called + frequently to monitor memory consumption. Even if locks are + otherwise defined, this function does not use them, so results might + not be up to date. +*/ +DLMALLOC_EXPORT size_t dlmalloc_max_footprint(void); + +/* + malloc_footprint_limit(); + Returns the number of bytes that the heap is allowed to obtain from + the system, returning the last value returned by + malloc_set_footprint_limit, or the maximum size_t value if + never set. The returned value reflects a permission. There is no + guarantee that this number of bytes can actually be obtained from + the system. +*/ +DLMALLOC_EXPORT size_t dlmalloc_footprint_limit(); + +/* + malloc_set_footprint_limit(); + Sets the maximum number of bytes to obtain from the system, causing + failure returns from malloc and related functions upon attempts to + exceed this value. The argument value may be subject to page + rounding to an enforceable limit; this actual value is returned. + Using an argument of the maximum possible size_t effectively + disables checks. If the argument is less than or equal to the + current malloc_footprint, then all future allocations that require + additional system memory will fail. However, invocation cannot + retroactively deallocate existing used memory. +*/ +DLMALLOC_EXPORT size_t dlmalloc_set_footprint_limit(size_t bytes); + +#if MALLOC_INSPECT_ALL +/* + malloc_inspect_all(void(*handler)(void *start, + void *end, + size_t used_bytes, + void* callback_arg), + void* arg); + Traverses the heap and calls the given handler for each managed + region, skipping all bytes that are (or may be) used for bookkeeping + purposes. Traversal does not include include chunks that have been + directly memory mapped. Each reported region begins at the start + address, and continues up to but not including the end address. The + first used_bytes of the region contain allocated data. If + used_bytes is zero, the region is unallocated. The handler is + invoked with the given callback argument. If locks are defined, they + are held during the entire traversal. It is a bad idea to invoke + other malloc functions from within the handler. + + For example, to count the number of in-use chunks with size greater + than 1000, you could write: + static int count = 0; + void count_chunks(void* start, void* end, size_t used, void* arg) { + if (used >= 1000) ++count; + } + then: + malloc_inspect_all(count_chunks, NULL); + + malloc_inspect_all is compiled only if MALLOC_INSPECT_ALL is defined. +*/ +DLMALLOC_EXPORT void dlmalloc_inspect_all(void(*handler)(void*, void *, size_t, void*), + void* arg); + +#endif /* MALLOC_INSPECT_ALL */ + +#if !NO_MALLINFO +/* + mallinfo() + Returns (by copy) a struct containing various summary statistics: + + arena: current total non-mmapped bytes allocated from system + ordblks: the number of free chunks + smblks: always zero. + hblks: current number of mmapped regions + hblkhd: total bytes held in mmapped regions + usmblks: the maximum total allocated space. This will be greater + than current total if trimming has occurred. + fsmblks: always zero + uordblks: current total allocated space (normal or mmapped) + fordblks: total free space + keepcost: the maximum number of bytes that could ideally be released + back to system via malloc_trim. ("ideally" means that + it ignores page restrictions etc.) + + Because these fields are ints, but internal bookkeeping may + be kept as longs, the reported values may wrap around zero and + thus be inaccurate. +*/ +DLMALLOC_EXPORT struct mallinfo dlmallinfo(void); +#endif /* NO_MALLINFO */ + +/* + independent_calloc(size_t n_elements, size_t element_size, void* chunks[]); + + independent_calloc is similar to calloc, but instead of returning a + single cleared space, it returns an array of pointers to n_elements + independent elements that can hold contents of size elem_size, each + of which starts out cleared, and can be independently freed, + realloc'ed etc. The elements are guaranteed to be adjacently + allocated (this is not guaranteed to occur with multiple callocs or + mallocs), which may also improve cache locality in some + applications. + + The "chunks" argument is optional (i.e., may be null, which is + probably the most typical usage). If it is null, the returned array + is itself dynamically allocated and should also be freed when it is + no longer needed. Otherwise, the chunks array must be of at least + n_elements in length. It is filled in with the pointers to the + chunks. + + In either case, independent_calloc returns this pointer array, or + null if the allocation failed. If n_elements is zero and "chunks" + is null, it returns a chunk representing an array with zero elements + (which should be freed if not wanted). + + Each element must be freed when it is no longer needed. This can be + done all at once using bulk_free. + + independent_calloc simplifies and speeds up implementations of many + kinds of pools. It may also be useful when constructing large data + structures that initially have a fixed number of fixed-sized nodes, + but the number is not known at compile time, and some of the nodes + may later need to be freed. For example: + + struct Node { int item; struct Node* next; }; + + struct Node* build_list() { + struct Node** pool; + int n = read_number_of_nodes_needed(); + if (n <= 0) return 0; + pool = (struct Node**)(independent_calloc(n, sizeof(struct Node), 0); + if (pool == 0) die(); + // organize into a linked list... + struct Node* first = pool[0]; + for (i = 0; i < n-1; ++i) + pool[i]->next = pool[i+1]; + free(pool); // Can now free the array (or not, if it is needed later) + return first; + } +*/ +DLMALLOC_EXPORT void** dlindependent_calloc(size_t, size_t, void**); + +/* + independent_comalloc(size_t n_elements, size_t sizes[], void* chunks[]); + + independent_comalloc allocates, all at once, a set of n_elements + chunks with sizes indicated in the "sizes" array. It returns + an array of pointers to these elements, each of which can be + independently freed, realloc'ed etc. The elements are guaranteed to + be adjacently allocated (this is not guaranteed to occur with + multiple callocs or mallocs), which may also improve cache locality + in some applications. + + The "chunks" argument is optional (i.e., may be null). If it is null + the returned array is itself dynamically allocated and should also + be freed when it is no longer needed. Otherwise, the chunks array + must be of at least n_elements in length. It is filled in with the + pointers to the chunks. + + In either case, independent_comalloc returns this pointer array, or + null if the allocation failed. If n_elements is zero and chunks is + null, it returns a chunk representing an array with zero elements + (which should be freed if not wanted). + + Each element must be freed when it is no longer needed. This can be + done all at once using bulk_free. + + independent_comallac differs from independent_calloc in that each + element may have a different size, and also that it does not + automatically clear elements. + + independent_comalloc can be used to speed up allocation in cases + where several structs or objects must always be allocated at the + same time. For example: + + struct Head { ... } + struct Foot { ... } + + void send_message(char* msg) { + int msglen = strlen(msg); + size_t sizes[3] = { sizeof(struct Head), msglen, sizeof(struct Foot) }; + void* chunks[3]; + if (independent_comalloc(3, sizes, chunks) == 0) + die(); + struct Head* head = (struct Head*)(chunks[0]); + char* body = (char*)(chunks[1]); + struct Foot* foot = (struct Foot*)(chunks[2]); + // ... + } + + In general though, independent_comalloc is worth using only for + larger values of n_elements. For small values, you probably won't + detect enough difference from series of malloc calls to bother. + + Overuse of independent_comalloc can increase overall memory usage, + since it cannot reuse existing noncontiguous small chunks that + might be available for some of the elements. +*/ +DLMALLOC_EXPORT void** dlindependent_comalloc(size_t, size_t*, void**); + +/* + bulk_free(void* array[], size_t n_elements) + Frees and clears (sets to null) each non-null pointer in the given + array. This is likely to be faster than freeing them one-by-one. + If footers are used, pointers that have been allocated in different + mspaces are not freed or cleared, and the count of all such pointers + is returned. For large arrays of pointers with poor locality, it + may be worthwhile to sort this array before calling bulk_free. +*/ +DLMALLOC_EXPORT size_t dlbulk_free(void**, size_t n_elements); + +/* + pvalloc(size_t n); + Equivalent to valloc(minimum-page-that-holds(n)), that is, + round up n to nearest pagesize. + */ +DLMALLOC_EXPORT void* dlpvalloc(size_t); + +/* + malloc_trim(size_t pad); + + If possible, gives memory back to the system (via negative arguments + to sbrk) if there is unused memory at the `high' end of the malloc + pool or in unused MMAP segments. You can call this after freeing + large blocks of memory to potentially reduce the system-level memory + requirements of a program. However, it cannot guarantee to reduce + memory. Under some allocation patterns, some large free blocks of + memory will be locked between two used chunks, so they cannot be + given back to the system. + + The `pad' argument to malloc_trim represents the amount of free + trailing space to leave untrimmed. If this argument is zero, only + the minimum amount of memory to maintain internal data structures + will be left. Non-zero arguments can be supplied to maintain enough + trailing space to service future expected allocations without having + to re-obtain memory from the system. + + Malloc_trim returns 1 if it actually released any memory, else 0. +*/ +DLMALLOC_EXPORT int dlmalloc_trim(size_t); + +/* + malloc_stats(); + Prints on stderr the amount of space obtained from the system (both + via sbrk and mmap), the maximum amount (which may be more than + current if malloc_trim and/or munmap got called), and the current + number of bytes allocated via malloc (or realloc, etc) but not yet + freed. Note that this is the number of bytes allocated, not the + number requested. It will be larger than the number requested + because of alignment and bookkeeping overhead. Because it includes + alignment wastage as being in use, this figure may be greater than + zero even when no user-level chunks are allocated. + + The reported current and maximum system memory can be inaccurate if + a program makes other calls to system memory allocation functions + (normally sbrk) outside of malloc. + + malloc_stats prints only the most commonly interesting statistics. + More information can be obtained by calling mallinfo. +*/ +DLMALLOC_EXPORT void dlmalloc_stats(void); + +/* + malloc_usable_size(void* p); + + Returns the number of bytes you can actually use in + an allocated chunk, which may be more than you requested (although + often not) due to alignment and minimum size constraints. + You can use this many bytes without worrying about + overwriting other allocated objects. This is not a particularly great + programming practice. malloc_usable_size can be more useful in + debugging and assertions, for example: + + p = malloc(n); + assert(malloc_usable_size(p) >= 256); +*/ +size_t dlmalloc_usable_size(void*); + +#endif /* ONLY_MSPACES */ + +#if MSPACES + +/* + mspace is an opaque type representing an independent + region of space that supports mspace_malloc, etc. +*/ +typedef void* mspace; + +/* + create_mspace creates and returns a new independent space with the + given initial capacity, or, if 0, the default granularity size. It + returns null if there is no system memory available to create the + space. If argument locked is non-zero, the space uses a separate + lock to control access. The capacity of the space will grow + dynamically as needed to service mspace_malloc requests. You can + control the sizes of incremental increases of this space by + compiling with a different DEFAULT_GRANULARITY or dynamically + setting with mallopt(M_GRANULARITY, value). +*/ +DLMALLOC_EXPORT mspace create_mspace(size_t capacity, int locked); + +/* + destroy_mspace destroys the given space, and attempts to return all + of its memory back to the system, returning the total number of + bytes freed. After destruction, the results of access to all memory + used by the space become undefined. +*/ +DLMALLOC_EXPORT size_t destroy_mspace(mspace msp); + +/* + create_mspace_with_base uses the memory supplied as the initial base + of a new mspace. Part (less than 128*sizeof(size_t) bytes) of this + space is used for bookkeeping, so the capacity must be at least this + large. (Otherwise 0 is returned.) When this initial space is + exhausted, additional memory will be obtained from the system. + Destroying this space will deallocate all additionally allocated + space (if possible) but not the initial base. +*/ +DLMALLOC_EXPORT mspace create_mspace_with_base(void* base, size_t capacity, int locked); + +/* + mspace_track_large_chunks controls whether requests for large chunks + are allocated in their own untracked mmapped regions, separate from + others in this mspace. By default large chunks are not tracked, + which reduces fragmentation. However, such chunks are not + necessarily released to the system upon destroy_mspace. Enabling + tracking by setting to true may increase fragmentation, but avoids + leakage when relying on destroy_mspace to release all memory + allocated using this space. The function returns the previous + setting. +*/ +DLMALLOC_EXPORT int mspace_track_large_chunks(mspace msp, int enable); + + +/* + mspace_malloc behaves as malloc, but operates within + the given space. +*/ +DLMALLOC_EXPORT void* mspace_malloc(mspace msp, size_t bytes); + +/* + mspace_free behaves as free, but operates within + the given space. + + If compiled with FOOTERS==1, mspace_free is not actually needed. + free may be called instead of mspace_free because freed chunks from + any space are handled by their originating spaces. +*/ +DLMALLOC_EXPORT void mspace_free(mspace msp, void* mem); + +/* + mspace_realloc behaves as realloc, but operates within + the given space. + + If compiled with FOOTERS==1, mspace_realloc is not actually + needed. realloc may be called instead of mspace_realloc because + realloced chunks from any space are handled by their originating + spaces. +*/ +DLMALLOC_EXPORT void* mspace_realloc(mspace msp, void* mem, size_t newsize); + +/* + mspace_calloc behaves as calloc, but operates within + the given space. +*/ +DLMALLOC_EXPORT void* mspace_calloc(mspace msp, size_t n_elements, size_t elem_size); + +/* + mspace_memalign behaves as memalign, but operates within + the given space. +*/ +DLMALLOC_EXPORT void* mspace_memalign(mspace msp, size_t alignment, size_t bytes); + +/* + mspace_aligned_alloc behaves as aligned_alloc, but operates within + the given space. +*/ +DLMALLOC_EXPORT void* mspace_aligned_alloc(mspace msp, size_t alignment, size_t bytes); + +/* + mspace_posix_memalign behaves as posix_memalign, but operates within + the given space. +*/ +DLMALLOC_EXPORT int mspace_posix_memalign(mspace msp, void **pp, size_t alignment, size_t bytes); + +/* + mspace_independent_calloc behaves as independent_calloc, but + operates within the given space. +*/ +DLMALLOC_EXPORT void** mspace_independent_calloc(mspace msp, size_t n_elements, + size_t elem_size, void* chunks[]); + +/* + mspace_independent_comalloc behaves as independent_comalloc, but + operates within the given space. +*/ +DLMALLOC_EXPORT void** mspace_independent_comalloc(mspace msp, size_t n_elements, + size_t sizes[], void* chunks[]); + +/* + mspace_footprint() returns the number of bytes obtained from the + system for this space. +*/ +DLMALLOC_EXPORT size_t mspace_footprint(mspace msp); + +/* + mspace_max_footprint() returns the peak number of bytes obtained from the + system for this space. +*/ +DLMALLOC_EXPORT size_t mspace_max_footprint(mspace msp); + +/* + Return least address of this mspace +*/ +DLMALLOC_EXPORT void* mspace_least_addr(mspace); + + +#if !NO_MALLINFO +/* + mspace_mallinfo behaves as mallinfo, but reports properties of + the given space. +*/ +DLMALLOC_EXPORT struct mallinfo mspace_mallinfo(mspace msp); +#endif /* NO_MALLINFO */ + +/* + malloc_usable_size(void* p) behaves the same as malloc_usable_size; +*/ +DLMALLOC_EXPORT size_t mspace_usable_size(const void* mem); + +/* + mspace_malloc_stats behaves as malloc_stats, but reports + properties of the given space. +*/ +DLMALLOC_EXPORT void mspace_malloc_stats(mspace msp); + +/* + mspace_trim behaves as malloc_trim, but + operates within the given space. +*/ +DLMALLOC_EXPORT int mspace_trim(mspace msp, size_t pad); + +/* + An alias for mallopt. +*/ +DLMALLOC_EXPORT int mspace_mallopt(int, int); + +#endif /* MSPACES */ + +#ifdef __cplusplus +} /* end of extern "C" */ +#endif /* __cplusplus */ + +/* + ======================================================================== + To make a fully customizable malloc.h header file, cut everything + above this line, put into file malloc.h, edit to suit, and #include it + on the next line, as well as in programs that use this malloc. + ======================================================================== +*/ + +/* #include "malloc.h" */ + +/*------------------------------ internal #includes ---------------------- */ + +#ifdef _MSC_VER +#pragma warning( disable : 4146 ) /* no "unsigned" warnings */ +#endif /* _MSC_VER */ +#if !NO_MALLOC_STATS +#include <stdio.h> /* for printing in malloc_stats */ +#endif /* NO_MALLOC_STATS */ +#ifndef LACKS_ERRNO_H +#include <errno.h> /* for MALLOC_FAILURE_ACTION */ +#endif /* LACKS_ERRNO_H */ +#ifdef DEBUG +#if ABORT_ON_ASSERT_FAILURE +#undef assert +#define assert(x) if(!(x)) ABORT +#else /* ABORT_ON_ASSERT_FAILURE */ +#include <assert.h> +#endif /* ABORT_ON_ASSERT_FAILURE */ +#else /* DEBUG */ +#ifndef assert +#define assert(x) +#endif +#define DEBUG 0 +#endif /* DEBUG */ +#if !defined(WIN32) && !defined(LACKS_TIME_H) +#include <time.h> /* for magic initialization */ +#endif /* WIN32 */ +#ifndef LACKS_STDLIB_H +#include <stdlib.h> /* for abort() */ +#endif /* LACKS_STDLIB_H */ +#ifndef LACKS_STRING_H +#include <string.h> /* for memset etc */ +#endif /* LACKS_STRING_H */ +#if USE_BUILTIN_FFS +#ifndef LACKS_STRINGS_H +#include <strings.h> /* for ffs */ +#endif /* LACKS_STRINGS_H */ +#endif /* USE_BUILTIN_FFS */ +#if HAVE_MMAP +#ifndef LACKS_SYS_MMAN_H +/* On some versions of linux, mremap decl in mman.h needs __USE_GNU set */ +#if (defined(linux) && !defined(__USE_GNU)) +#define __USE_GNU 1 +#include <sys/mman.h> /* for mmap */ +#undef __USE_GNU +#else +#include <sys/mman.h> /* for mmap */ +#endif /* linux */ +#endif /* LACKS_SYS_MMAN_H */ +#ifndef LACKS_FCNTL_H +#include <fcntl.h> +#endif /* LACKS_FCNTL_H */ +#endif /* HAVE_MMAP */ +#ifndef LACKS_UNISTD_H +#include <unistd.h> /* for sbrk, sysconf */ +#else /* LACKS_UNISTD_H */ +#if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__) +extern void* sbrk(ptrdiff_t); +#endif /* FreeBSD etc */ +#endif /* LACKS_UNISTD_H */ + +/* Declarations for locking */ +#if USE_LOCKS +#ifndef WIN32 +#if defined (__SVR4) && defined (__sun) /* solaris */ +#include <thread.h> +#elif !defined(LACKS_SCHED_H) +#include <sched.h> +#endif /* solaris or LACKS_SCHED_H */ +#if (defined(USE_RECURSIVE_LOCKS) && USE_RECURSIVE_LOCKS != 0) || !USE_SPIN_LOCKS +#include <pthread.h> +#endif /* USE_RECURSIVE_LOCKS ... */ +#elif defined(_MSC_VER) +#ifndef _M_AMD64 +/* These are already defined on AMD64 builds */ +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ +LONG __cdecl _InterlockedCompareExchange(LONG volatile *Dest, LONG Exchange, LONG Comp); +LONG __cdecl _InterlockedExchange(LONG volatile *Target, LONG Value); +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /* _M_AMD64 */ +#pragma intrinsic (_InterlockedCompareExchange) +#pragma intrinsic (_InterlockedExchange) +#define interlockedcompareexchange _InterlockedCompareExchange +#define interlockedexchange _InterlockedExchange +#elif defined(WIN32) && defined(__GNUC__) +#define interlockedcompareexchange(a, b, c) __sync_val_compare_and_swap(a, c, b) +#define interlockedexchange __sync_lock_test_and_set +#endif /* Win32 */ +#else /* USE_LOCKS */ +#endif /* USE_LOCKS */ + +#ifndef LOCK_AT_FORK +#define LOCK_AT_FORK 0 +#endif + +/* Declarations for bit scanning on win32 */ +#if defined(_MSC_VER) && _MSC_VER>=1300 +#ifndef BitScanForward /* Try to avoid pulling in WinNT.h */ +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ +unsigned char _BitScanForward(unsigned long *index, unsigned long mask); +unsigned char _BitScanReverse(unsigned long *index, unsigned long mask); +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#define BitScanForward _BitScanForward +#define BitScanReverse _BitScanReverse +#pragma intrinsic(_BitScanForward) +#pragma intrinsic(_BitScanReverse) +#endif /* BitScanForward */ +#endif /* defined(_MSC_VER) && _MSC_VER>=1300 */ + +#ifndef WIN32 +#ifndef malloc_getpagesize +# ifdef _SC_PAGESIZE /* some SVR4 systems omit an underscore */ +# ifndef _SC_PAGE_SIZE +# define _SC_PAGE_SIZE _SC_PAGESIZE +# endif +# endif +# ifdef _SC_PAGE_SIZE +# define malloc_getpagesize sysconf(_SC_PAGE_SIZE) +# else +# if defined(BSD) || defined(DGUX) || defined(HAVE_GETPAGESIZE) + extern size_t getpagesize(); +# define malloc_getpagesize getpagesize() +# else +# ifdef WIN32 /* use supplied emulation of getpagesize */ +# define malloc_getpagesize getpagesize() +# else +# ifndef LACKS_SYS_PARAM_H +# include <sys/param.h> +# endif +# ifdef EXEC_PAGESIZE +# define malloc_getpagesize EXEC_PAGESIZE +# else +# ifdef NBPG +# ifndef CLSIZE +# define malloc_getpagesize NBPG +# else +# define malloc_getpagesize (NBPG * CLSIZE) +# endif +# else +# ifdef NBPC +# define malloc_getpagesize NBPC +# else +# ifdef PAGESIZE +# define malloc_getpagesize PAGESIZE +# else /* just guess */ +# define malloc_getpagesize ((size_t)4096U) +# endif +# endif +# endif +# endif +# endif +# endif +# endif +#endif +#endif + +/* ------------------- size_t and alignment properties -------------------- */ + +/* The byte and bit size of a size_t */ +#define SIZE_T_SIZE (sizeof(size_t)) +#define SIZE_T_BITSIZE (sizeof(size_t) << 3) + +/* Some constants coerced to size_t */ +/* Annoying but necessary to avoid errors on some platforms */ +#define SIZE_T_ZERO ((size_t)0) +#define SIZE_T_ONE ((size_t)1) +#define SIZE_T_TWO ((size_t)2) +#define SIZE_T_FOUR ((size_t)4) +#define TWO_SIZE_T_SIZES (SIZE_T_SIZE<<1) +#define FOUR_SIZE_T_SIZES (SIZE_T_SIZE<<2) +#define SIX_SIZE_T_SIZES (FOUR_SIZE_T_SIZES+TWO_SIZE_T_SIZES) +#define HALF_MAX_SIZE_T (MAX_SIZE_T / 2U) + +/* The bit mask value corresponding to MALLOC_ALIGNMENT */ +#define CHUNK_ALIGN_MASK (MALLOC_ALIGNMENT - SIZE_T_ONE) + +/* True if address a has acceptable alignment */ +#define is_aligned(A) (((size_t)((A)) & (CHUNK_ALIGN_MASK)) == 0) + +/* the number of bytes to offset an address to align it */ +#define align_offset(A)\ + ((((size_t)(A) & CHUNK_ALIGN_MASK) == 0)? 0 :\ + ((MALLOC_ALIGNMENT - ((size_t)(A) & CHUNK_ALIGN_MASK)) & CHUNK_ALIGN_MASK)) + +/* -------------------------- MMAP preliminaries ------------------------- */ + +/* + If HAVE_MORECORE or HAVE_MMAP are false, we just define calls and + checks to fail so compiler optimizer can delete code rather than + using so many "#if"s. +*/ + + +/* MORECORE and MMAP must return MFAIL on failure */ +#define MFAIL ((void*)(MAX_SIZE_T)) +#define CMFAIL ((char*)(MFAIL)) /* defined for convenience */ + +#if HAVE_MMAP + +#ifndef WIN32 +#define MUNMAP_DEFAULT(a, s) munmap((a), (s)) +#define MMAP_PROT (PROT_READ|PROT_WRITE) +#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON) +#define MAP_ANONYMOUS MAP_ANON +#endif /* MAP_ANON */ +#ifdef MAP_ANONYMOUS +#define MMAP_FLAGS (MAP_PRIVATE|MAP_ANONYMOUS) +#define MMAP_DEFAULT(s) mmap(0, (s), MMAP_PROT, MMAP_FLAGS, -1, 0) +#else /* MAP_ANONYMOUS */ +/* + Nearly all versions of mmap support MAP_ANONYMOUS, so the following + is unlikely to be needed, but is supplied just in case. +*/ +#define MMAP_FLAGS (MAP_PRIVATE) +static int dev_zero_fd = -1; /* Cached file descriptor for /dev/zero. */ +#define MMAP_DEFAULT(s) ((dev_zero_fd < 0) ? \ + (dev_zero_fd = open("/dev/zero", O_RDWR), \ + mmap(0, (s), MMAP_PROT, MMAP_FLAGS, dev_zero_fd, 0)) : \ + mmap(0, (s), MMAP_PROT, MMAP_FLAGS, dev_zero_fd, 0)) +#endif /* MAP_ANONYMOUS */ + +#define DIRECT_MMAP_DEFAULT(s) MMAP_DEFAULT(s) + +#else /* WIN32 */ + +/* Win32 MMAP via VirtualAlloc */ +static FORCEINLINE void* win32mmap(size_t size) { + void* ptr = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE); + return (ptr != 0)? ptr: MFAIL; +} + +/* For direct MMAP, use MEM_TOP_DOWN to minimize interference */ +static FORCEINLINE void* win32direct_mmap(size_t size) { + void* ptr = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN, + PAGE_READWRITE); + return (ptr != 0)? ptr: MFAIL; +} + +/* This function supports releasing coalesed segments */ +static FORCEINLINE int win32munmap(void* ptr, size_t size) { + MEMORY_BASIC_INFORMATION minfo; + char* cptr = (char*)ptr; + while (size) { + if (VirtualQuery(cptr, &minfo, sizeof(minfo)) == 0) + return -1; + if (minfo.BaseAddress != cptr || minfo.AllocationBase != cptr || + minfo.State != MEM_COMMIT || minfo.RegionSize > size) + return -1; + if (VirtualFree(cptr, 0, MEM_RELEASE) == 0) + return -1; + cptr += minfo.RegionSize; + size -= minfo.RegionSize; + } + return 0; +} + +#define MMAP_DEFAULT(s) win32mmap(s) +#define MUNMAP_DEFAULT(a, s) win32munmap((a), (s)) +#define DIRECT_MMAP_DEFAULT(s) win32direct_mmap(s) +#endif /* WIN32 */ +#endif /* HAVE_MMAP */ + +#if HAVE_MREMAP +#ifndef WIN32 +#define MREMAP_DEFAULT(addr, osz, nsz, mv) mremap((addr), (osz), (nsz), (mv)) +#endif /* WIN32 */ +#endif /* HAVE_MREMAP */ + +/** + * Define CALL_MORECORE + */ +#if HAVE_MORECORE + #ifdef MORECORE + #define CALL_MORECORE(S) MORECORE(S) + #else /* MORECORE */ + #define CALL_MORECORE(S) MORECORE_DEFAULT(S) + #endif /* MORECORE */ +#else /* HAVE_MORECORE */ + #define CALL_MORECORE(S) MFAIL +#endif /* HAVE_MORECORE */ + +/** + * Define CALL_MMAP/CALL_MUNMAP/CALL_DIRECT_MMAP + */ +#if HAVE_MMAP + #define USE_MMAP_BIT (SIZE_T_ONE) + + #ifdef MMAP + #define CALL_MMAP(s) MMAP(s) + #else /* MMAP */ + #define CALL_MMAP(s) MMAP_DEFAULT(s) + #endif /* MMAP */ + #ifdef MUNMAP + #define CALL_MUNMAP(a, s) MUNMAP((a), (s)) + #else /* MUNMAP */ + #define CALL_MUNMAP(a, s) MUNMAP_DEFAULT((a), (s)) + #endif /* MUNMAP */ + #ifdef DIRECT_MMAP + #define CALL_DIRECT_MMAP(s) DIRECT_MMAP(s) + #else /* DIRECT_MMAP */ + #define CALL_DIRECT_MMAP(s) DIRECT_MMAP_DEFAULT(s) + #endif /* DIRECT_MMAP */ +#else /* HAVE_MMAP */ + #define USE_MMAP_BIT (SIZE_T_ZERO) + + #define MMAP(s) MFAIL + #define MUNMAP(a, s) (-1) + #define DIRECT_MMAP(s) MFAIL + #define CALL_DIRECT_MMAP(s) DIRECT_MMAP(s) + #define CALL_MMAP(s) MMAP(s) + #define CALL_MUNMAP(a, s) MUNMAP((a), (s)) +#endif /* HAVE_MMAP */ + +/** + * Define CALL_MREMAP + */ +#if HAVE_MMAP && HAVE_MREMAP + #ifdef MREMAP + #define CALL_MREMAP(addr, osz, nsz, mv) MREMAP((addr), (osz), (nsz), (mv)) + #else /* MREMAP */ + #define CALL_MREMAP(addr, osz, nsz, mv) MREMAP_DEFAULT((addr), (osz), (nsz), (mv)) + #endif /* MREMAP */ +#else /* HAVE_MMAP && HAVE_MREMAP */ + #define CALL_MREMAP(addr, osz, nsz, mv) MFAIL +#endif /* HAVE_MMAP && HAVE_MREMAP */ + +/* mstate bit set if continguous morecore disabled or failed */ +#define USE_NONCONTIGUOUS_BIT (4U) + +/* segment bit set in create_mspace_with_base */ +#define EXTERN_BIT (8U) + + +/* --------------------------- Lock preliminaries ------------------------ */ + +/* + When locks are defined, there is one global lock, plus + one per-mspace lock. + + The global lock_ensures that mparams.magic and other unique + mparams values are initialized only once. It also protects + sequences of calls to MORECORE. In many cases sys_alloc requires + two calls, that should not be interleaved with calls by other + threads. This does not protect against direct calls to MORECORE + by other threads not using this lock, so there is still code to + cope the best we can on interference. + + Per-mspace locks surround calls to malloc, free, etc. + By default, locks are simple non-reentrant mutexes. + + Because lock-protected regions generally have bounded times, it is + OK to use the supplied simple spinlocks. Spinlocks are likely to + improve performance for lightly contended applications, but worsen + performance under heavy contention. + + If USE_LOCKS is > 1, the definitions of lock routines here are + bypassed, in which case you will need to define the type MLOCK_T, + and at least INITIAL_LOCK, DESTROY_LOCK, ACQUIRE_LOCK, RELEASE_LOCK + and TRY_LOCK. You must also declare a + static MLOCK_T malloc_global_mutex = { initialization values };. + +*/ + +#if !USE_LOCKS +#define USE_LOCK_BIT (0U) +#define INITIAL_LOCK(l) (0) +#define DESTROY_LOCK(l) (0) +#define ACQUIRE_MALLOC_GLOBAL_LOCK() +#define RELEASE_MALLOC_GLOBAL_LOCK() + +#else +#if USE_LOCKS > 1 +/* ----------------------- User-defined locks ------------------------ */ +/* Define your own lock implementation here */ +/* #define INITIAL_LOCK(lk) ... */ +/* #define DESTROY_LOCK(lk) ... */ +/* #define ACQUIRE_LOCK(lk) ... */ +/* #define RELEASE_LOCK(lk) ... */ +/* #define TRY_LOCK(lk) ... */ +/* static MLOCK_T malloc_global_mutex = ... */ + +#elif USE_SPIN_LOCKS + +/* First, define CAS_LOCK and CLEAR_LOCK on ints */ +/* Note CAS_LOCK defined to return 0 on success */ + +#if defined(__GNUC__)&& (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)) +#define CAS_LOCK(sl) __sync_lock_test_and_set(sl, 1) +#define CLEAR_LOCK(sl) __sync_lock_release(sl) + +#elif (defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))) +/* Custom spin locks for older gcc on x86 */ +static FORCEINLINE int x86_cas_lock(int *sl) { + int ret; + int val = 1; + int cmp = 0; + __asm__ __volatile__ ("lock; cmpxchgl %1, %2" + : "=a" (ret) + : "r" (val), "m" (*(sl)), "0"(cmp) + : "memory", "cc"); + return ret; +} + +static FORCEINLINE void x86_clear_lock(int* sl) { + assert(*sl != 0); + int prev = 0; + int ret; + __asm__ __volatile__ ("lock; xchgl %0, %1" + : "=r" (ret) + : "m" (*(sl)), "0"(prev) + : "memory"); +} + +#define CAS_LOCK(sl) x86_cas_lock(sl) +#define CLEAR_LOCK(sl) x86_clear_lock(sl) + +#else /* Win32 MSC */ +#define CAS_LOCK(sl) interlockedexchange(sl, (LONG)1) +#define CLEAR_LOCK(sl) interlockedexchange (sl, (LONG)0) + +#endif /* ... gcc spins locks ... */ + +/* How to yield for a spin lock */ +#define SPINS_PER_YIELD 63 +#if defined(_MSC_VER) +#define SLEEP_EX_DURATION 50 /* delay for yield/sleep */ +#define SPIN_LOCK_YIELD SleepEx(SLEEP_EX_DURATION, FALSE) +#elif defined (__SVR4) && defined (__sun) /* solaris */ +#define SPIN_LOCK_YIELD thr_yield(); +#elif !defined(LACKS_SCHED_H) +#define SPIN_LOCK_YIELD sched_yield(); +#else +#define SPIN_LOCK_YIELD +#endif /* ... yield ... */ + +#if !defined(USE_RECURSIVE_LOCKS) || USE_RECURSIVE_LOCKS == 0 +/* Plain spin locks use single word (embedded in malloc_states) */ +static int spin_acquire_lock(int *sl) { + int spins = 0; + while (*(volatile int *)sl != 0 || CAS_LOCK(sl)) { + if ((++spins & SPINS_PER_YIELD) == 0) { + SPIN_LOCK_YIELD; + } + } + return 0; +} + +#define MLOCK_T int +#define TRY_LOCK(sl) !CAS_LOCK(sl) +#define RELEASE_LOCK(sl) CLEAR_LOCK(sl) +#define ACQUIRE_LOCK(sl) (CAS_LOCK(sl)? spin_acquire_lock(sl) : 0) +#define INITIAL_LOCK(sl) (*sl = 0) +#define DESTROY_LOCK(sl) (0) +static MLOCK_T malloc_global_mutex = 0; + +#else /* USE_RECURSIVE_LOCKS */ +/* types for lock owners */ +#ifdef WIN32 +#define THREAD_ID_T DWORD +#define CURRENT_THREAD GetCurrentThreadId() +#define EQ_OWNER(X,Y) ((X) == (Y)) +#else +/* + Note: the following assume that pthread_t is a type that can be + initialized to (casted) zero. If this is not the case, you will need to + somehow redefine these or not use spin locks. +*/ +#define THREAD_ID_T pthread_t +#define CURRENT_THREAD pthread_self() +#define EQ_OWNER(X,Y) pthread_equal(X, Y) +#endif + +struct malloc_recursive_lock { + int sl; + unsigned int c; + THREAD_ID_T threadid; +}; + +#define MLOCK_T struct malloc_recursive_lock +static MLOCK_T malloc_global_mutex = { 0, 0, (THREAD_ID_T)0}; + +static FORCEINLINE void recursive_release_lock(MLOCK_T *lk) { + assert(lk->sl != 0); + if (--lk->c == 0) { + CLEAR_LOCK(&lk->sl); + } +} + +static FORCEINLINE int recursive_acquire_lock(MLOCK_T *lk) { + THREAD_ID_T mythreadid = CURRENT_THREAD; + int spins = 0; + for (;;) { + if (*((volatile int *)(&lk->sl)) == 0) { + if (!CAS_LOCK(&lk->sl)) { + lk->threadid = mythreadid; + lk->c = 1; + return 0; + } + } + else if (EQ_OWNER(lk->threadid, mythreadid)) { + ++lk->c; + return 0; + } + if ((++spins & SPINS_PER_YIELD) == 0) { + SPIN_LOCK_YIELD; + } + } +} + +static FORCEINLINE int recursive_try_lock(MLOCK_T *lk) { + THREAD_ID_T mythreadid = CURRENT_THREAD; + if (*((volatile int *)(&lk->sl)) == 0) { + if (!CAS_LOCK(&lk->sl)) { + lk->threadid = mythreadid; + lk->c = 1; + return 1; + } + } + else if (EQ_OWNER(lk->threadid, mythreadid)) { + ++lk->c; + return 1; + } + return 0; +} + +#define RELEASE_LOCK(lk) recursive_release_lock(lk) +#define TRY_LOCK(lk) recursive_try_lock(lk) +#define ACQUIRE_LOCK(lk) recursive_acquire_lock(lk) +#define INITIAL_LOCK(lk) ((lk)->threadid = (THREAD_ID_T)0, (lk)->sl = 0, (lk)->c = 0) +#define DESTROY_LOCK(lk) (0) +#endif /* USE_RECURSIVE_LOCKS */ + +#elif defined(WIN32) /* Win32 critical sections */ +#define MLOCK_T CRITICAL_SECTION +#define ACQUIRE_LOCK(lk) (EnterCriticalSection(lk), 0) +#define RELEASE_LOCK(lk) LeaveCriticalSection(lk) +#define TRY_LOCK(lk) TryEnterCriticalSection(lk) +#define INITIAL_LOCK(lk) (!InitializeCriticalSectionAndSpinCount((lk), 0x80000000|4000)) +#define DESTROY_LOCK(lk) (DeleteCriticalSection(lk), 0) +#define NEED_GLOBAL_LOCK_INIT + +static MLOCK_T malloc_global_mutex; +static volatile LONG malloc_global_mutex_status; + +/* Use spin loop to initialize global lock */ +static void init_malloc_global_mutex() { + for (;;) { + long stat = malloc_global_mutex_status; + if (stat > 0) + return; + /* transition to < 0 while initializing, then to > 0) */ + if (stat == 0 && + interlockedcompareexchange(&malloc_global_mutex_status, (LONG)-1, (LONG)0) == 0) { + InitializeCriticalSection(&malloc_global_mutex); + interlockedexchange(&malloc_global_mutex_status, (LONG)1); + return; + } + SleepEx(0, FALSE); + } +} + +#else /* pthreads-based locks */ +#define MLOCK_T pthread_mutex_t +#define ACQUIRE_LOCK(lk) pthread_mutex_lock(lk) +#define RELEASE_LOCK(lk) pthread_mutex_unlock(lk) +#define TRY_LOCK(lk) (!pthread_mutex_trylock(lk)) +#define INITIAL_LOCK(lk) pthread_init_lock(lk) +#define DESTROY_LOCK(lk) pthread_mutex_destroy(lk) + +#if defined(USE_RECURSIVE_LOCKS) && USE_RECURSIVE_LOCKS != 0 && defined(linux) && !defined(PTHREAD_MUTEX_RECURSIVE) +/* Cope with old-style linux recursive lock initialization by adding */ +/* skipped internal declaration from pthread.h */ +extern int pthread_mutexattr_setkind_np __P ((pthread_mutexattr_t *__attr, + int __kind)); +#define PTHREAD_MUTEX_RECURSIVE PTHREAD_MUTEX_RECURSIVE_NP +#define pthread_mutexattr_settype(x,y) pthread_mutexattr_setkind_np(x,y) +#endif /* USE_RECURSIVE_LOCKS ... */ + +static MLOCK_T malloc_global_mutex = PTHREAD_MUTEX_INITIALIZER; + +static int pthread_init_lock (MLOCK_T *lk) { + pthread_mutexattr_t attr; + if (pthread_mutexattr_init(&attr)) return 1; +#if defined(USE_RECURSIVE_LOCKS) && USE_RECURSIVE_LOCKS != 0 + if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE)) return 1; +#endif + if (pthread_mutex_init(lk, &attr)) return 1; + if (pthread_mutexattr_destroy(&attr)) return 1; + return 0; +} + +#endif /* ... lock types ... */ + +/* Common code for all lock types */ +#define USE_LOCK_BIT (2U) + +#ifndef ACQUIRE_MALLOC_GLOBAL_LOCK +#define ACQUIRE_MALLOC_GLOBAL_LOCK() ACQUIRE_LOCK(&malloc_global_mutex); +#endif + +#ifndef RELEASE_MALLOC_GLOBAL_LOCK +#define RELEASE_MALLOC_GLOBAL_LOCK() RELEASE_LOCK(&malloc_global_mutex); +#endif + +#endif /* USE_LOCKS */ + +/* ----------------------- Chunk representations ------------------------ */ + +/* + (The following includes lightly edited explanations by Colin Plumb.) + + The malloc_chunk declaration below is misleading (but accurate and + necessary). It declares a "view" into memory allowing access to + necessary fields at known offsets from a given base. + + Chunks of memory are maintained using a `boundary tag' method as + originally described by Knuth. (See the paper by Paul Wilson + ftp://ftp.cs.utexas.edu/pub/garbage/allocsrv.ps for a survey of such + techniques.) Sizes of free chunks are stored both in the front of + each chunk and at the end. This makes consolidating fragmented + chunks into bigger chunks fast. The head fields also hold bits + representing whether chunks are free or in use. + + Here are some pictures to make it clearer. They are "exploded" to + show that the state of a chunk can be thought of as extending from + the high 31 bits of the head field of its header through the + prev_foot and PINUSE_BIT bit of the following chunk header. + + A chunk that's in use looks like: + + chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Size of previous chunk (if P = 0) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |P| + | Size of this chunk 1| +-+ + mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + +- -+ + | | + +- -+ + | : + +- size - sizeof(size_t) available payload bytes -+ + : | + chunk-> +- -+ + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |1| + | Size of next chunk (may or may not be in use) | +-+ + mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + And if it's free, it looks like this: + + chunk-> +- -+ + | User payload (must be in use, or we would have merged!) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |P| + | Size of this chunk 0| +-+ + mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Next pointer | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Prev pointer | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | : + +- size - sizeof(struct chunk) unused bytes -+ + : | + chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Size of this chunk | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |0| + | Size of next chunk (must be in use, or we would have merged)| +-+ + mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | : + +- User payload -+ + : | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + |0| + +-+ + Note that since we always merge adjacent free chunks, the chunks + adjacent to a free chunk must be in use. + + Given a pointer to a chunk (which can be derived trivially from the + payload pointer) we can, in O(1) time, find out whether the adjacent + chunks are free, and if so, unlink them from the lists that they + are on and merge them with the current chunk. + + Chunks always begin on even word boundaries, so the mem portion + (which is returned to the user) is also on an even word boundary, and + thus at least double-word aligned. + + The P (PINUSE_BIT) bit, stored in the unused low-order bit of the + chunk size (which is always a multiple of two words), is an in-use + bit for the *previous* chunk. If that bit is *clear*, then the + word before the current chunk size contains the previous chunk + size, and can be used to find the front of the previous chunk. + The very first chunk allocated always has this bit set, preventing + access to non-existent (or non-owned) memory. If pinuse is set for + any given chunk, then you CANNOT determine the size of the + previous chunk, and might even get a memory addressing fault when + trying to do so. + + The C (CINUSE_BIT) bit, stored in the unused second-lowest bit of + the chunk size redundantly records whether the current chunk is + inuse (unless the chunk is mmapped). This redundancy enables usage + checks within free and realloc, and reduces indirection when freeing + and consolidating chunks. + + Each freshly allocated chunk must have both cinuse and pinuse set. + That is, each allocated chunk borders either a previously allocated + and still in-use chunk, or the base of its memory arena. This is + ensured by making all allocations from the `lowest' part of any + found chunk. Further, no free chunk physically borders another one, + so each free chunk is known to be preceded and followed by either + inuse chunks or the ends of memory. + + Note that the `foot' of the current chunk is actually represented + as the prev_foot of the NEXT chunk. This makes it easier to + deal with alignments etc but can be very confusing when trying + to extend or adapt this code. + + The exceptions to all this are + + 1. The special chunk `top' is the top-most available chunk (i.e., + the one bordering the end of available memory). It is treated + specially. Top is never included in any bin, is used only if + no other chunk is available, and is released back to the + system if it is very large (see M_TRIM_THRESHOLD). In effect, + the top chunk is treated as larger (and thus less well + fitting) than any other available chunk. The top chunk + doesn't update its trailing size field since there is no next + contiguous chunk that would have to index off it. However, + space is still allocated for it (TOP_FOOT_SIZE) to enable + separation or merging when space is extended. + + 3. Chunks allocated via mmap, have both cinuse and pinuse bits + cleared in their head fields. Because they are allocated + one-by-one, each must carry its own prev_foot field, which is + also used to hold the offset this chunk has within its mmapped + region, which is needed to preserve alignment. Each mmapped + chunk is trailed by the first two fields of a fake next-chunk + for sake of usage checks. + +*/ + +struct malloc_chunk { + size_t prev_foot; /* Size of previous chunk (if free). */ + size_t head; /* Size and inuse bits. */ + struct malloc_chunk* fd; /* double links -- used only if free. */ + struct malloc_chunk* bk; +}; + +typedef struct malloc_chunk mchunk; +typedef struct malloc_chunk* mchunkptr; +typedef struct malloc_chunk* sbinptr; /* The type of bins of chunks */ +typedef unsigned int bindex_t; /* Described below */ +typedef unsigned int binmap_t; /* Described below */ +typedef unsigned int flag_t; /* The type of various bit flag sets */ + +/* ------------------- Chunks sizes and alignments ----------------------- */ + +#define MCHUNK_SIZE (sizeof(mchunk)) + +#if FOOTERS +#define CHUNK_OVERHEAD (TWO_SIZE_T_SIZES) +#else /* FOOTERS */ +#define CHUNK_OVERHEAD (SIZE_T_SIZE) +#endif /* FOOTERS */ + +/* MMapped chunks need a second word of overhead ... */ +#define MMAP_CHUNK_OVERHEAD (TWO_SIZE_T_SIZES) +/* ... and additional padding for fake next-chunk at foot */ +#define MMAP_FOOT_PAD (FOUR_SIZE_T_SIZES) + +/* The smallest size we can malloc is an aligned minimal chunk */ +#define MIN_CHUNK_SIZE\ + ((MCHUNK_SIZE + CHUNK_ALIGN_MASK) & ~CHUNK_ALIGN_MASK) + +/* conversion from malloc headers to user pointers, and back */ +#define chunk2mem(p) ((void*)((char*)(p) + TWO_SIZE_T_SIZES)) +#define mem2chunk(mem) ((mchunkptr)((char*)(mem) - TWO_SIZE_T_SIZES)) +/* chunk associated with aligned address A */ +#define align_as_chunk(A) (mchunkptr)((A) + align_offset(chunk2mem(A))) + +/* Bounds on request (not chunk) sizes. */ +#define MAX_REQUEST ((-MIN_CHUNK_SIZE) << 2) +#define MIN_REQUEST (MIN_CHUNK_SIZE - CHUNK_OVERHEAD - SIZE_T_ONE) + +/* pad request bytes into a usable size */ +#define pad_request(req) \ + (((req) + CHUNK_OVERHEAD + CHUNK_ALIGN_MASK) & ~CHUNK_ALIGN_MASK) + +/* pad request, checking for minimum (but not maximum) */ +#define request2size(req) \ + (((req) < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(req)) + + +/* ------------------ Operations on head and foot fields ----------------- */ + +/* + The head field of a chunk is or'ed with PINUSE_BIT when previous + adjacent chunk in use, and or'ed with CINUSE_BIT if this chunk is in + use, unless mmapped, in which case both bits are cleared. + + FLAG4_BIT is not used by this malloc, but might be useful in extensions. +*/ + +#define PINUSE_BIT (SIZE_T_ONE) +#define CINUSE_BIT (SIZE_T_TWO) +#define FLAG4_BIT (SIZE_T_FOUR) +#define INUSE_BITS (PINUSE_BIT|CINUSE_BIT) +#define FLAG_BITS (PINUSE_BIT|CINUSE_BIT|FLAG4_BIT) + +/* Head value for fenceposts */ +#define FENCEPOST_HEAD (INUSE_BITS|SIZE_T_SIZE) + +/* extraction of fields from head words */ +#define cinuse(p) ((p)->head & CINUSE_BIT) +#define pinuse(p) ((p)->head & PINUSE_BIT) +#define flag4inuse(p) ((p)->head & FLAG4_BIT) +#define is_inuse(p) (((p)->head & INUSE_BITS) != PINUSE_BIT) +#define is_mmapped(p) (((p)->head & INUSE_BITS) == 0) + +#define chunksize(p) ((p)->head & ~(FLAG_BITS)) + +#define clear_pinuse(p) ((p)->head &= ~PINUSE_BIT) +#define set_flag4(p) ((p)->head |= FLAG4_BIT) +#define clear_flag4(p) ((p)->head &= ~FLAG4_BIT) + +/* Treat space at ptr +/- offset as a chunk */ +#define chunk_plus_offset(p, s) ((mchunkptr)(((char*)(p)) + (s))) +#define chunk_minus_offset(p, s) ((mchunkptr)(((char*)(p)) - (s))) + +/* Ptr to next or previous physical malloc_chunk. */ +#define next_chunk(p) ((mchunkptr)( ((char*)(p)) + ((p)->head & ~FLAG_BITS))) +#define prev_chunk(p) ((mchunkptr)( ((char*)(p)) - ((p)->prev_foot) )) + +/* extract next chunk's pinuse bit */ +#define next_pinuse(p) ((next_chunk(p)->head) & PINUSE_BIT) + +/* Get/set size at footer */ +#define get_foot(p, s) (((mchunkptr)((char*)(p) + (s)))->prev_foot) +#define set_foot(p, s) (((mchunkptr)((char*)(p) + (s)))->prev_foot = (s)) + +/* Set size, pinuse bit, and foot */ +#define set_size_and_pinuse_of_free_chunk(p, s)\ + ((p)->head = (s|PINUSE_BIT), set_foot(p, s)) + +/* Set size, pinuse bit, foot, and clear next pinuse */ +#define set_free_with_pinuse(p, s, n)\ + (clear_pinuse(n), set_size_and_pinuse_of_free_chunk(p, s)) + +/* Get the internal overhead associated with chunk p */ +#define overhead_for(p)\ + (is_mmapped(p)? MMAP_CHUNK_OVERHEAD : CHUNK_OVERHEAD) + +/* Return true if malloced space is not necessarily cleared */ +#if MMAP_CLEARS +#define calloc_must_clear(p) (!is_mmapped(p)) +#else /* MMAP_CLEARS */ +#define calloc_must_clear(p) (1) +#endif /* MMAP_CLEARS */ + +/* ---------------------- Overlaid data structures ----------------------- */ + +/* + When chunks are not in use, they are treated as nodes of either + lists or trees. + + "Small" chunks are stored in circular doubly-linked lists, and look + like this: + + chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Size of previous chunk | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + `head:' | Size of chunk, in bytes |P| + mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Forward pointer to next chunk in list | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Back pointer to previous chunk in list | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Unused space (may be 0 bytes long) . + . . + . | +nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + `foot:' | Size of chunk, in bytes | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + Larger chunks are kept in a form of bitwise digital trees (aka + tries) keyed on chunksizes. Because malloc_tree_chunks are only for + free chunks greater than 256 bytes, their size doesn't impose any + constraints on user chunk sizes. Each node looks like: + + chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Size of previous chunk | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + `head:' | Size of chunk, in bytes |P| + mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Forward pointer to next chunk of same size | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Back pointer to previous chunk of same size | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Pointer to left child (child[0]) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Pointer to right child (child[1]) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Pointer to parent | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | bin index of this chunk | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Unused space . + . | +nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + `foot:' | Size of chunk, in bytes | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + Each tree holding treenodes is a tree of unique chunk sizes. Chunks + of the same size are arranged in a circularly-linked list, with only + the oldest chunk (the next to be used, in our FIFO ordering) + actually in the tree. (Tree members are distinguished by a non-null + parent pointer.) If a chunk with the same size an an existing node + is inserted, it is linked off the existing node using pointers that + work in the same way as fd/bk pointers of small chunks. + + Each tree contains a power of 2 sized range of chunk sizes (the + smallest is 0x100 <= x < 0x180), which is is divided in half at each + tree level, with the chunks in the smaller half of the range (0x100 + <= x < 0x140 for the top nose) in the left subtree and the larger + half (0x140 <= x < 0x180) in the right subtree. This is, of course, + done by inspecting individual bits. + + Using these rules, each node's left subtree contains all smaller + sizes than its right subtree. However, the node at the root of each + subtree has no particular ordering relationship to either. (The + dividing line between the subtree sizes is based on trie relation.) + If we remove the last chunk of a given size from the interior of the + tree, we need to replace it with a leaf node. The tree ordering + rules permit a node to be replaced by any leaf below it. + + The smallest chunk in a tree (a common operation in a best-fit + allocator) can be found by walking a path to the leftmost leaf in + the tree. Unlike a usual binary tree, where we follow left child + pointers until we reach a null, here we follow the right child + pointer any time the left one is null, until we reach a leaf with + both child pointers null. The smallest chunk in the tree will be + somewhere along that path. + + The worst case number of steps to add, find, or remove a node is + bounded by the number of bits differentiating chunks within + bins. Under current bin calculations, this ranges from 6 up to 21 + (for 32 bit sizes) or up to 53 (for 64 bit sizes). The typical case + is of course much better. +*/ + +struct malloc_tree_chunk { + /* The first four fields must be compatible with malloc_chunk */ + size_t prev_foot; + size_t head; + struct malloc_tree_chunk* fd; + struct malloc_tree_chunk* bk; + + struct malloc_tree_chunk* child[2]; + struct malloc_tree_chunk* parent; + bindex_t index; +}; + +typedef struct malloc_tree_chunk tchunk; +typedef struct malloc_tree_chunk* tchunkptr; +typedef struct malloc_tree_chunk* tbinptr; /* The type of bins of trees */ + +/* A little helper macro for trees */ +#define leftmost_child(t) ((t)->child[0] != 0? (t)->child[0] : (t)->child[1]) + +/* ----------------------------- Segments -------------------------------- */ + +/* + Each malloc space may include non-contiguous segments, held in a + list headed by an embedded malloc_segment record representing the + top-most space. Segments also include flags holding properties of + the space. Large chunks that are directly allocated by mmap are not + included in this list. They are instead independently created and + destroyed without otherwise keeping track of them. + + Segment management mainly comes into play for spaces allocated by + MMAP. Any call to MMAP might or might not return memory that is + adjacent to an existing segment. MORECORE normally contiguously + extends the current space, so this space is almost always adjacent, + which is simpler and faster to deal with. (This is why MORECORE is + used preferentially to MMAP when both are available -- see + sys_alloc.) When allocating using MMAP, we don't use any of the + hinting mechanisms (inconsistently) supported in various + implementations of unix mmap, or distinguish reserving from + committing memory. Instead, we just ask for space, and exploit + contiguity when we get it. It is probably possible to do + better than this on some systems, but no general scheme seems + to be significantly better. + + Management entails a simpler variant of the consolidation scheme + used for chunks to reduce fragmentation -- new adjacent memory is + normally prepended or appended to an existing segment. However, + there are limitations compared to chunk consolidation that mostly + reflect the fact that segment processing is relatively infrequent + (occurring only when getting memory from system) and that we + don't expect to have huge numbers of segments: + + * Segments are not indexed, so traversal requires linear scans. (It + would be possible to index these, but is not worth the extra + overhead and complexity for most programs on most platforms.) + * New segments are only appended to old ones when holding top-most + memory; if they cannot be prepended to others, they are held in + different segments. + + Except for the top-most segment of an mstate, each segment record + is kept at the tail of its segment. Segments are added by pushing + segment records onto the list headed by &mstate.seg for the + containing mstate. + + Segment flags control allocation/merge/deallocation policies: + * If EXTERN_BIT set, then we did not allocate this segment, + and so should not try to deallocate or merge with others. + (This currently holds only for the initial segment passed + into create_mspace_with_base.) + * If USE_MMAP_BIT set, the segment may be merged with + other surrounding mmapped segments and trimmed/de-allocated + using munmap. + * If neither bit is set, then the segment was obtained using + MORECORE so can be merged with surrounding MORECORE'd segments + and deallocated/trimmed using MORECORE with negative arguments. +*/ + +struct malloc_segment { + char* base; /* base address */ + size_t size; /* allocated size */ + struct malloc_segment* next; /* ptr to next segment */ + flag_t sflags; /* mmap and extern flag */ +}; + +#define is_mmapped_segment(S) ((S)->sflags & USE_MMAP_BIT) +#define is_extern_segment(S) ((S)->sflags & EXTERN_BIT) + +typedef struct malloc_segment msegment; +typedef struct malloc_segment* msegmentptr; + +/* ---------------------------- malloc_state ----------------------------- */ + +/* + A malloc_state holds all of the bookkeeping for a space. + The main fields are: + + Top + The topmost chunk of the currently active segment. Its size is + cached in topsize. The actual size of topmost space is + topsize+TOP_FOOT_SIZE, which includes space reserved for adding + fenceposts and segment records if necessary when getting more + space from the system. The size at which to autotrim top is + cached from mparams in trim_check, except that it is disabled if + an autotrim fails. + + Designated victim (dv) + This is the preferred chunk for servicing small requests that + don't have exact fits. It is normally the chunk split off most + recently to service another small request. Its size is cached in + dvsize. The link fields of this chunk are not maintained since it + is not kept in a bin. + + SmallBins + An array of bin headers for free chunks. These bins hold chunks + with sizes less than MIN_LARGE_SIZE bytes. Each bin contains + chunks of all the same size, spaced 8 bytes apart. To simplify + use in double-linked lists, each bin header acts as a malloc_chunk + pointing to the real first node, if it exists (else pointing to + itself). This avoids special-casing for headers. But to avoid + waste, we allocate only the fd/bk pointers of bins, and then use + repositioning tricks to treat these as the fields of a chunk. + + TreeBins + Treebins are pointers to the roots of trees holding a range of + sizes. There are 2 equally spaced treebins for each power of two + from TREE_SHIFT to TREE_SHIFT+16. The last bin holds anything + larger. + + Bin maps + There is one bit map for small bins ("smallmap") and one for + treebins ("treemap). Each bin sets its bit when non-empty, and + clears the bit when empty. Bit operations are then used to avoid + bin-by-bin searching -- nearly all "search" is done without ever + looking at bins that won't be selected. The bit maps + conservatively use 32 bits per map word, even if on 64bit system. + For a good description of some of the bit-based techniques used + here, see Henry S. Warren Jr's book "Hacker's Delight" (and + supplement at http://hackersdelight.org/). Many of these are + intended to reduce the branchiness of paths through malloc etc, as + well as to reduce the number of memory locations read or written. + + Segments + A list of segments headed by an embedded malloc_segment record + representing the initial space. + + Address check support + The least_addr field is the least address ever obtained from + MORECORE or MMAP. Attempted frees and reallocs of any address less + than this are trapped (unless INSECURE is defined). + + Magic tag + A cross-check field that should always hold same value as mparams.magic. + + Max allowed footprint + The maximum allowed bytes to allocate from system (zero means no limit) + + Flags + Bits recording whether to use MMAP, locks, or contiguous MORECORE + + Statistics + Each space keeps track of current and maximum system memory + obtained via MORECORE or MMAP. + + Trim support + Fields holding the amount of unused topmost memory that should trigger + trimming, and a counter to force periodic scanning to release unused + non-topmost segments. + + Locking + If USE_LOCKS is defined, the "mutex" lock is acquired and released + around every public call using this mspace. + + Extension support + A void* pointer and a size_t field that can be used to help implement + extensions to this malloc. +*/ + +/* Bin types, widths and sizes */ +#define NSMALLBINS (32U) +#define NTREEBINS (32U) +#define SMALLBIN_SHIFT (3U) +#define SMALLBIN_WIDTH (SIZE_T_ONE << SMALLBIN_SHIFT) +#define TREEBIN_SHIFT (8U) +#define MIN_LARGE_SIZE (SIZE_T_ONE << TREEBIN_SHIFT) +#define MAX_SMALL_SIZE (MIN_LARGE_SIZE - SIZE_T_ONE) +#define MAX_SMALL_REQUEST (MAX_SMALL_SIZE - CHUNK_ALIGN_MASK - CHUNK_OVERHEAD) + +struct malloc_state { + binmap_t smallmap; + binmap_t treemap; + size_t dvsize; + size_t topsize; + char* least_addr; + mchunkptr dv; + mchunkptr top; + size_t trim_check; + size_t release_checks; + size_t magic; + mchunkptr smallbins[(NSMALLBINS+1)*2]; + tbinptr treebins[NTREEBINS]; + size_t footprint; + size_t max_footprint; + size_t footprint_limit; /* zero means no limit */ + flag_t mflags; +#if USE_LOCKS + MLOCK_T mutex; /* locate lock among fields that rarely change */ +#endif /* USE_LOCKS */ + msegment seg; + void* extp; /* Unused but available for extensions */ + size_t exts; +}; + +typedef struct malloc_state* mstate; + +/* ------------- Global malloc_state and malloc_params ------------------- */ + +/* + malloc_params holds global properties, including those that can be + dynamically set using mallopt. There is a single instance, mparams, + initialized in init_mparams. Note that the non-zeroness of "magic" + also serves as an initialization flag. +*/ + +struct malloc_params { + size_t magic; + size_t page_size; + size_t granularity; + size_t mmap_threshold; + size_t trim_threshold; + flag_t default_mflags; +}; + +static struct malloc_params mparams; + +/* Ensure mparams initialized */ +#define ensure_initialization() (void)(mparams.magic != 0 || init_mparams()) + +#if !ONLY_MSPACES + +/* The global malloc_state used for all non-"mspace" calls */ +static struct malloc_state _gm_; +#define gm (&_gm_) +#define is_global(M) ((M) == &_gm_) + +#endif /* !ONLY_MSPACES */ + +#define is_initialized(M) ((M)->top != 0) + +/* -------------------------- system alloc setup ------------------------- */ + +/* Operations on mflags */ + +#define use_lock(M) ((M)->mflags & USE_LOCK_BIT) +#define enable_lock(M) ((M)->mflags |= USE_LOCK_BIT) +#if USE_LOCKS +#define disable_lock(M) ((M)->mflags &= ~USE_LOCK_BIT) +#else +#define disable_lock(M) +#endif + +#define use_mmap(M) ((M)->mflags & USE_MMAP_BIT) +#define enable_mmap(M) ((M)->mflags |= USE_MMAP_BIT) +#if HAVE_MMAP +#define disable_mmap(M) ((M)->mflags &= ~USE_MMAP_BIT) +#else +#define disable_mmap(M) +#endif + +#define use_noncontiguous(M) ((M)->mflags & USE_NONCONTIGUOUS_BIT) +#define disable_contiguous(M) ((M)->mflags |= USE_NONCONTIGUOUS_BIT) + +#define set_lock(M,L)\ + ((M)->mflags = (L)?\ + ((M)->mflags | USE_LOCK_BIT) :\ + ((M)->mflags & ~USE_LOCK_BIT)) + +/* page-align a size */ +#define page_align(S)\ + (((S) + (mparams.page_size - SIZE_T_ONE)) & ~(mparams.page_size - SIZE_T_ONE)) + +/* granularity-align a size */ +#define granularity_align(S)\ + (((S) + (mparams.granularity - SIZE_T_ONE))\ + & ~(mparams.granularity - SIZE_T_ONE)) + + +/* For mmap, use granularity alignment on windows, else page-align */ +#ifdef WIN32 +#define mmap_align(S) granularity_align(S) +#else +#define mmap_align(S) page_align(S) +#endif + +/* For sys_alloc, enough padding to ensure can malloc request on success */ +#define SYS_ALLOC_PADDING (TOP_FOOT_SIZE + MALLOC_ALIGNMENT) + +#define is_page_aligned(S)\ + (((size_t)(S) & (mparams.page_size - SIZE_T_ONE)) == 0) +#define is_granularity_aligned(S)\ + (((size_t)(S) & (mparams.granularity - SIZE_T_ONE)) == 0) + +/* True if segment S holds address A */ +#define segment_holds(S, A)\ + ((char*)(A) >= S->base && (char*)(A) < S->base + S->size) + +/* Return segment holding given address */ +static msegmentptr segment_holding(mstate m, char* addr) { + msegmentptr sp = &m->seg; + for (;;) { + if (addr >= sp->base && addr < sp->base + sp->size) + return sp; + if ((sp = sp->next) == 0) + return 0; + } +} + +/* Return true if segment contains a segment link */ +static int has_segment_link(mstate m, msegmentptr ss) { + msegmentptr sp = &m->seg; + for (;;) { + if ((char*)sp >= ss->base && (char*)sp < ss->base + ss->size) + return 1; + if ((sp = sp->next) == 0) + return 0; + } +} + +#ifndef MORECORE_CANNOT_TRIM +#define should_trim(M,s) ((s) > (M)->trim_check) +#else /* MORECORE_CANNOT_TRIM */ +#define should_trim(M,s) (0) +#endif /* MORECORE_CANNOT_TRIM */ + +/* + TOP_FOOT_SIZE is padding at the end of a segment, including space + that may be needed to place segment records and fenceposts when new + noncontiguous segments are added. +*/ +#define TOP_FOOT_SIZE\ + (align_offset(chunk2mem(0))+pad_request(sizeof(struct malloc_segment))+MIN_CHUNK_SIZE) + + +/* ------------------------------- Hooks -------------------------------- */ + +/* + PREACTION should be defined to return 0 on success, and nonzero on + failure. If you are not using locking, you can redefine these to do + anything you like. +*/ + +#if USE_LOCKS +#define PREACTION(M) ((use_lock(M))? ACQUIRE_LOCK(&(M)->mutex) : 0) +#define POSTACTION(M) { if (use_lock(M)) RELEASE_LOCK(&(M)->mutex); } +#else /* USE_LOCKS */ + +#ifndef PREACTION +#define PREACTION(M) (0) +#endif /* PREACTION */ + +#ifndef POSTACTION +#define POSTACTION(M) +#endif /* POSTACTION */ + +#endif /* USE_LOCKS */ + +/* + CORRUPTION_ERROR_ACTION is triggered upon detected bad addresses. + USAGE_ERROR_ACTION is triggered on detected bad frees and + reallocs. The argument p is an address that might have triggered the + fault. It is ignored by the two predefined actions, but might be + useful in custom actions that try to help diagnose errors. +*/ + +#if PROCEED_ON_ERROR + +/* A count of the number of corruption errors causing resets */ +int malloc_corruption_error_count; + +/* default corruption action */ +static void reset_on_error(mstate m); + +#define CORRUPTION_ERROR_ACTION(m) reset_on_error(m) +#define USAGE_ERROR_ACTION(m, p) + +#else /* PROCEED_ON_ERROR */ + +#ifndef CORRUPTION_ERROR_ACTION +#define CORRUPTION_ERROR_ACTION(m) ABORT +#endif /* CORRUPTION_ERROR_ACTION */ + +#ifndef USAGE_ERROR_ACTION +#define USAGE_ERROR_ACTION(m,p) ABORT +#endif /* USAGE_ERROR_ACTION */ + +#endif /* PROCEED_ON_ERROR */ + + +/* -------------------------- Debugging setup ---------------------------- */ + +#if ! DEBUG + +#define check_free_chunk(M,P) +#define check_inuse_chunk(M,P) +#define check_malloced_chunk(M,P,N) +#define check_mmapped_chunk(M,P) +#define check_malloc_state(M) +#define check_top_chunk(M,P) + +#else /* DEBUG */ +#define check_free_chunk(M,P) do_check_free_chunk(M,P) +#define check_inuse_chunk(M,P) do_check_inuse_chunk(M,P) +#define check_top_chunk(M,P) do_check_top_chunk(M,P) +#define check_malloced_chunk(M,P,N) do_check_malloced_chunk(M,P,N) +#define check_mmapped_chunk(M,P) do_check_mmapped_chunk(M,P) +#define check_malloc_state(M) do_check_malloc_state(M) + +static void do_check_any_chunk(mstate m, mchunkptr p); +static void do_check_top_chunk(mstate m, mchunkptr p); +static void do_check_mmapped_chunk(mstate m, mchunkptr p); +static void do_check_inuse_chunk(mstate m, mchunkptr p); +static void do_check_free_chunk(mstate m, mchunkptr p); +static void do_check_malloced_chunk(mstate m, void* mem, size_t s); +static void do_check_tree(mstate m, tchunkptr t); +static void do_check_treebin(mstate m, bindex_t i); +static void do_check_smallbin(mstate m, bindex_t i); +static void do_check_malloc_state(mstate m); +static int bin_find(mstate m, mchunkptr x); +static size_t traverse_and_check(mstate m); +#endif /* DEBUG */ + +/* ---------------------------- Indexing Bins ---------------------------- */ + +#define is_small(s) (((s) >> SMALLBIN_SHIFT) < NSMALLBINS) +#define small_index(s) (bindex_t)((s) >> SMALLBIN_SHIFT) +#define small_index2size(i) ((i) << SMALLBIN_SHIFT) +#define MIN_SMALL_INDEX (small_index(MIN_CHUNK_SIZE)) + +/* addressing by index. See above about smallbin repositioning */ +#define smallbin_at(M, i) ((sbinptr)((char*)&((M)->smallbins[(i)<<1]))) +#define treebin_at(M,i) (&((M)->treebins[i])) + +/* assign tree index for size S to variable I. Use x86 asm if possible */ +#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) +#define compute_tree_index(S, I)\ +{\ + unsigned int X = S >> TREEBIN_SHIFT;\ + if (X == 0)\ + I = 0;\ + else if (X > 0xFFFF)\ + I = NTREEBINS-1;\ + else {\ + unsigned int K = (unsigned) sizeof(X)*__CHAR_BIT__ - 1 - (unsigned) __builtin_clz(X); \ + I = (bindex_t)((K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1)));\ + }\ +} + +#elif defined (__INTEL_COMPILER) +#define compute_tree_index(S, I)\ +{\ + size_t X = S >> TREEBIN_SHIFT;\ + if (X == 0)\ + I = 0;\ + else if (X > 0xFFFF)\ + I = NTREEBINS-1;\ + else {\ + unsigned int K = _bit_scan_reverse (X); \ + I = (bindex_t)((K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1)));\ + }\ +} + +#elif defined(_MSC_VER) && _MSC_VER>=1300 +#define compute_tree_index(S, I)\ +{\ + size_t X = S >> TREEBIN_SHIFT;\ + if (X == 0)\ + I = 0;\ + else if (X > 0xFFFF)\ + I = NTREEBINS-1;\ + else {\ + unsigned int K;\ + _BitScanReverse((DWORD *) &K, (DWORD) X);\ + I = (bindex_t)((K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1)));\ + }\ +} + +#else /* GNUC */ +#define compute_tree_index(S, I)\ +{\ + size_t X = S >> TREEBIN_SHIFT;\ + if (X == 0)\ + I = 0;\ + else if (X > 0xFFFF)\ + I = NTREEBINS-1;\ + else {\ + unsigned int Y = (unsigned int)X;\ + unsigned int N = ((Y - 0x100) >> 16) & 8;\ + unsigned int K = (((Y <<= N) - 0x1000) >> 16) & 4;\ + N += K;\ + N += K = (((Y <<= K) - 0x4000) >> 16) & 2;\ + K = 14 - N + ((Y <<= K) >> 15);\ + I = (K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1));\ + }\ +} +#endif /* GNUC */ + +/* Bit representing maximum resolved size in a treebin at i */ +#define bit_for_tree_index(i) \ + (i == NTREEBINS-1)? (SIZE_T_BITSIZE-1) : (((i) >> 1) + TREEBIN_SHIFT - 2) + +/* Shift placing maximum resolved bit in a treebin at i as sign bit */ +#define leftshift_for_tree_index(i) \ + ((i == NTREEBINS-1)? 0 : \ + ((SIZE_T_BITSIZE-SIZE_T_ONE) - (((i) >> 1) + TREEBIN_SHIFT - 2))) + +/* The size of the smallest chunk held in bin with index i */ +#define minsize_for_tree_index(i) \ + ((SIZE_T_ONE << (((i) >> 1) + TREEBIN_SHIFT)) | \ + (((size_t)((i) & SIZE_T_ONE)) << (((i) >> 1) + TREEBIN_SHIFT - 1))) + + +/* ------------------------ Operations on bin maps ----------------------- */ + +/* bit corresponding to given index */ +#define idx2bit(i) ((binmap_t)(1) << (i)) + +/* Mark/Clear bits with given index */ +#define mark_smallmap(M,i) ((M)->smallmap |= idx2bit(i)) +#define clear_smallmap(M,i) ((M)->smallmap &= ~idx2bit(i)) +#define smallmap_is_marked(M,i) ((M)->smallmap & idx2bit(i)) + +#define mark_treemap(M,i) ((M)->treemap |= idx2bit(i)) +#define clear_treemap(M,i) ((M)->treemap &= ~idx2bit(i)) +#define treemap_is_marked(M,i) ((M)->treemap & idx2bit(i)) + +/* isolate the least set bit of a bitmap */ +#define least_bit(x) ((x) & -(x)) + +/* mask with all bits to left of least bit of x on */ +#define left_bits(x) ((x<<1) | -(x<<1)) + +/* mask with all bits to left of or equal to least bit of x on */ +#define same_or_left_bits(x) ((x) | -(x)) + +/* index corresponding to given bit. Use x86 asm if possible */ + +#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) +#define compute_bit2idx(X, I)\ +{\ + unsigned int J;\ + J = __builtin_ctz(X); \ + I = (bindex_t)J;\ +} + +#elif defined (__INTEL_COMPILER) +#define compute_bit2idx(X, I)\ +{\ + unsigned int J;\ + J = _bit_scan_forward (X); \ + I = (bindex_t)J;\ +} + +#elif defined(_MSC_VER) && _MSC_VER>=1300 +#define compute_bit2idx(X, I)\ +{\ + unsigned int J;\ + _BitScanForward((DWORD *) &J, X);\ + I = (bindex_t)J;\ +} + +#elif USE_BUILTIN_FFS +#define compute_bit2idx(X, I) I = ffs(X)-1 + +#else +#define compute_bit2idx(X, I)\ +{\ + unsigned int Y = X - 1;\ + unsigned int K = Y >> (16-4) & 16;\ + unsigned int N = K; Y >>= K;\ + N += K = Y >> (8-3) & 8; Y >>= K;\ + N += K = Y >> (4-2) & 4; Y >>= K;\ + N += K = Y >> (2-1) & 2; Y >>= K;\ + N += K = Y >> (1-0) & 1; Y >>= K;\ + I = (bindex_t)(N + Y);\ +} +#endif /* GNUC */ + + +/* ----------------------- Runtime Check Support ------------------------- */ + +/* + For security, the main invariant is that malloc/free/etc never + writes to a static address other than malloc_state, unless static + malloc_state itself has been corrupted, which cannot occur via + malloc (because of these checks). In essence this means that we + believe all pointers, sizes, maps etc held in malloc_state, but + check all of those linked or offsetted from other embedded data + structures. These checks are interspersed with main code in a way + that tends to minimize their run-time cost. + + When FOOTERS is defined, in addition to range checking, we also + verify footer fields of inuse chunks, which can be used guarantee + that the mstate controlling malloc/free is intact. This is a + streamlined version of the approach described by William Robertson + et al in "Run-time Detection of Heap-based Overflows" LISA'03 + http://www.usenix.org/events/lisa03/tech/robertson.html The footer + of an inuse chunk holds the xor of its mstate and a random seed, + that is checked upon calls to free() and realloc(). This is + (probabalistically) unguessable from outside the program, but can be + computed by any code successfully malloc'ing any chunk, so does not + itself provide protection against code that has already broken + security through some other means. Unlike Robertson et al, we + always dynamically check addresses of all offset chunks (previous, + next, etc). This turns out to be cheaper than relying on hashes. +*/ + +#if !INSECURE +/* Check if address a is at least as high as any from MORECORE or MMAP */ +#define ok_address(M, a) ((char*)(a) >= (M)->least_addr) +/* Check if address of next chunk n is higher than base chunk p */ +#define ok_next(p, n) ((char*)(p) < (char*)(n)) +/* Check if p has inuse status */ +#define ok_inuse(p) is_inuse(p) +/* Check if p has its pinuse bit on */ +#define ok_pinuse(p) pinuse(p) + +#else /* !INSECURE */ +#define ok_address(M, a) (1) +#define ok_next(b, n) (1) +#define ok_inuse(p) (1) +#define ok_pinuse(p) (1) +#endif /* !INSECURE */ + +#if (FOOTERS && !INSECURE) +/* Check if (alleged) mstate m has expected magic field */ +#define ok_magic(M) ((M)->magic == mparams.magic) +#else /* (FOOTERS && !INSECURE) */ +#define ok_magic(M) (1) +#endif /* (FOOTERS && !INSECURE) */ + +/* In gcc, use __builtin_expect to minimize impact of checks */ +#if !INSECURE +#if defined(__GNUC__) && __GNUC__ >= 3 +#define RTCHECK(e) __builtin_expect(e, 1) +#else /* GNUC */ +#define RTCHECK(e) (e) +#endif /* GNUC */ +#else /* !INSECURE */ +#define RTCHECK(e) (1) +#endif /* !INSECURE */ + +/* macros to set up inuse chunks with or without footers */ + +#if !FOOTERS + +#define mark_inuse_foot(M,p,s) + +/* Macros for setting head/foot of non-mmapped chunks */ + +/* Set cinuse bit and pinuse bit of next chunk */ +#define set_inuse(M,p,s)\ + ((p)->head = (((p)->head & PINUSE_BIT)|s|CINUSE_BIT),\ + ((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT) + +/* Set cinuse and pinuse of this chunk and pinuse of next chunk */ +#define set_inuse_and_pinuse(M,p,s)\ + ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\ + ((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT) + +/* Set size, cinuse and pinuse bit of this chunk */ +#define set_size_and_pinuse_of_inuse_chunk(M, p, s)\ + ((p)->head = (s|PINUSE_BIT|CINUSE_BIT)) + +#else /* FOOTERS */ + +/* Set foot of inuse chunk to be xor of mstate and seed */ +#define mark_inuse_foot(M,p,s)\ + (((mchunkptr)((char*)(p) + (s)))->prev_foot = ((size_t)(M) ^ mparams.magic)) + +#define get_mstate_for(p)\ + ((mstate)(((mchunkptr)((char*)(p) +\ + (chunksize(p))))->prev_foot ^ mparams.magic)) + +#define set_inuse(M,p,s)\ + ((p)->head = (((p)->head & PINUSE_BIT)|s|CINUSE_BIT),\ + (((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT), \ + mark_inuse_foot(M,p,s)) + +#define set_inuse_and_pinuse(M,p,s)\ + ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\ + (((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT),\ + mark_inuse_foot(M,p,s)) + +#define set_size_and_pinuse_of_inuse_chunk(M, p, s)\ + ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\ + mark_inuse_foot(M, p, s)) + +#endif /* !FOOTERS */ + +/* ---------------------------- setting mparams -------------------------- */ + +#if LOCK_AT_FORK +static void pre_fork(void) { ACQUIRE_LOCK(&(gm)->mutex); } +static void post_fork_parent(void) { RELEASE_LOCK(&(gm)->mutex); } +static void post_fork_child(void) { INITIAL_LOCK(&(gm)->mutex); } +#endif /* LOCK_AT_FORK */ + +/* Initialize mparams */ +static int init_mparams(void) { +#ifdef NEED_GLOBAL_LOCK_INIT + if (malloc_global_mutex_status <= 0) + init_malloc_global_mutex(); +#endif + + ACQUIRE_MALLOC_GLOBAL_LOCK(); + if (mparams.magic == 0) { + size_t magic; + size_t psize; + size_t gsize; + +#ifndef WIN32 + psize = malloc_getpagesize; + gsize = ((DEFAULT_GRANULARITY != 0)? DEFAULT_GRANULARITY : psize); +#else /* WIN32 */ + { + SYSTEM_INFO system_info; + GetSystemInfo(&system_info); + psize = system_info.dwPageSize; + gsize = ((DEFAULT_GRANULARITY != 0)? + DEFAULT_GRANULARITY : system_info.dwAllocationGranularity); + } +#endif /* WIN32 */ + + /* Sanity-check configuration: + size_t must be unsigned and as wide as pointer type. + ints must be at least 4 bytes. + alignment must be at least 8. + Alignment, min chunk size, and page size must all be powers of 2. + */ + if ((sizeof(size_t) != sizeof(char*)) || + (MAX_SIZE_T < MIN_CHUNK_SIZE) || + (sizeof(int) < 4) || + (MALLOC_ALIGNMENT < (size_t)8U) || + ((MALLOC_ALIGNMENT & (MALLOC_ALIGNMENT-SIZE_T_ONE)) != 0) || + ((MCHUNK_SIZE & (MCHUNK_SIZE-SIZE_T_ONE)) != 0) || + ((gsize & (gsize-SIZE_T_ONE)) != 0) || + ((psize & (psize-SIZE_T_ONE)) != 0)) + ABORT; + mparams.granularity = gsize; + mparams.page_size = psize; + mparams.mmap_threshold = DEFAULT_MMAP_THRESHOLD; + mparams.trim_threshold = DEFAULT_TRIM_THRESHOLD; +#if MORECORE_CONTIGUOUS + mparams.default_mflags = USE_LOCK_BIT|USE_MMAP_BIT; +#else /* MORECORE_CONTIGUOUS */ + mparams.default_mflags = USE_LOCK_BIT|USE_MMAP_BIT|USE_NONCONTIGUOUS_BIT; +#endif /* MORECORE_CONTIGUOUS */ + +#if !ONLY_MSPACES + /* Set up lock for main malloc area */ + gm->mflags = mparams.default_mflags; + (void)INITIAL_LOCK(&gm->mutex); +#endif +#if LOCK_AT_FORK + pthread_atfork(&pre_fork, &post_fork_parent, &post_fork_child); +#endif + + { +#if USE_DEV_RANDOM + int fd; + unsigned char buf[sizeof(size_t)]; + /* Try to use /dev/urandom, else fall back on using time */ + if ((fd = open("/dev/urandom", O_RDONLY)) >= 0 && + read(fd, buf, sizeof(buf)) == sizeof(buf)) { + magic = *((size_t *) buf); + close(fd); + } + else +#endif /* USE_DEV_RANDOM */ +#ifdef WIN32 + magic = (size_t)(GetTickCount() ^ (size_t)0x55555555U); +#elif defined(LACKS_TIME_H) + magic = (size_t)&magic ^ (size_t)0x55555555U; +#else + magic = (size_t)(time(0) ^ (size_t)0x55555555U); +#endif + magic |= (size_t)8U; /* ensure nonzero */ + magic &= ~(size_t)7U; /* improve chances of fault for bad values */ + /* Until memory modes commonly available, use volatile-write */ + (*(volatile size_t *)(&(mparams.magic))) = magic; + } + } + + RELEASE_MALLOC_GLOBAL_LOCK(); + return 1; +} + +/* support for mallopt */ +static int change_mparam(int param_number, int value) { + size_t val; + ensure_initialization(); + val = (value == -1)? MAX_SIZE_T : (size_t)value; + switch(param_number) { + case M_TRIM_THRESHOLD: + mparams.trim_threshold = val; + return 1; + case M_GRANULARITY: + if (val >= mparams.page_size && ((val & (val-1)) == 0)) { + mparams.granularity = val; + return 1; + } + else + return 0; + case M_MMAP_THRESHOLD: + mparams.mmap_threshold = val; + return 1; + default: + return 0; + } +} + +#if DEBUG +/* ------------------------- Debugging Support --------------------------- */ + +/* Check properties of any chunk, whether free, inuse, mmapped etc */ +static void do_check_any_chunk(mstate m, mchunkptr p) { + assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD)); + assert(ok_address(m, p)); +} + +/* Check properties of top chunk */ +static void do_check_top_chunk(mstate m, mchunkptr p) { + msegmentptr sp = segment_holding(m, (char*)p); + size_t sz = p->head & ~INUSE_BITS; /* third-lowest bit can be set! */ + assert(sp != 0); + assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD)); + assert(ok_address(m, p)); + assert(sz == m->topsize); + assert(sz > 0); + assert(sz == ((sp->base + sp->size) - (char*)p) - TOP_FOOT_SIZE); + assert(pinuse(p)); + assert(!pinuse(chunk_plus_offset(p, sz))); +} + +/* Check properties of (inuse) mmapped chunks */ +static void do_check_mmapped_chunk(mstate m, mchunkptr p) { + size_t sz = chunksize(p); + size_t len = (sz + (p->prev_foot) + MMAP_FOOT_PAD); + assert(is_mmapped(p)); + assert(use_mmap(m)); + assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD)); + assert(ok_address(m, p)); + assert(!is_small(sz)); + assert((len & (mparams.page_size-SIZE_T_ONE)) == 0); + assert(chunk_plus_offset(p, sz)->head == FENCEPOST_HEAD); + assert(chunk_plus_offset(p, sz+SIZE_T_SIZE)->head == 0); +} + +/* Check properties of inuse chunks */ +static void do_check_inuse_chunk(mstate m, mchunkptr p) { + do_check_any_chunk(m, p); + assert(is_inuse(p)); + assert(next_pinuse(p)); + /* If not pinuse and not mmapped, previous chunk has OK offset */ + assert(is_mmapped(p) || pinuse(p) || next_chunk(prev_chunk(p)) == p); + if (is_mmapped(p)) + do_check_mmapped_chunk(m, p); +} + +/* Check properties of free chunks */ +static void do_check_free_chunk(mstate m, mchunkptr p) { + size_t sz = chunksize(p); + mchunkptr next = chunk_plus_offset(p, sz); + do_check_any_chunk(m, p); + assert(!is_inuse(p)); + assert(!next_pinuse(p)); + assert (!is_mmapped(p)); + if (p != m->dv && p != m->top) { + if (sz >= MIN_CHUNK_SIZE) { + assert((sz & CHUNK_ALIGN_MASK) == 0); + assert(is_aligned(chunk2mem(p))); + assert(next->prev_foot == sz); + assert(pinuse(p)); + assert (next == m->top || is_inuse(next)); + assert(p->fd->bk == p); + assert(p->bk->fd == p); + } + else /* markers are always of size SIZE_T_SIZE */ + assert(sz == SIZE_T_SIZE); + } +} + +/* Check properties of malloced chunks at the point they are malloced */ +static void do_check_malloced_chunk(mstate m, void* mem, size_t s) { + if (mem != 0) { + mchunkptr p = mem2chunk(mem); + size_t sz = p->head & ~INUSE_BITS; + do_check_inuse_chunk(m, p); + assert((sz & CHUNK_ALIGN_MASK) == 0); + assert(sz >= MIN_CHUNK_SIZE); + assert(sz >= s); + /* unless mmapped, size is less than MIN_CHUNK_SIZE more than request */ + assert(is_mmapped(p) || sz < (s + MIN_CHUNK_SIZE)); + } +} + +/* Check a tree and its subtrees. */ +static void do_check_tree(mstate m, tchunkptr t) { + tchunkptr head = 0; + tchunkptr u = t; + bindex_t tindex = t->index; + size_t tsize = chunksize(t); + bindex_t idx; + compute_tree_index(tsize, idx); + assert(tindex == idx); + assert(tsize >= MIN_LARGE_SIZE); + assert(tsize >= minsize_for_tree_index(idx)); + assert((idx == NTREEBINS-1) || (tsize < minsize_for_tree_index((idx+1)))); + + do { /* traverse through chain of same-sized nodes */ + do_check_any_chunk(m, ((mchunkptr)u)); + assert(u->index == tindex); + assert(chunksize(u) == tsize); + assert(!is_inuse(u)); + assert(!next_pinuse(u)); + assert(u->fd->bk == u); + assert(u->bk->fd == u); + if (u->parent == 0) { + assert(u->child[0] == 0); + assert(u->child[1] == 0); + } + else { + assert(head == 0); /* only one node on chain has parent */ + head = u; + assert(u->parent != u); + assert (u->parent->child[0] == u || + u->parent->child[1] == u || + *((tbinptr*)(u->parent)) == u); + if (u->child[0] != 0) { + assert(u->child[0]->parent == u); + assert(u->child[0] != u); + do_check_tree(m, u->child[0]); + } + if (u->child[1] != 0) { + assert(u->child[1]->parent == u); + assert(u->child[1] != u); + do_check_tree(m, u->child[1]); + } + if (u->child[0] != 0 && u->child[1] != 0) { + assert(chunksize(u->child[0]) < chunksize(u->child[1])); + } + } + u = u->fd; + } while (u != t); + assert(head != 0); +} + +/* Check all the chunks in a treebin. */ +static void do_check_treebin(mstate m, bindex_t i) { + tbinptr* tb = treebin_at(m, i); + tchunkptr t = *tb; + int empty = (m->treemap & (1U << i)) == 0; + if (t == 0) + assert(empty); + if (!empty) + do_check_tree(m, t); +} + +/* Check all the chunks in a smallbin. */ +static void do_check_smallbin(mstate m, bindex_t i) { + sbinptr b = smallbin_at(m, i); + mchunkptr p = b->bk; + unsigned int empty = (m->smallmap & (1U << i)) == 0; + if (p == b) + assert(empty); + if (!empty) { + for (; p != b; p = p->bk) { + size_t size = chunksize(p); + mchunkptr q; + /* each chunk claims to be free */ + do_check_free_chunk(m, p); + /* chunk belongs in bin */ + assert(small_index(size) == i); + assert(p->bk == b || chunksize(p->bk) == chunksize(p)); + /* chunk is followed by an inuse chunk */ + q = next_chunk(p); + if (q->head != FENCEPOST_HEAD) + do_check_inuse_chunk(m, q); + } + } +} + +/* Find x in a bin. Used in other check functions. */ +static int bin_find(mstate m, mchunkptr x) { + size_t size = chunksize(x); + if (is_small(size)) { + bindex_t sidx = small_index(size); + sbinptr b = smallbin_at(m, sidx); + if (smallmap_is_marked(m, sidx)) { + mchunkptr p = b; + do { + if (p == x) + return 1; + } while ((p = p->fd) != b); + } + } + else { + bindex_t tidx; + compute_tree_index(size, tidx); + if (treemap_is_marked(m, tidx)) { + tchunkptr t = *treebin_at(m, tidx); + size_t sizebits = size << leftshift_for_tree_index(tidx); + while (t != 0 && chunksize(t) != size) { + t = t->child[(sizebits >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1]; + sizebits <<= 1; + } + if (t != 0) { + tchunkptr u = t; + do { + if (u == (tchunkptr)x) + return 1; + } while ((u = u->fd) != t); + } + } + } + return 0; +} + +/* Traverse each chunk and check it; return total */ +static size_t traverse_and_check(mstate m) { + size_t sum = 0; + if (is_initialized(m)) { + msegmentptr s = &m->seg; + sum += m->topsize + TOP_FOOT_SIZE; + while (s != 0) { + mchunkptr q = align_as_chunk(s->base); + mchunkptr lastq = 0; + assert(pinuse(q)); + while (segment_holds(s, q) && + q != m->top && q->head != FENCEPOST_HEAD) { + sum += chunksize(q); + if (is_inuse(q)) { + assert(!bin_find(m, q)); + do_check_inuse_chunk(m, q); + } + else { + assert(q == m->dv || bin_find(m, q)); + assert(lastq == 0 || is_inuse(lastq)); /* Not 2 consecutive free */ + do_check_free_chunk(m, q); + } + lastq = q; + q = next_chunk(q); + } + s = s->next; + } + } + return sum; +} + + +/* Check all properties of malloc_state. */ +static void do_check_malloc_state(mstate m) { + bindex_t i; + size_t total; + /* check bins */ + for (i = 0; i < NSMALLBINS; ++i) + do_check_smallbin(m, i); + for (i = 0; i < NTREEBINS; ++i) + do_check_treebin(m, i); + + if (m->dvsize != 0) { /* check dv chunk */ + do_check_any_chunk(m, m->dv); + assert(m->dvsize == chunksize(m->dv)); + assert(m->dvsize >= MIN_CHUNK_SIZE); + assert(bin_find(m, m->dv) == 0); + } + + if (m->top != 0) { /* check top chunk */ + do_check_top_chunk(m, m->top); + /*assert(m->topsize == chunksize(m->top)); redundant */ + assert(m->topsize > 0); + assert(bin_find(m, m->top) == 0); + } + + total = traverse_and_check(m); + assert(total <= m->footprint); + assert(m->footprint <= m->max_footprint); +} +#endif /* DEBUG */ + +/* ----------------------------- statistics ------------------------------ */ + +#if !NO_MALLINFO +static struct mallinfo internal_mallinfo(mstate m) { + struct mallinfo nm = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + ensure_initialization(); + if (!PREACTION(m)) { + check_malloc_state(m); + if (is_initialized(m)) { + size_t nfree = SIZE_T_ONE; /* top always free */ + size_t mfree = m->topsize + TOP_FOOT_SIZE; + size_t sum = mfree; + msegmentptr s = &m->seg; + while (s != 0) { + mchunkptr q = align_as_chunk(s->base); + while (segment_holds(s, q) && + q != m->top && q->head != FENCEPOST_HEAD) { + size_t sz = chunksize(q); + sum += sz; + if (!is_inuse(q)) { + mfree += sz; + ++nfree; + } + q = next_chunk(q); + } + s = s->next; + } + + nm.arena = sum; + nm.ordblks = nfree; + nm.hblkhd = m->footprint - sum; + nm.usmblks = m->max_footprint; + nm.uordblks = m->footprint - mfree; + nm.fordblks = mfree; + nm.keepcost = m->topsize; + } + + POSTACTION(m); + } + return nm; +} +#endif /* !NO_MALLINFO */ + +#if !NO_MALLOC_STATS +static void internal_malloc_stats(mstate m) { + ensure_initialization(); + if (!PREACTION(m)) { + size_t maxfp = 0; + size_t fp = 0; + size_t used = 0; + check_malloc_state(m); + if (is_initialized(m)) { + msegmentptr s = &m->seg; + maxfp = m->max_footprint; + fp = m->footprint; + used = fp - (m->topsize + TOP_FOOT_SIZE); + + while (s != 0) { + mchunkptr q = align_as_chunk(s->base); + while (segment_holds(s, q) && + q != m->top && q->head != FENCEPOST_HEAD) { + if (!is_inuse(q)) + used -= chunksize(q); + q = next_chunk(q); + } + s = s->next; + } + } + POSTACTION(m); /* drop lock */ + fprintf(stderr, "max system bytes = %10lu\n", (unsigned long)(maxfp)); + fprintf(stderr, "system bytes = %10lu\n", (unsigned long)(fp)); + fprintf(stderr, "in use bytes = %10lu\n", (unsigned long)(used)); + } +} +#endif /* NO_MALLOC_STATS */ + +/* ----------------------- Operations on smallbins ----------------------- */ + +/* + Various forms of linking and unlinking are defined as macros. Even + the ones for trees, which are very long but have very short typical + paths. This is ugly but reduces reliance on inlining support of + compilers. +*/ + +/* Link a free chunk into a smallbin */ +#define insert_small_chunk(M, P, S) {\ + bindex_t I = small_index(S);\ + mchunkptr B = smallbin_at(M, I);\ + mchunkptr F = B;\ + assert(S >= MIN_CHUNK_SIZE);\ + if (!smallmap_is_marked(M, I))\ + mark_smallmap(M, I);\ + else if (RTCHECK(ok_address(M, B->fd)))\ + F = B->fd;\ + else {\ + CORRUPTION_ERROR_ACTION(M);\ + }\ + B->fd = P;\ + F->bk = P;\ + P->fd = F;\ + P->bk = B;\ +} + +/* Unlink a chunk from a smallbin */ +#define unlink_small_chunk(M, P, S) {\ + mchunkptr F = P->fd;\ + mchunkptr B = P->bk;\ + bindex_t I = small_index(S);\ + assert(P != B);\ + assert(P != F);\ + assert(chunksize(P) == small_index2size(I));\ + if (RTCHECK(F == smallbin_at(M,I) || (ok_address(M, F) && F->bk == P))) { \ + if (B == F) {\ + clear_smallmap(M, I);\ + }\ + else if (RTCHECK(B == smallbin_at(M,I) ||\ + (ok_address(M, B) && B->fd == P))) {\ + F->bk = B;\ + B->fd = F;\ + }\ + else {\ + CORRUPTION_ERROR_ACTION(M);\ + }\ + }\ + else {\ + CORRUPTION_ERROR_ACTION(M);\ + }\ +} + +/* Unlink the first chunk from a smallbin */ +#define unlink_first_small_chunk(M, B, P, I) {\ + mchunkptr F = P->fd;\ + assert(P != B);\ + assert(P != F);\ + assert(chunksize(P) == small_index2size(I));\ + if (B == F) {\ + clear_smallmap(M, I);\ + }\ + else if (RTCHECK(ok_address(M, F) && F->bk == P)) {\ + F->bk = B;\ + B->fd = F;\ + }\ + else {\ + CORRUPTION_ERROR_ACTION(M);\ + }\ +} + +/* Replace dv node, binning the old one */ +/* Used only when dvsize known to be small */ +#define replace_dv(M, P, S) {\ + size_t DVS = M->dvsize;\ + assert(is_small(DVS));\ + if (DVS != 0) {\ + mchunkptr DV = M->dv;\ + insert_small_chunk(M, DV, DVS);\ + }\ + M->dvsize = S;\ + M->dv = P;\ +} + +/* ------------------------- Operations on trees ------------------------- */ + +/* Insert chunk into tree */ +#define insert_large_chunk(M, X, S) {\ + tbinptr* H;\ + bindex_t I;\ + compute_tree_index(S, I);\ + H = treebin_at(M, I);\ + X->index = I;\ + X->child[0] = X->child[1] = 0;\ + if (!treemap_is_marked(M, I)) {\ + mark_treemap(M, I);\ + *H = X;\ + X->parent = (tchunkptr)H;\ + X->fd = X->bk = X;\ + }\ + else {\ + tchunkptr T = *H;\ + size_t K = S << leftshift_for_tree_index(I);\ + for (;;) {\ + if (chunksize(T) != S) {\ + tchunkptr* C = &(T->child[(K >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1]);\ + K <<= 1;\ + if (*C != 0)\ + T = *C;\ + else if (RTCHECK(ok_address(M, C))) {\ + *C = X;\ + X->parent = T;\ + X->fd = X->bk = X;\ + break;\ + }\ + else {\ + CORRUPTION_ERROR_ACTION(M);\ + break;\ + }\ + }\ + else {\ + tchunkptr F = T->fd;\ + if (RTCHECK(ok_address(M, T) && ok_address(M, F))) {\ + T->fd = F->bk = X;\ + X->fd = F;\ + X->bk = T;\ + X->parent = 0;\ + break;\ + }\ + else {\ + CORRUPTION_ERROR_ACTION(M);\ + break;\ + }\ + }\ + }\ + }\ +} + +/* + Unlink steps: + + 1. If x is a chained node, unlink it from its same-sized fd/bk links + and choose its bk node as its replacement. + 2. If x was the last node of its size, but not a leaf node, it must + be replaced with a leaf node (not merely one with an open left or + right), to make sure that lefts and rights of descendents + correspond properly to bit masks. We use the rightmost descendent + of x. We could use any other leaf, but this is easy to locate and + tends to counteract removal of leftmosts elsewhere, and so keeps + paths shorter than minimally guaranteed. This doesn't loop much + because on average a node in a tree is near the bottom. + 3. If x is the base of a chain (i.e., has parent links) relink + x's parent and children to x's replacement (or null if none). +*/ + +#define unlink_large_chunk(M, X) {\ + tchunkptr XP = X->parent;\ + tchunkptr R;\ + if (X->bk != X) {\ + tchunkptr F = X->fd;\ + R = X->bk;\ + if (RTCHECK(ok_address(M, F) && F->bk == X && R->fd == X)) {\ + F->bk = R;\ + R->fd = F;\ + }\ + else {\ + CORRUPTION_ERROR_ACTION(M);\ + }\ + }\ + else {\ + tchunkptr* RP;\ + if (((R = *(RP = &(X->child[1]))) != 0) ||\ + ((R = *(RP = &(X->child[0]))) != 0)) {\ + tchunkptr* CP;\ + while ((*(CP = &(R->child[1])) != 0) ||\ + (*(CP = &(R->child[0])) != 0)) {\ + R = *(RP = CP);\ + }\ + if (RTCHECK(ok_address(M, RP)))\ + *RP = 0;\ + else {\ + CORRUPTION_ERROR_ACTION(M);\ + }\ + }\ + }\ + if (XP != 0) {\ + tbinptr* H = treebin_at(M, X->index);\ + if (X == *H) {\ + if ((*H = R) == 0) \ + clear_treemap(M, X->index);\ + }\ + else if (RTCHECK(ok_address(M, XP))) {\ + if (XP->child[0] == X) \ + XP->child[0] = R;\ + else \ + XP->child[1] = R;\ + }\ + else\ + CORRUPTION_ERROR_ACTION(M);\ + if (R != 0) {\ + if (RTCHECK(ok_address(M, R))) {\ + tchunkptr C0, C1;\ + R->parent = XP;\ + if ((C0 = X->child[0]) != 0) {\ + if (RTCHECK(ok_address(M, C0))) {\ + R->child[0] = C0;\ + C0->parent = R;\ + }\ + else\ + CORRUPTION_ERROR_ACTION(M);\ + }\ + if ((C1 = X->child[1]) != 0) {\ + if (RTCHECK(ok_address(M, C1))) {\ + R->child[1] = C1;\ + C1->parent = R;\ + }\ + else\ + CORRUPTION_ERROR_ACTION(M);\ + }\ + }\ + else\ + CORRUPTION_ERROR_ACTION(M);\ + }\ + }\ +} + +/* Relays to large vs small bin operations */ + +#define insert_chunk(M, P, S)\ + if (is_small(S)) insert_small_chunk(M, P, S)\ + else { tchunkptr TP = (tchunkptr)(P); insert_large_chunk(M, TP, S); } + +#define unlink_chunk(M, P, S)\ + if (is_small(S)) unlink_small_chunk(M, P, S)\ + else { tchunkptr TP = (tchunkptr)(P); unlink_large_chunk(M, TP); } + + +/* Relays to internal calls to malloc/free from realloc, memalign etc */ + +#if ONLY_MSPACES +#define internal_malloc(m, b) mspace_malloc(m, b) +#define internal_free(m, mem) mspace_free(m,mem); +#else /* ONLY_MSPACES */ +#if MSPACES +#define internal_malloc(m, b)\ + ((m == gm)? dlmalloc(b) : mspace_malloc(m, b)) +#define internal_free(m, mem)\ + if (m == gm) dlfree(mem); else mspace_free(m,mem); +#else /* MSPACES */ +#define internal_malloc(m, b) dlmalloc(b) +#define internal_free(m, mem) dlfree(mem) +#endif /* MSPACES */ +#endif /* ONLY_MSPACES */ + +/* ----------------------- Direct-mmapping chunks ----------------------- */ + +/* + Directly mmapped chunks are set up with an offset to the start of + the mmapped region stored in the prev_foot field of the chunk. This + allows reconstruction of the required argument to MUNMAP when freed, + and also allows adjustment of the returned chunk to meet alignment + requirements (especially in memalign). +*/ + +/* Malloc using mmap */ +static void* mmap_alloc(mstate m, size_t nb) { + size_t mmsize = mmap_align(nb + SIX_SIZE_T_SIZES + CHUNK_ALIGN_MASK); + if (m->footprint_limit != 0) { + size_t fp = m->footprint + mmsize; + if (fp <= m->footprint || fp > m->footprint_limit) + return 0; + } + if (mmsize > nb) { /* Check for wrap around 0 */ + char* mm = (char*)(CALL_DIRECT_MMAP(mmsize)); + if (mm != CMFAIL) { + size_t offset = align_offset(chunk2mem(mm)); + size_t psize = mmsize - offset - MMAP_FOOT_PAD; + mchunkptr p = (mchunkptr)(mm + offset); + p->prev_foot = offset; + p->head = psize; + mark_inuse_foot(m, p, psize); + chunk_plus_offset(p, psize)->head = FENCEPOST_HEAD; + chunk_plus_offset(p, psize+SIZE_T_SIZE)->head = 0; + + if (m->least_addr == 0 || mm < m->least_addr) + m->least_addr = mm; + if ((m->footprint += mmsize) > m->max_footprint) + m->max_footprint = m->footprint; + assert(is_aligned(chunk2mem(p))); + check_mmapped_chunk(m, p); + return chunk2mem(p); + } + } + return 0; +} + +/* Realloc using mmap */ +static mchunkptr mmap_resize(mstate m, mchunkptr oldp, size_t nb, int flags) { + size_t oldsize = chunksize(oldp); + (void)flags; /* placate people compiling -Wunused */ + if (is_small(nb)) /* Can't shrink mmap regions below small size */ + return 0; + /* Keep old chunk if big enough but not too big */ + if (oldsize >= nb + SIZE_T_SIZE && + (oldsize - nb) <= (mparams.granularity << 1)) + return oldp; + else { + size_t offset = oldp->prev_foot; + size_t oldmmsize = oldsize + offset + MMAP_FOOT_PAD; + size_t newmmsize = mmap_align(nb + SIX_SIZE_T_SIZES + CHUNK_ALIGN_MASK); + char* cp = (char*)CALL_MREMAP((char*)oldp - offset, + oldmmsize, newmmsize, flags); + if (cp != CMFAIL) { + mchunkptr newp = (mchunkptr)(cp + offset); + size_t psize = newmmsize - offset - MMAP_FOOT_PAD; + newp->head = psize; + mark_inuse_foot(m, newp, psize); + chunk_plus_offset(newp, psize)->head = FENCEPOST_HEAD; + chunk_plus_offset(newp, psize+SIZE_T_SIZE)->head = 0; + + if (cp < m->least_addr) + m->least_addr = cp; + if ((m->footprint += newmmsize - oldmmsize) > m->max_footprint) + m->max_footprint = m->footprint; + check_mmapped_chunk(m, newp); + return newp; + } + } + return 0; +} + + +/* -------------------------- mspace management -------------------------- */ + +/* Initialize top chunk and its size */ +static void init_top(mstate m, mchunkptr p, size_t psize) { + /* Ensure alignment */ + size_t offset = align_offset(chunk2mem(p)); + p = (mchunkptr)((char*)p + offset); + psize -= offset; + + m->top = p; + m->topsize = psize; + p->head = psize | PINUSE_BIT; + /* set size of fake trailing chunk holding overhead space only once */ + chunk_plus_offset(p, psize)->head = TOP_FOOT_SIZE; + m->trim_check = mparams.trim_threshold; /* reset on each update */ +} + +/* Initialize bins for a new mstate that is otherwise zeroed out */ +static void init_bins(mstate m) { + /* Establish circular links for smallbins */ + bindex_t i; + for (i = 0; i < NSMALLBINS; ++i) { + sbinptr bin = smallbin_at(m,i); + bin->fd = bin->bk = bin; + } +} + +#if PROCEED_ON_ERROR + +/* default corruption action */ +static void reset_on_error(mstate m) { + int i; + ++malloc_corruption_error_count; + /* Reinitialize fields to forget about all memory */ + m->smallmap = m->treemap = 0; + m->dvsize = m->topsize = 0; + m->seg.base = 0; + m->seg.size = 0; + m->seg.next = 0; + m->top = m->dv = 0; + for (i = 0; i < NTREEBINS; ++i) + *treebin_at(m, i) = 0; + init_bins(m); +} +#endif /* PROCEED_ON_ERROR */ + +/* Allocate chunk and prepend remainder with chunk in successor base. */ +static void* prepend_alloc(mstate m, char* newbase, char* oldbase, + size_t nb) { + mchunkptr p = align_as_chunk(newbase); + mchunkptr oldfirst = align_as_chunk(oldbase); + size_t psize = (char*)oldfirst - (char*)p; + mchunkptr q = chunk_plus_offset(p, nb); + size_t qsize = psize - nb; + set_size_and_pinuse_of_inuse_chunk(m, p, nb); + + assert((char*)oldfirst > (char*)q); + assert(pinuse(oldfirst)); + assert(qsize >= MIN_CHUNK_SIZE); + + /* consolidate remainder with first chunk of old base */ + if (oldfirst == m->top) { + size_t tsize = m->topsize += qsize; + m->top = q; + q->head = tsize | PINUSE_BIT; + check_top_chunk(m, q); + } + else if (oldfirst == m->dv) { + size_t dsize = m->dvsize += qsize; + m->dv = q; + set_size_and_pinuse_of_free_chunk(q, dsize); + } + else { + if (!is_inuse(oldfirst)) { + size_t nsize = chunksize(oldfirst); + unlink_chunk(m, oldfirst, nsize); + oldfirst = chunk_plus_offset(oldfirst, nsize); + qsize += nsize; + } + set_free_with_pinuse(q, qsize, oldfirst); + insert_chunk(m, q, qsize); + check_free_chunk(m, q); + } + + check_malloced_chunk(m, chunk2mem(p), nb); + return chunk2mem(p); +} + +/* Add a segment to hold a new noncontiguous region */ +static void add_segment(mstate m, char* tbase, size_t tsize, flag_t mmapped) { + /* Determine locations and sizes of segment, fenceposts, old top */ + char* old_top = (char*)m->top; + msegmentptr oldsp = segment_holding(m, old_top); + char* old_end = oldsp->base + oldsp->size; + size_t ssize = pad_request(sizeof(struct malloc_segment)); + char* rawsp = old_end - (ssize + FOUR_SIZE_T_SIZES + CHUNK_ALIGN_MASK); + size_t offset = align_offset(chunk2mem(rawsp)); + char* asp = rawsp + offset; + char* csp = (asp < (old_top + MIN_CHUNK_SIZE))? old_top : asp; + mchunkptr sp = (mchunkptr)csp; + msegmentptr ss = (msegmentptr)(chunk2mem(sp)); + mchunkptr tnext = chunk_plus_offset(sp, ssize); + mchunkptr p = tnext; + int nfences = 0; + + /* reset top to new space */ + init_top(m, (mchunkptr)tbase, tsize - TOP_FOOT_SIZE); + + /* Set up segment record */ + assert(is_aligned(ss)); + set_size_and_pinuse_of_inuse_chunk(m, sp, ssize); + *ss = m->seg; /* Push current record */ + m->seg.base = tbase; + m->seg.size = tsize; + m->seg.sflags = mmapped; + m->seg.next = ss; + + /* Insert trailing fenceposts */ + for (;;) { + mchunkptr nextp = chunk_plus_offset(p, SIZE_T_SIZE); + p->head = FENCEPOST_HEAD; + ++nfences; + if ((char*)(&(nextp->head)) < old_end) + p = nextp; + else + break; + } + assert(nfences >= 2); + + /* Insert the rest of old top into a bin as an ordinary free chunk */ + if (csp != old_top) { + mchunkptr q = (mchunkptr)old_top; + size_t psize = csp - old_top; + mchunkptr tn = chunk_plus_offset(q, psize); + set_free_with_pinuse(q, psize, tn); + insert_chunk(m, q, psize); + } + + check_top_chunk(m, m->top); +} + +/* -------------------------- System allocation -------------------------- */ + +/* Get memory from system using MORECORE or MMAP */ +static void* sys_alloc(mstate m, size_t nb) { + char* tbase = CMFAIL; + size_t tsize = 0; + flag_t mmap_flag = 0; + size_t asize; /* allocation size */ + + ensure_initialization(); + + /* Directly map large chunks, but only if already initialized */ + if (use_mmap(m) && nb >= mparams.mmap_threshold && m->topsize != 0) { + void* mem = mmap_alloc(m, nb); + if (mem != 0) + return mem; + } + + asize = granularity_align(nb + SYS_ALLOC_PADDING); + if (asize <= nb) + return 0; /* wraparound */ + if (m->footprint_limit != 0) { + size_t fp = m->footprint + asize; + if (fp <= m->footprint || fp > m->footprint_limit) + return 0; + } + + /* + Try getting memory in any of three ways (in most-preferred to + least-preferred order): + 1. A call to MORECORE that can normally contiguously extend memory. + (disabled if not MORECORE_CONTIGUOUS or not HAVE_MORECORE or + or main space is mmapped or a previous contiguous call failed) + 2. A call to MMAP new space (disabled if not HAVE_MMAP). + Note that under the default settings, if MORECORE is unable to + fulfill a request, and HAVE_MMAP is true, then mmap is + used as a noncontiguous system allocator. This is a useful backup + strategy for systems with holes in address spaces -- in this case + sbrk cannot contiguously expand the heap, but mmap may be able to + find space. + 3. A call to MORECORE that cannot usually contiguously extend memory. + (disabled if not HAVE_MORECORE) + + In all cases, we need to request enough bytes from system to ensure + we can malloc nb bytes upon success, so pad with enough space for + top_foot, plus alignment-pad to make sure we don't lose bytes if + not on boundary, and round this up to a granularity unit. + */ + + if (MORECORE_CONTIGUOUS && !use_noncontiguous(m)) { + char* br = CMFAIL; + size_t ssize = asize; /* sbrk call size */ + msegmentptr ss = (m->top == 0)? 0 : segment_holding(m, (char*)m->top); + ACQUIRE_MALLOC_GLOBAL_LOCK(); + + if (ss == 0) { /* First time through or recovery */ + char* base = (char*)CALL_MORECORE(0); + if (base != CMFAIL) { + size_t fp; + /* Adjust to end on a page boundary */ + if (!is_page_aligned(base)) + ssize += (page_align((size_t)base) - (size_t)base); + fp = m->footprint + ssize; /* recheck limits */ + if (ssize > nb && ssize < HALF_MAX_SIZE_T && + (m->footprint_limit == 0 || + (fp > m->footprint && fp <= m->footprint_limit)) && + (br = (char*)(CALL_MORECORE(ssize))) == base) { + tbase = base; + tsize = ssize; + } + } + } + else { + /* Subtract out existing available top space from MORECORE request. */ + ssize = granularity_align(nb - m->topsize + SYS_ALLOC_PADDING); + /* Use mem here only if it did continuously extend old space */ + if (ssize < HALF_MAX_SIZE_T && + (br = (char*)(CALL_MORECORE(ssize))) == ss->base+ss->size) { + tbase = br; + tsize = ssize; + } + } + + if (tbase == CMFAIL) { /* Cope with partial failure */ + if (br != CMFAIL) { /* Try to use/extend the space we did get */ + if (ssize < HALF_MAX_SIZE_T && + ssize < nb + SYS_ALLOC_PADDING) { + size_t esize = granularity_align(nb + SYS_ALLOC_PADDING - ssize); + if (esize < HALF_MAX_SIZE_T) { + char* end = (char*)CALL_MORECORE(esize); + if (end != CMFAIL) + ssize += esize; + else { /* Can't use; try to release */ + (void) CALL_MORECORE(-ssize); + br = CMFAIL; + } + } + } + } + if (br != CMFAIL) { /* Use the space we did get */ + tbase = br; + tsize = ssize; + } + else + disable_contiguous(m); /* Don't try contiguous path in the future */ + } + + RELEASE_MALLOC_GLOBAL_LOCK(); + } + + if (HAVE_MMAP && tbase == CMFAIL) { /* Try MMAP */ + char* mp = (char*)(CALL_MMAP(asize)); + if (mp != CMFAIL) { + tbase = mp; + tsize = asize; + mmap_flag = USE_MMAP_BIT; + } + } + + if (HAVE_MORECORE && tbase == CMFAIL) { /* Try noncontiguous MORECORE */ + if (asize < HALF_MAX_SIZE_T) { + char* br = CMFAIL; + char* end = CMFAIL; + ACQUIRE_MALLOC_GLOBAL_LOCK(); + br = (char*)(CALL_MORECORE(asize)); + end = (char*)(CALL_MORECORE(0)); + RELEASE_MALLOC_GLOBAL_LOCK(); + if (br != CMFAIL && end != CMFAIL && br < end) { + size_t ssize = end - br; + if (ssize > nb + TOP_FOOT_SIZE) { + tbase = br; + tsize = ssize; + } + } + } + } + + if (tbase != CMFAIL) { + + if ((m->footprint += tsize) > m->max_footprint) + m->max_footprint = m->footprint; + + if (!is_initialized(m)) { /* first-time initialization */ + if (m->least_addr == 0 || tbase < m->least_addr) + m->least_addr = tbase; + m->seg.base = tbase; + m->seg.size = tsize; + m->seg.sflags = mmap_flag; + m->magic = mparams.magic; + m->release_checks = MAX_RELEASE_CHECK_RATE; + init_bins(m); +#if !ONLY_MSPACES + if (is_global(m)) + init_top(m, (mchunkptr)tbase, tsize - TOP_FOOT_SIZE); + else +#endif + { + /* Offset top by embedded malloc_state */ + mchunkptr mn = next_chunk(mem2chunk(m)); + init_top(m, mn, (size_t)((tbase + tsize) - (char*)mn) -TOP_FOOT_SIZE); + } + } + + else { + /* Try to merge with an existing segment */ + msegmentptr sp = &m->seg; + /* Only consider most recent segment if traversal suppressed */ + while (sp != 0 && tbase != sp->base + sp->size) + sp = (NO_SEGMENT_TRAVERSAL) ? 0 : sp->next; + if (sp != 0 && + !is_extern_segment(sp) && + (sp->sflags & USE_MMAP_BIT) == mmap_flag && + segment_holds(sp, m->top)) { /* append */ + sp->size += tsize; + init_top(m, m->top, m->topsize + tsize); + } + else { + if (tbase < m->least_addr) + m->least_addr = tbase; + sp = &m->seg; + while (sp != 0 && sp->base != tbase + tsize) + sp = (NO_SEGMENT_TRAVERSAL) ? 0 : sp->next; + if (sp != 0 && + !is_extern_segment(sp) && + (sp->sflags & USE_MMAP_BIT) == mmap_flag) { + char* oldbase = sp->base; + sp->base = tbase; + sp->size += tsize; + return prepend_alloc(m, tbase, oldbase, nb); + } + else + add_segment(m, tbase, tsize, mmap_flag); + } + } + + if (nb < m->topsize) { /* Allocate from new or extended top space */ + size_t rsize = m->topsize -= nb; + mchunkptr p = m->top; + mchunkptr r = m->top = chunk_plus_offset(p, nb); + r->head = rsize | PINUSE_BIT; + set_size_and_pinuse_of_inuse_chunk(m, p, nb); + check_top_chunk(m, m->top); + check_malloced_chunk(m, chunk2mem(p), nb); + return chunk2mem(p); + } + } + + MALLOC_FAILURE_ACTION; + return 0; +} + +/* ----------------------- system deallocation -------------------------- */ + +/* Unmap and unlink any mmapped segments that don't contain used chunks */ +static size_t release_unused_segments(mstate m) { + size_t released = 0; + int nsegs = 0; + msegmentptr pred = &m->seg; + msegmentptr sp = pred->next; + while (sp != 0) { + char* base = sp->base; + size_t size = sp->size; + msegmentptr next = sp->next; + ++nsegs; + if (is_mmapped_segment(sp) && !is_extern_segment(sp)) { + mchunkptr p = align_as_chunk(base); + size_t psize = chunksize(p); + /* Can unmap if first chunk holds entire segment and not pinned */ + if (!is_inuse(p) && (char*)p + psize >= base + size - TOP_FOOT_SIZE) { + tchunkptr tp = (tchunkptr)p; + assert(segment_holds(sp, (char*)sp)); + if (p == m->dv) { + m->dv = 0; + m->dvsize = 0; + } + else { + unlink_large_chunk(m, tp); + } + if (CALL_MUNMAP(base, size) == 0) { + released += size; + m->footprint -= size; + /* unlink obsoleted record */ + sp = pred; + sp->next = next; + } + else { /* back out if cannot unmap */ + insert_large_chunk(m, tp, psize); + } + } + } + if (NO_SEGMENT_TRAVERSAL) /* scan only first segment */ + break; + pred = sp; + sp = next; + } + /* Reset check counter */ + m->release_checks = (((size_t) nsegs > (size_t) MAX_RELEASE_CHECK_RATE)? + (size_t) nsegs : (size_t) MAX_RELEASE_CHECK_RATE); + return released; +} + +static int sys_trim(mstate m, size_t pad) { + size_t released = 0; + ensure_initialization(); + if (pad < MAX_REQUEST && is_initialized(m)) { + pad += TOP_FOOT_SIZE; /* ensure enough room for segment overhead */ + + if (m->topsize > pad) { + /* Shrink top space in granularity-size units, keeping at least one */ + size_t unit = mparams.granularity; + size_t extra = ((m->topsize - pad + (unit - SIZE_T_ONE)) / unit - + SIZE_T_ONE) * unit; + msegmentptr sp = segment_holding(m, (char*)m->top); + + if (!is_extern_segment(sp)) { + if (is_mmapped_segment(sp)) { + if (HAVE_MMAP && + sp->size >= extra && + !has_segment_link(m, sp)) { /* can't shrink if pinned */ + size_t newsize = sp->size - extra; + (void)newsize; /* placate people compiling -Wunused-variable */ + /* Prefer mremap, fall back to munmap */ + if ((CALL_MREMAP(sp->base, sp->size, newsize, 0) != MFAIL) || + (CALL_MUNMAP(sp->base + newsize, extra) == 0)) { + released = extra; + } + } + } + else if (HAVE_MORECORE) { + if (extra >= HALF_MAX_SIZE_T) /* Avoid wrapping negative */ + extra = (HALF_MAX_SIZE_T) + SIZE_T_ONE - unit; + ACQUIRE_MALLOC_GLOBAL_LOCK(); + { + /* Make sure end of memory is where we last set it. */ + char* old_br = (char*)(CALL_MORECORE(0)); + if (old_br == sp->base + sp->size) { + char* rel_br = (char*)(CALL_MORECORE(-extra)); + char* new_br = (char*)(CALL_MORECORE(0)); + if (rel_br != CMFAIL && new_br < old_br) + released = old_br - new_br; + } + } + RELEASE_MALLOC_GLOBAL_LOCK(); + } + } + + if (released != 0) { + sp->size -= released; + m->footprint -= released; + init_top(m, m->top, m->topsize - released); + check_top_chunk(m, m->top); + } + } + + /* Unmap any unused mmapped segments */ + if (HAVE_MMAP) + released += release_unused_segments(m); + + /* On failure, disable autotrim to avoid repeated failed future calls */ + if (released == 0 && m->topsize > m->trim_check) + m->trim_check = MAX_SIZE_T; + } + + return (released != 0)? 1 : 0; +} + +/* Consolidate and bin a chunk. Differs from exported versions + of free mainly in that the chunk need not be marked as inuse. +*/ +static void dispose_chunk(mstate m, mchunkptr p, size_t psize) { + mchunkptr next = chunk_plus_offset(p, psize); + if (!pinuse(p)) { + mchunkptr prev; + size_t prevsize = p->prev_foot; + if (is_mmapped(p)) { + psize += prevsize + MMAP_FOOT_PAD; + if (CALL_MUNMAP((char*)p - prevsize, psize) == 0) + m->footprint -= psize; + return; + } + prev = chunk_minus_offset(p, prevsize); + psize += prevsize; + p = prev; + if (RTCHECK(ok_address(m, prev))) { /* consolidate backward */ + if (p != m->dv) { + unlink_chunk(m, p, prevsize); + } + else if ((next->head & INUSE_BITS) == INUSE_BITS) { + m->dvsize = psize; + set_free_with_pinuse(p, psize, next); + return; + } + } + else { + CORRUPTION_ERROR_ACTION(m); + return; + } + } + if (RTCHECK(ok_address(m, next))) { + if (!cinuse(next)) { /* consolidate forward */ + if (next == m->top) { + size_t tsize = m->topsize += psize; + m->top = p; + p->head = tsize | PINUSE_BIT; + if (p == m->dv) { + m->dv = 0; + m->dvsize = 0; + } + return; + } + else if (next == m->dv) { + size_t dsize = m->dvsize += psize; + m->dv = p; + set_size_and_pinuse_of_free_chunk(p, dsize); + return; + } + else { + size_t nsize = chunksize(next); + psize += nsize; + unlink_chunk(m, next, nsize); + set_size_and_pinuse_of_free_chunk(p, psize); + if (p == m->dv) { + m->dvsize = psize; + return; + } + } + } + else { + set_free_with_pinuse(p, psize, next); + } + insert_chunk(m, p, psize); + } + else { + CORRUPTION_ERROR_ACTION(m); + } +} + +/* ---------------------------- malloc --------------------------- */ + +/* allocate a large request from the best fitting chunk in a treebin */ +static void* tmalloc_large(mstate m, size_t nb) { + tchunkptr v = 0; + size_t rsize = -nb; /* Unsigned negation */ + tchunkptr t; + bindex_t idx; + compute_tree_index(nb, idx); + if ((t = *treebin_at(m, idx)) != 0) { + /* Traverse tree for this bin looking for node with size == nb */ + size_t sizebits = nb << leftshift_for_tree_index(idx); + tchunkptr rst = 0; /* The deepest untaken right subtree */ + for (;;) { + tchunkptr rt; + size_t trem = chunksize(t) - nb; + if (trem < rsize) { + v = t; + if ((rsize = trem) == 0) + break; + } + rt = t->child[1]; + t = t->child[(sizebits >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1]; + if (rt != 0 && rt != t) + rst = rt; + if (t == 0) { + t = rst; /* set t to least subtree holding sizes > nb */ + break; + } + sizebits <<= 1; + } + } + if (t == 0 && v == 0) { /* set t to root of next non-empty treebin */ + binmap_t leftbits = left_bits(idx2bit(idx)) & m->treemap; + if (leftbits != 0) { + bindex_t i; + binmap_t leastbit = least_bit(leftbits); + compute_bit2idx(leastbit, i); + t = *treebin_at(m, i); + } + } + + while (t != 0) { /* find smallest of tree or subtree */ + size_t trem = chunksize(t) - nb; + if (trem < rsize) { + rsize = trem; + v = t; + } + t = leftmost_child(t); + } + + /* If dv is a better fit, return 0 so malloc will use it */ + if (v != 0 && rsize < (size_t)(m->dvsize - nb)) { + if (RTCHECK(ok_address(m, v))) { /* split */ + mchunkptr r = chunk_plus_offset(v, nb); + assert(chunksize(v) == rsize + nb); + if (RTCHECK(ok_next(v, r))) { + unlink_large_chunk(m, v); + if (rsize < MIN_CHUNK_SIZE) + set_inuse_and_pinuse(m, v, (rsize + nb)); + else { + set_size_and_pinuse_of_inuse_chunk(m, v, nb); + set_size_and_pinuse_of_free_chunk(r, rsize); + insert_chunk(m, r, rsize); + } + return chunk2mem(v); + } + } + CORRUPTION_ERROR_ACTION(m); + } + return 0; +} + +/* allocate a small request from the best fitting chunk in a treebin */ +static void* tmalloc_small(mstate m, size_t nb) { + tchunkptr t, v; + size_t rsize; + bindex_t i; + binmap_t leastbit = least_bit(m->treemap); + compute_bit2idx(leastbit, i); + v = t = *treebin_at(m, i); + rsize = chunksize(t) - nb; + + while ((t = leftmost_child(t)) != 0) { + size_t trem = chunksize(t) - nb; + if (trem < rsize) { + rsize = trem; + v = t; + } + } + + if (RTCHECK(ok_address(m, v))) { + mchunkptr r = chunk_plus_offset(v, nb); + assert(chunksize(v) == rsize + nb); + if (RTCHECK(ok_next(v, r))) { + unlink_large_chunk(m, v); + if (rsize < MIN_CHUNK_SIZE) + set_inuse_and_pinuse(m, v, (rsize + nb)); + else { + set_size_and_pinuse_of_inuse_chunk(m, v, nb); + set_size_and_pinuse_of_free_chunk(r, rsize); + replace_dv(m, r, rsize); + } + return chunk2mem(v); + } + } + + CORRUPTION_ERROR_ACTION(m); + return 0; +} + +#if !ONLY_MSPACES + +void* dlmalloc(size_t bytes) { + /* + Basic algorithm: + If a small request (< 256 bytes minus per-chunk overhead): + 1. If one exists, use a remainderless chunk in associated smallbin. + (Remainderless means that there are too few excess bytes to + represent as a chunk.) + 2. If it is big enough, use the dv chunk, which is normally the + chunk adjacent to the one used for the most recent small request. + 3. If one exists, split the smallest available chunk in a bin, + saving remainder in dv. + 4. If it is big enough, use the top chunk. + 5. If available, get memory from system and use it + Otherwise, for a large request: + 1. Find the smallest available binned chunk that fits, and use it + if it is better fitting than dv chunk, splitting if necessary. + 2. If better fitting than any binned chunk, use the dv chunk. + 3. If it is big enough, use the top chunk. + 4. If request size >= mmap threshold, try to directly mmap this chunk. + 5. If available, get memory from system and use it + + The ugly goto's here ensure that postaction occurs along all paths. + */ + +#if USE_LOCKS + ensure_initialization(); /* initialize in sys_alloc if not using locks */ +#endif + + if (!PREACTION(gm)) { + void* mem; + size_t nb; + if (bytes <= MAX_SMALL_REQUEST) { + bindex_t idx; + binmap_t smallbits; + nb = (bytes < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(bytes); + idx = small_index(nb); + smallbits = gm->smallmap >> idx; + + if ((smallbits & 0x3U) != 0) { /* Remainderless fit to a smallbin. */ + mchunkptr b, p; + idx += ~smallbits & 1; /* Uses next bin if idx empty */ + b = smallbin_at(gm, idx); + p = b->fd; + assert(chunksize(p) == small_index2size(idx)); + unlink_first_small_chunk(gm, b, p, idx); + set_inuse_and_pinuse(gm, p, small_index2size(idx)); + mem = chunk2mem(p); + check_malloced_chunk(gm, mem, nb); + goto postaction; + } + + else if (nb > gm->dvsize) { + if (smallbits != 0) { /* Use chunk in next nonempty smallbin */ + mchunkptr b, p, r; + size_t rsize; + bindex_t i; + binmap_t leftbits = (smallbits << idx) & left_bits(idx2bit(idx)); + binmap_t leastbit = least_bit(leftbits); + compute_bit2idx(leastbit, i); + b = smallbin_at(gm, i); + p = b->fd; + assert(chunksize(p) == small_index2size(i)); + unlink_first_small_chunk(gm, b, p, i); + rsize = small_index2size(i) - nb; + /* Fit here cannot be remainderless if 4byte sizes */ + if (SIZE_T_SIZE != 4 && rsize < MIN_CHUNK_SIZE) + set_inuse_and_pinuse(gm, p, small_index2size(i)); + else { + set_size_and_pinuse_of_inuse_chunk(gm, p, nb); + r = chunk_plus_offset(p, nb); + set_size_and_pinuse_of_free_chunk(r, rsize); + replace_dv(gm, r, rsize); + } + mem = chunk2mem(p); + check_malloced_chunk(gm, mem, nb); + goto postaction; + } + + else if (gm->treemap != 0 && (mem = tmalloc_small(gm, nb)) != 0) { + check_malloced_chunk(gm, mem, nb); + goto postaction; + } + } + } + else if (bytes >= MAX_REQUEST) + nb = MAX_SIZE_T; /* Too big to allocate. Force failure (in sys alloc) */ + else { + nb = pad_request(bytes); + if (gm->treemap != 0 && (mem = tmalloc_large(gm, nb)) != 0) { + check_malloced_chunk(gm, mem, nb); + goto postaction; + } + } + + if (nb <= gm->dvsize) { + size_t rsize = gm->dvsize - nb; + mchunkptr p = gm->dv; + if (rsize >= MIN_CHUNK_SIZE) { /* split dv */ + mchunkptr r = gm->dv = chunk_plus_offset(p, nb); + gm->dvsize = rsize; + set_size_and_pinuse_of_free_chunk(r, rsize); + set_size_and_pinuse_of_inuse_chunk(gm, p, nb); + } + else { /* exhaust dv */ + size_t dvs = gm->dvsize; + gm->dvsize = 0; + gm->dv = 0; + set_inuse_and_pinuse(gm, p, dvs); + } + mem = chunk2mem(p); + check_malloced_chunk(gm, mem, nb); + goto postaction; + } + + else if (nb < gm->topsize) { /* Split top */ + size_t rsize = gm->topsize -= nb; + mchunkptr p = gm->top; + mchunkptr r = gm->top = chunk_plus_offset(p, nb); + r->head = rsize | PINUSE_BIT; + set_size_and_pinuse_of_inuse_chunk(gm, p, nb); + mem = chunk2mem(p); + check_top_chunk(gm, gm->top); + check_malloced_chunk(gm, mem, nb); + goto postaction; + } + + mem = sys_alloc(gm, nb); + + postaction: + POSTACTION(gm); + return mem; + } + + return 0; +} + +/* ---------------------------- free --------------------------- */ + +void dlfree(void* mem) { + /* + Consolidate freed chunks with preceeding or succeeding bordering + free chunks, if they exist, and then place in a bin. Intermixed + with special cases for top, dv, mmapped chunks, and usage errors. + */ + + if (mem != 0) { + mchunkptr p = mem2chunk(mem); +#if FOOTERS + mstate fm = get_mstate_for(p); + if (!ok_magic(fm)) { + USAGE_ERROR_ACTION(fm, p); + return; + } +#else /* FOOTERS */ +#define fm gm +#endif /* FOOTERS */ + if (!PREACTION(fm)) { + check_inuse_chunk(fm, p); + if (RTCHECK(ok_address(fm, p) && ok_inuse(p))) { + size_t psize = chunksize(p); + mchunkptr next = chunk_plus_offset(p, psize); + if (!pinuse(p)) { + size_t prevsize = p->prev_foot; + if (is_mmapped(p)) { + psize += prevsize + MMAP_FOOT_PAD; + if (CALL_MUNMAP((char*)p - prevsize, psize) == 0) + fm->footprint -= psize; + goto postaction; + } + else { + mchunkptr prev = chunk_minus_offset(p, prevsize); + psize += prevsize; + p = prev; + if (RTCHECK(ok_address(fm, prev))) { /* consolidate backward */ + if (p != fm->dv) { + unlink_chunk(fm, p, prevsize); + } + else if ((next->head & INUSE_BITS) == INUSE_BITS) { + fm->dvsize = psize; + set_free_with_pinuse(p, psize, next); + goto postaction; + } + } + else + goto erroraction; + } + } + + if (RTCHECK(ok_next(p, next) && ok_pinuse(next))) { + if (!cinuse(next)) { /* consolidate forward */ + if (next == fm->top) { + size_t tsize = fm->topsize += psize; + fm->top = p; + p->head = tsize | PINUSE_BIT; + if (p == fm->dv) { + fm->dv = 0; + fm->dvsize = 0; + } + if (should_trim(fm, tsize)) + sys_trim(fm, 0); + goto postaction; + } + else if (next == fm->dv) { + size_t dsize = fm->dvsize += psize; + fm->dv = p; + set_size_and_pinuse_of_free_chunk(p, dsize); + goto postaction; + } + else { + size_t nsize = chunksize(next); + psize += nsize; + unlink_chunk(fm, next, nsize); + set_size_and_pinuse_of_free_chunk(p, psize); + if (p == fm->dv) { + fm->dvsize = psize; + goto postaction; + } + } + } + else + set_free_with_pinuse(p, psize, next); + + if (is_small(psize)) { + insert_small_chunk(fm, p, psize); + check_free_chunk(fm, p); + } + else { + tchunkptr tp = (tchunkptr)p; + insert_large_chunk(fm, tp, psize); + check_free_chunk(fm, p); + if (--fm->release_checks == 0) + release_unused_segments(fm); + } + goto postaction; + } + } + erroraction: + USAGE_ERROR_ACTION(fm, p); + postaction: + POSTACTION(fm); + } + } +#if !FOOTERS +#undef fm +#endif /* FOOTERS */ +} + +void* dlcalloc(size_t n_elements, size_t elem_size) { + void* mem; + size_t req = 0; + if (n_elements != 0) { + req = n_elements * elem_size; + if (((n_elements | elem_size) & ~(size_t)0xffff) && + (req / n_elements != elem_size)) + req = MAX_SIZE_T; /* force downstream failure on overflow */ + } + mem = dlmalloc(req); + if (mem != 0 && calloc_must_clear(mem2chunk(mem))) + memset(mem, 0, req); + return mem; +} + +#endif /* !ONLY_MSPACES */ + +/* ------------ Internal support for realloc, memalign, etc -------------- */ + +/* Try to realloc; only in-place unless can_move true */ +static mchunkptr try_realloc_chunk(mstate m, mchunkptr p, size_t nb, + int can_move) { + mchunkptr newp = 0; + size_t oldsize = chunksize(p); + mchunkptr next = chunk_plus_offset(p, oldsize); + if (RTCHECK(ok_address(m, p) && ok_inuse(p) && + ok_next(p, next) && ok_pinuse(next))) { + if (is_mmapped(p)) { + newp = mmap_resize(m, p, nb, can_move); + } + else if (oldsize >= nb) { /* already big enough */ + size_t rsize = oldsize - nb; + if (rsize >= MIN_CHUNK_SIZE) { /* split off remainder */ + mchunkptr r = chunk_plus_offset(p, nb); + set_inuse(m, p, nb); + set_inuse(m, r, rsize); + dispose_chunk(m, r, rsize); + } + newp = p; + } + else if (next == m->top) { /* extend into top */ + if (oldsize + m->topsize > nb) { + size_t newsize = oldsize + m->topsize; + size_t newtopsize = newsize - nb; + mchunkptr newtop = chunk_plus_offset(p, nb); + set_inuse(m, p, nb); + newtop->head = newtopsize |PINUSE_BIT; + m->top = newtop; + m->topsize = newtopsize; + newp = p; + } + } + else if (next == m->dv) { /* extend into dv */ + size_t dvs = m->dvsize; + if (oldsize + dvs >= nb) { + size_t dsize = oldsize + dvs - nb; + if (dsize >= MIN_CHUNK_SIZE) { + mchunkptr r = chunk_plus_offset(p, nb); + mchunkptr n = chunk_plus_offset(r, dsize); + set_inuse(m, p, nb); + set_size_and_pinuse_of_free_chunk(r, dsize); + clear_pinuse(n); + m->dvsize = dsize; + m->dv = r; + } + else { /* exhaust dv */ + size_t newsize = oldsize + dvs; + set_inuse(m, p, newsize); + m->dvsize = 0; + m->dv = 0; + } + newp = p; + } + } + else if (!cinuse(next)) { /* extend into next free chunk */ + size_t nextsize = chunksize(next); + if (oldsize + nextsize >= nb) { + size_t rsize = oldsize + nextsize - nb; + unlink_chunk(m, next, nextsize); + if (rsize < MIN_CHUNK_SIZE) { + size_t newsize = oldsize + nextsize; + set_inuse(m, p, newsize); + } + else { + mchunkptr r = chunk_plus_offset(p, nb); + set_inuse(m, p, nb); + set_inuse(m, r, rsize); + dispose_chunk(m, r, rsize); + } + newp = p; + } + } + } + else { + USAGE_ERROR_ACTION(m, chunk2mem(p)); + } + return newp; +} + +static void* internal_memalign(mstate m, size_t alignment, size_t bytes) { + void* mem = 0; + if (alignment < MIN_CHUNK_SIZE) /* must be at least a minimum chunk size */ + alignment = MIN_CHUNK_SIZE; + if ((alignment & (alignment-SIZE_T_ONE)) != 0) {/* Ensure a power of 2 */ + size_t a = MALLOC_ALIGNMENT << 1; + while (a < alignment) a <<= 1; + alignment = a; + } + if (bytes >= MAX_REQUEST - alignment) { + if (m != 0) { /* Test isn't needed but avoids compiler warning */ + MALLOC_FAILURE_ACTION; + } + } + else { + size_t nb = request2size(bytes); + size_t req = nb + alignment + MIN_CHUNK_SIZE - CHUNK_OVERHEAD; + mem = internal_malloc(m, req); + if (mem != 0) { + mchunkptr p = mem2chunk(mem); + if (PREACTION(m)) + return 0; + if ((((size_t)(mem)) & (alignment - 1)) != 0) { /* misaligned */ + /* + Find an aligned spot inside chunk. Since we need to give + back leading space in a chunk of at least MIN_CHUNK_SIZE, if + the first calculation places us at a spot with less than + MIN_CHUNK_SIZE leader, we can move to the next aligned spot. + We've allocated enough total room so that this is always + possible. + */ + char* br = (char*)mem2chunk((size_t)(((size_t)((char*)mem + alignment - + SIZE_T_ONE)) & + -alignment)); + char* pos = ((size_t)(br - (char*)(p)) >= MIN_CHUNK_SIZE)? + br : br+alignment; + mchunkptr newp = (mchunkptr)pos; + size_t leadsize = pos - (char*)(p); + size_t newsize = chunksize(p) - leadsize; + + if (is_mmapped(p)) { /* For mmapped chunks, just adjust offset */ + newp->prev_foot = p->prev_foot + leadsize; + newp->head = newsize; + } + else { /* Otherwise, give back leader, use the rest */ + set_inuse(m, newp, newsize); + set_inuse(m, p, leadsize); + dispose_chunk(m, p, leadsize); + } + p = newp; + } + + /* Give back spare room at the end */ + if (!is_mmapped(p)) { + size_t size = chunksize(p); + if (size > nb + MIN_CHUNK_SIZE) { + size_t remainder_size = size - nb; + mchunkptr remainder = chunk_plus_offset(p, nb); + set_inuse(m, p, nb); + set_inuse(m, remainder, remainder_size); + dispose_chunk(m, remainder, remainder_size); + } + } + + mem = chunk2mem(p); + assert (chunksize(p) >= nb); + assert(((size_t)mem & (alignment - 1)) == 0); + check_inuse_chunk(m, p); + POSTACTION(m); + } + } + return mem; +} + +/* + Common support for independent_X routines, handling + all of the combinations that can result. + The opts arg has: + bit 0 set if all elements are same size (using sizes[0]) + bit 1 set if elements should be zeroed +*/ +static void** ialloc(mstate m, + size_t n_elements, + size_t* sizes, + int opts, + void* chunks[]) { + + size_t element_size; /* chunksize of each element, if all same */ + size_t contents_size; /* total size of elements */ + size_t array_size; /* request size of pointer array */ + void* mem; /* malloced aggregate space */ + mchunkptr p; /* corresponding chunk */ + size_t remainder_size; /* remaining bytes while splitting */ + void** marray; /* either "chunks" or malloced ptr array */ + mchunkptr array_chunk; /* chunk for malloced ptr array */ + flag_t was_enabled; /* to disable mmap */ + size_t size; + size_t i; + + ensure_initialization(); + /* compute array length, if needed */ + if (chunks != 0) { + if (n_elements == 0) + return chunks; /* nothing to do */ + marray = chunks; + array_size = 0; + } + else { + /* if empty req, must still return chunk representing empty array */ + if (n_elements == 0) + return (void**)internal_malloc(m, 0); + marray = 0; + array_size = request2size(n_elements * (sizeof(void*))); + } + + /* compute total element size */ + if (opts & 0x1) { /* all-same-size */ + element_size = request2size(*sizes); + contents_size = n_elements * element_size; + } + else { /* add up all the sizes */ + element_size = 0; + contents_size = 0; + for (i = 0; i != n_elements; ++i) + contents_size += request2size(sizes[i]); + } + + size = contents_size + array_size; + + /* + Allocate the aggregate chunk. First disable direct-mmapping so + malloc won't use it, since we would not be able to later + free/realloc space internal to a segregated mmap region. + */ + was_enabled = use_mmap(m); + disable_mmap(m); + mem = internal_malloc(m, size - CHUNK_OVERHEAD); + if (was_enabled) + enable_mmap(m); + if (mem == 0) + return 0; + + if (PREACTION(m)) return 0; + p = mem2chunk(mem); + remainder_size = chunksize(p); + + assert(!is_mmapped(p)); + + if (opts & 0x2) { /* optionally clear the elements */ + memset((size_t*)mem, 0, remainder_size - SIZE_T_SIZE - array_size); + } + + /* If not provided, allocate the pointer array as final part of chunk */ + if (marray == 0) { + size_t array_chunk_size; + array_chunk = chunk_plus_offset(p, contents_size); + array_chunk_size = remainder_size - contents_size; + marray = (void**) (chunk2mem(array_chunk)); + set_size_and_pinuse_of_inuse_chunk(m, array_chunk, array_chunk_size); + remainder_size = contents_size; + } + + /* split out elements */ + for (i = 0; ; ++i) { + marray[i] = chunk2mem(p); + if (i != n_elements-1) { + if (element_size != 0) + size = element_size; + else + size = request2size(sizes[i]); + remainder_size -= size; + set_size_and_pinuse_of_inuse_chunk(m, p, size); + p = chunk_plus_offset(p, size); + } + else { /* the final element absorbs any overallocation slop */ + set_size_and_pinuse_of_inuse_chunk(m, p, remainder_size); + break; + } + } + +#if DEBUG + if (marray != chunks) { + /* final element must have exactly exhausted chunk */ + if (element_size != 0) { + assert(remainder_size == element_size); + } + else { + assert(remainder_size == request2size(sizes[i])); + } + check_inuse_chunk(m, mem2chunk(marray)); + } + for (i = 0; i != n_elements; ++i) + check_inuse_chunk(m, mem2chunk(marray[i])); + +#endif /* DEBUG */ + + POSTACTION(m); + return marray; +} + +/* Try to free all pointers in the given array. + Note: this could be made faster, by delaying consolidation, + at the price of disabling some user integrity checks, We + still optimize some consolidations by combining adjacent + chunks before freeing, which will occur often if allocated + with ialloc or the array is sorted. +*/ +static size_t internal_bulk_free(mstate m, void* array[], size_t nelem) { + size_t unfreed = 0; + if (!PREACTION(m)) { + void** a; + void** fence = &(array[nelem]); + for (a = array; a != fence; ++a) { + void* mem = *a; + if (mem != 0) { + mchunkptr p = mem2chunk(mem); + size_t psize = chunksize(p); +#if FOOTERS + if (get_mstate_for(p) != m) { + ++unfreed; + continue; + } +#endif + check_inuse_chunk(m, p); + *a = 0; + if (RTCHECK(ok_address(m, p) && ok_inuse(p))) { + void ** b = a + 1; /* try to merge with next chunk */ + mchunkptr next = next_chunk(p); + if (b != fence && *b == chunk2mem(next)) { + size_t newsize = chunksize(next) + psize; + set_inuse(m, p, newsize); + *b = chunk2mem(p); + } + else + dispose_chunk(m, p, psize); + } + else { + CORRUPTION_ERROR_ACTION(m); + break; + } + } + } + if (should_trim(m, m->topsize)) + sys_trim(m, 0); + POSTACTION(m); + } + return unfreed; +} + +/* Traversal */ +#if MALLOC_INSPECT_ALL +static void internal_inspect_all(mstate m, + void(*handler)(void *start, + void *end, + size_t used_bytes, + void* callback_arg), + void* arg) { + if (is_initialized(m)) { + mchunkptr top = m->top; + msegmentptr s; + for (s = &m->seg; s != 0; s = s->next) { + mchunkptr q = align_as_chunk(s->base); + while (segment_holds(s, q) && q->head != FENCEPOST_HEAD) { + mchunkptr next = next_chunk(q); + size_t sz = chunksize(q); + size_t used; + void* start; + if (is_inuse(q)) { + used = sz - CHUNK_OVERHEAD; /* must not be mmapped */ + start = chunk2mem(q); + } + else { + used = 0; + if (is_small(sz)) { /* offset by possible bookkeeping */ + start = (void*)((char*)q + sizeof(struct malloc_chunk)); + } + else { + start = (void*)((char*)q + sizeof(struct malloc_tree_chunk)); + } + } + if (start < (void*)next) /* skip if all space is bookkeeping */ + handler(start, next, used, arg); + if (q == top) + break; + q = next; + } + } + } +} +#endif /* MALLOC_INSPECT_ALL */ + +/* ------------------ Exported realloc, memalign, etc -------------------- */ + +#if !ONLY_MSPACES + +void* dlrealloc(void* oldmem, size_t bytes) { + void* mem = 0; + if (oldmem == 0) { + mem = dlmalloc(bytes); + } + else if (bytes >= MAX_REQUEST) { + MALLOC_FAILURE_ACTION; + } +#ifdef REALLOC_ZERO_BYTES_FREES + else if (bytes == 0) { + dlfree(oldmem); + } +#endif /* REALLOC_ZERO_BYTES_FREES */ + else { + size_t nb = request2size(bytes); + mchunkptr oldp = mem2chunk(oldmem); +#if ! FOOTERS + mstate m = gm; +#else /* FOOTERS */ + mstate m = get_mstate_for(oldp); + if (!ok_magic(m)) { + USAGE_ERROR_ACTION(m, oldmem); + return 0; + } +#endif /* FOOTERS */ + if (!PREACTION(m)) { + mchunkptr newp = try_realloc_chunk(m, oldp, nb, 1); + POSTACTION(m); + if (newp != 0) { + check_inuse_chunk(m, newp); + mem = chunk2mem(newp); + } + else { + mem = internal_malloc(m, bytes); + if (mem != 0) { + size_t oc = chunksize(oldp) - overhead_for(oldp); + memcpy(mem, oldmem, (oc < bytes)? oc : bytes); + internal_free(m, oldmem); + } + } + } + } + return mem; +} + +void* dlrealloc_in_place(void* oldmem, size_t bytes) { + void* mem = 0; + if (oldmem != 0) { + if (bytes >= MAX_REQUEST) { + MALLOC_FAILURE_ACTION; + } + else { + size_t nb = request2size(bytes); + mchunkptr oldp = mem2chunk(oldmem); +#if ! FOOTERS + mstate m = gm; +#else /* FOOTERS */ + mstate m = get_mstate_for(oldp); + if (!ok_magic(m)) { + USAGE_ERROR_ACTION(m, oldmem); + return 0; + } +#endif /* FOOTERS */ + if (!PREACTION(m)) { + mchunkptr newp = try_realloc_chunk(m, oldp, nb, 0); + POSTACTION(m); + if (newp == oldp) { + check_inuse_chunk(m, newp); + mem = oldmem; + } + } + } + } + return mem; +} + +void* dlmemalign(size_t alignment, size_t bytes) { + if (alignment <= MALLOC_ALIGNMENT) { + return dlmalloc(bytes); + } + return internal_memalign(gm, alignment, bytes); +} + +void* dlaligned_alloc(size_t alignment, size_t size) { + if (size % alignment) + return NULL; + return dlmemalign(alignment, size); +} + +int dlposix_memalign(void** pp, size_t alignment, size_t bytes) { + void* mem = 0; + if (alignment == MALLOC_ALIGNMENT) + mem = dlmalloc(bytes); + else { + size_t d = alignment / sizeof(void*); + size_t r = alignment % sizeof(void*); + if (r != 0 || d == 0 || (d & (d-SIZE_T_ONE)) != 0) + return EINVAL; + else if (bytes <= MAX_REQUEST - alignment) { + if (alignment < MIN_CHUNK_SIZE) + alignment = MIN_CHUNK_SIZE; + mem = internal_memalign(gm, alignment, bytes); + } + } + if (mem == 0) + return ENOMEM; + else { + *pp = mem; + return 0; + } +} + +void* dlvalloc(size_t bytes) { + size_t pagesz; + ensure_initialization(); + pagesz = mparams.page_size; + return dlmemalign(pagesz, bytes); +} + +void* dlpvalloc(size_t bytes) { + size_t pagesz; + ensure_initialization(); + pagesz = mparams.page_size; + return dlmemalign(pagesz, (bytes + pagesz - SIZE_T_ONE) & ~(pagesz - SIZE_T_ONE)); +} + +void** dlindependent_calloc(size_t n_elements, size_t elem_size, + void* chunks[]) { + size_t sz = elem_size; /* serves as 1-element array */ + return ialloc(gm, n_elements, &sz, 3, chunks); +} + +void** dlindependent_comalloc(size_t n_elements, size_t sizes[], + void* chunks[]) { + return ialloc(gm, n_elements, sizes, 0, chunks); +} + +size_t dlbulk_free(void* array[], size_t nelem) { + return internal_bulk_free(gm, array, nelem); +} + +#if MALLOC_INSPECT_ALL +void dlmalloc_inspect_all(void(*handler)(void *start, + void *end, + size_t used_bytes, + void* callback_arg), + void* arg) { + ensure_initialization(); + if (!PREACTION(gm)) { + internal_inspect_all(gm, handler, arg); + POSTACTION(gm); + } +} +#endif /* MALLOC_INSPECT_ALL */ + +int dlmalloc_trim(size_t pad) { + int result = 0; + ensure_initialization(); + if (!PREACTION(gm)) { + result = sys_trim(gm, pad); + POSTACTION(gm); + } + return result; +} + +size_t dlmalloc_footprint(void) { + return gm->footprint; +} + +size_t dlmalloc_max_footprint(void) { + return gm->max_footprint; +} + +size_t dlmalloc_footprint_limit(void) { + size_t maf = gm->footprint_limit; + return maf == 0 ? MAX_SIZE_T : maf; +} + +size_t dlmalloc_set_footprint_limit(size_t bytes) { + size_t result; /* invert sense of 0 */ + if (bytes == 0) + result = granularity_align(1); /* Use minimal size */ + if (bytes == MAX_SIZE_T) + result = 0; /* disable */ + else + result = granularity_align(bytes); + return gm->footprint_limit = result; +} + +#if !NO_MALLINFO +struct mallinfo dlmallinfo(void) { + return internal_mallinfo(gm); +} +#endif /* NO_MALLINFO */ + +#if !NO_MALLOC_STATS +void dlmalloc_stats() { + internal_malloc_stats(gm); +} +#endif /* NO_MALLOC_STATS */ + +int dlmallopt(int param_number, int value) { + return change_mparam(param_number, value); +} + +size_t dlmalloc_usable_size(void* mem) { + if (mem != 0) { + mchunkptr p = mem2chunk(mem); + if (is_inuse(p)) + return chunksize(p) - overhead_for(p); + } + return 0; +} + +#endif /* !ONLY_MSPACES */ + +/* ----------------------------- user mspaces ---------------------------- */ + +#if MSPACES + +static mstate init_user_mstate(char* tbase, size_t tsize) { + size_t msize = pad_request(sizeof(struct malloc_state)); + mchunkptr mn; + mchunkptr msp = align_as_chunk(tbase); + mstate m = (mstate)(chunk2mem(msp)); + memset(m, 0, msize); + (void)INITIAL_LOCK(&m->mutex); + msp->head = (msize|INUSE_BITS); + m->seg.base = m->least_addr = tbase; + m->seg.size = m->footprint = m->max_footprint = tsize; + m->magic = mparams.magic; + m->release_checks = MAX_RELEASE_CHECK_RATE; + m->mflags = mparams.default_mflags; + m->extp = 0; + m->exts = 0; + disable_contiguous(m); + init_bins(m); + mn = next_chunk(mem2chunk(m)); + init_top(m, mn, (size_t)((tbase + tsize) - (char*)mn) - TOP_FOOT_SIZE); + check_top_chunk(m, m->top); + return m; +} + +mspace create_mspace(size_t capacity, int locked) { + mstate m = 0; + size_t msize; + ensure_initialization(); + msize = pad_request(sizeof(struct malloc_state)); + if (capacity < (size_t) -(msize + TOP_FOOT_SIZE + mparams.page_size)) { + size_t rs = ((capacity == 0)? mparams.granularity : + (capacity + TOP_FOOT_SIZE + msize)); + size_t tsize = granularity_align(rs); + char* tbase = (char*)(CALL_MMAP(tsize)); + if (tbase != CMFAIL) { + m = init_user_mstate(tbase, tsize); + m->seg.sflags = USE_MMAP_BIT; + set_lock(m, locked); + } + } + return (mspace)m; +} + +mspace create_mspace_with_base(void* base, size_t capacity, int locked) { + mstate m = 0; + size_t msize; + ensure_initialization(); + msize = pad_request(sizeof(struct malloc_state)); + if (capacity > msize + TOP_FOOT_SIZE && + capacity < (size_t) -(msize + TOP_FOOT_SIZE + mparams.page_size)) { + m = init_user_mstate((char*)base, capacity); + m->seg.sflags = EXTERN_BIT; + set_lock(m, locked); + } + return (mspace)m; +} + +int mspace_track_large_chunks(mspace msp, int enable) { + int ret = 0; + mstate ms = (mstate)msp; + if (!PREACTION(ms)) { + if (!use_mmap(ms)) { + ret = 1; + } + if (!enable) { + enable_mmap(ms); + } else { + disable_mmap(ms); + } + POSTACTION(ms); + } + return ret; +} + +size_t destroy_mspace(mspace msp) { + size_t freed = 0; + mstate ms = (mstate)msp; + if (ok_magic(ms)) { + msegmentptr sp = &ms->seg; + (void)DESTROY_LOCK(&ms->mutex); /* destroy before unmapped */ + while (sp != 0) { + char* base = sp->base; + size_t size = sp->size; + flag_t flag = sp->sflags; + (void)base; /* placate people compiling -Wunused-variable */ + sp = sp->next; + if ((flag & USE_MMAP_BIT) && !(flag & EXTERN_BIT) && + CALL_MUNMAP(base, size) == 0) + freed += size; + } + } + else { + USAGE_ERROR_ACTION(ms,ms); + } + return freed; +} + +/* + mspace versions of routines are near-clones of the global + versions. This is not so nice but better than the alternatives. +*/ + +void* mspace_malloc(mspace msp, size_t bytes) { + mstate ms = (mstate)msp; + if (!ok_magic(ms)) { + USAGE_ERROR_ACTION(ms,ms); + return 0; + } + if (!PREACTION(ms)) { + void* mem; + size_t nb; + if (bytes <= MAX_SMALL_REQUEST) { + bindex_t idx; + binmap_t smallbits; + nb = (bytes < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(bytes); + idx = small_index(nb); + smallbits = ms->smallmap >> idx; + + if ((smallbits & 0x3U) != 0) { /* Remainderless fit to a smallbin. */ + mchunkptr b, p; + idx += ~smallbits & 1; /* Uses next bin if idx empty */ + b = smallbin_at(ms, idx); + p = b->fd; + assert(chunksize(p) == small_index2size(idx)); + unlink_first_small_chunk(ms, b, p, idx); + set_inuse_and_pinuse(ms, p, small_index2size(idx)); + mem = chunk2mem(p); + check_malloced_chunk(ms, mem, nb); + goto postaction; + } + + else if (nb > ms->dvsize) { + if (smallbits != 0) { /* Use chunk in next nonempty smallbin */ + mchunkptr b, p, r; + size_t rsize; + bindex_t i; + binmap_t leftbits = (smallbits << idx) & left_bits(idx2bit(idx)); + binmap_t leastbit = least_bit(leftbits); + compute_bit2idx(leastbit, i); + b = smallbin_at(ms, i); + p = b->fd; + assert(chunksize(p) == small_index2size(i)); + unlink_first_small_chunk(ms, b, p, i); + rsize = small_index2size(i) - nb; + /* Fit here cannot be remainderless if 4byte sizes */ + if (SIZE_T_SIZE != 4 && rsize < MIN_CHUNK_SIZE) + set_inuse_and_pinuse(ms, p, small_index2size(i)); + else { + set_size_and_pinuse_of_inuse_chunk(ms, p, nb); + r = chunk_plus_offset(p, nb); + set_size_and_pinuse_of_free_chunk(r, rsize); + replace_dv(ms, r, rsize); + } + mem = chunk2mem(p); + check_malloced_chunk(ms, mem, nb); + goto postaction; + } + + else if (ms->treemap != 0 && (mem = tmalloc_small(ms, nb)) != 0) { + check_malloced_chunk(ms, mem, nb); + goto postaction; + } + } + } + else if (bytes >= MAX_REQUEST) + nb = MAX_SIZE_T; /* Too big to allocate. Force failure (in sys alloc) */ + else { + nb = pad_request(bytes); + if (ms->treemap != 0 && (mem = tmalloc_large(ms, nb)) != 0) { + check_malloced_chunk(ms, mem, nb); + goto postaction; + } + } + + if (nb <= ms->dvsize) { + size_t rsize = ms->dvsize - nb; + mchunkptr p = ms->dv; + if (rsize >= MIN_CHUNK_SIZE) { /* split dv */ + mchunkptr r = ms->dv = chunk_plus_offset(p, nb); + ms->dvsize = rsize; + set_size_and_pinuse_of_free_chunk(r, rsize); + set_size_and_pinuse_of_inuse_chunk(ms, p, nb); + } + else { /* exhaust dv */ + size_t dvs = ms->dvsize; + ms->dvsize = 0; + ms->dv = 0; + set_inuse_and_pinuse(ms, p, dvs); + } + mem = chunk2mem(p); + check_malloced_chunk(ms, mem, nb); + goto postaction; + } + + else if (nb < ms->topsize) { /* Split top */ + size_t rsize = ms->topsize -= nb; + mchunkptr p = ms->top; + mchunkptr r = ms->top = chunk_plus_offset(p, nb); + r->head = rsize | PINUSE_BIT; + set_size_and_pinuse_of_inuse_chunk(ms, p, nb); + mem = chunk2mem(p); + check_top_chunk(ms, ms->top); + check_malloced_chunk(ms, mem, nb); + goto postaction; + } + + mem = sys_alloc(ms, nb); + + postaction: + POSTACTION(ms); + return mem; + } + + return 0; +} + +void mspace_free(mspace msp, void* mem) { + if (mem != 0) { + mchunkptr p = mem2chunk(mem); +#if FOOTERS + mstate fm = get_mstate_for(p); + (void)msp; /* placate people compiling -Wunused */ +#else /* FOOTERS */ + mstate fm = (mstate)msp; +#endif /* FOOTERS */ + if (!ok_magic(fm)) { + USAGE_ERROR_ACTION(fm, p); + return; + } + if (!PREACTION(fm)) { + check_inuse_chunk(fm, p); + if (RTCHECK(ok_address(fm, p) && ok_inuse(p))) { + size_t psize = chunksize(p); + mchunkptr next = chunk_plus_offset(p, psize); + if (!pinuse(p)) { + size_t prevsize = p->prev_foot; + if (is_mmapped(p)) { + psize += prevsize + MMAP_FOOT_PAD; + if (CALL_MUNMAP((char*)p - prevsize, psize) == 0) + fm->footprint -= psize; + goto postaction; + } + else { + mchunkptr prev = chunk_minus_offset(p, prevsize); + psize += prevsize; + p = prev; + if (RTCHECK(ok_address(fm, prev))) { /* consolidate backward */ + if (p != fm->dv) { + unlink_chunk(fm, p, prevsize); + } + else if ((next->head & INUSE_BITS) == INUSE_BITS) { + fm->dvsize = psize; + set_free_with_pinuse(p, psize, next); + goto postaction; + } + } + else + goto erroraction; + } + } + + if (RTCHECK(ok_next(p, next) && ok_pinuse(next))) { + if (!cinuse(next)) { /* consolidate forward */ + if (next == fm->top) { + size_t tsize = fm->topsize += psize; + fm->top = p; + p->head = tsize | PINUSE_BIT; + if (p == fm->dv) { + fm->dv = 0; + fm->dvsize = 0; + } + if (should_trim(fm, tsize)) + sys_trim(fm, 0); + goto postaction; + } + else if (next == fm->dv) { + size_t dsize = fm->dvsize += psize; + fm->dv = p; + set_size_and_pinuse_of_free_chunk(p, dsize); + goto postaction; + } + else { + size_t nsize = chunksize(next); + psize += nsize; + unlink_chunk(fm, next, nsize); + set_size_and_pinuse_of_free_chunk(p, psize); + if (p == fm->dv) { + fm->dvsize = psize; + goto postaction; + } + } + } + else + set_free_with_pinuse(p, psize, next); + + if (is_small(psize)) { + insert_small_chunk(fm, p, psize); + check_free_chunk(fm, p); + } + else { + tchunkptr tp = (tchunkptr)p; + insert_large_chunk(fm, tp, psize); + check_free_chunk(fm, p); + if (--fm->release_checks == 0) + release_unused_segments(fm); + } + goto postaction; + } + } + erroraction: + USAGE_ERROR_ACTION(fm, p); + postaction: + POSTACTION(fm); + } + } +} + +void* mspace_calloc(mspace msp, size_t n_elements, size_t elem_size) { + void* mem; + size_t req = 0; + mstate ms = (mstate)msp; + if (!ok_magic(ms)) { + USAGE_ERROR_ACTION(ms,ms); + return 0; + } + if (n_elements != 0) { + req = n_elements * elem_size; + if (((n_elements | elem_size) & ~(size_t)0xffff) && + (req / n_elements != elem_size)) + req = MAX_SIZE_T; /* force downstream failure on overflow */ + } + mem = internal_malloc(ms, req); + if (mem != 0 && calloc_must_clear(mem2chunk(mem))) + memset(mem, 0, req); + return mem; +} + +void* mspace_realloc(mspace msp, void* oldmem, size_t bytes) { + void* mem = 0; + if (oldmem == 0) { + mem = mspace_malloc(msp, bytes); + } + else if (bytes >= MAX_REQUEST) { + MALLOC_FAILURE_ACTION; + } +#ifdef REALLOC_ZERO_BYTES_FREES + else if (bytes == 0) { + mspace_free(msp, oldmem); + } +#endif /* REALLOC_ZERO_BYTES_FREES */ + else { + size_t nb = request2size(bytes); + mchunkptr oldp = mem2chunk(oldmem); +#if ! FOOTERS + mstate m = (mstate)msp; +#else /* FOOTERS */ + mstate m = get_mstate_for(oldp); + if (!ok_magic(m)) { + USAGE_ERROR_ACTION(m, oldmem); + return 0; + } +#endif /* FOOTERS */ + if (!PREACTION(m)) { + mchunkptr newp = try_realloc_chunk(m, oldp, nb, 1); + POSTACTION(m); + if (newp != 0) { + check_inuse_chunk(m, newp); + mem = chunk2mem(newp); + } + else { + mem = mspace_malloc(m, bytes); + if (mem != 0) { + size_t oc = chunksize(oldp) - overhead_for(oldp); + memcpy(mem, oldmem, (oc < bytes)? oc : bytes); + mspace_free(m, oldmem); + } + } + } + } + return mem; +} + +void* mspace_realloc_in_place(mspace msp, void* oldmem, size_t bytes) { + void* mem = 0; + if (oldmem != 0) { + if (bytes >= MAX_REQUEST) { + MALLOC_FAILURE_ACTION; + } + else { + size_t nb = request2size(bytes); + mchunkptr oldp = mem2chunk(oldmem); +#if ! FOOTERS + mstate m = (mstate)msp; +#else /* FOOTERS */ + mstate m = get_mstate_for(oldp); + (void)msp; /* placate people compiling -Wunused */ + if (!ok_magic(m)) { + USAGE_ERROR_ACTION(m, oldmem); + return 0; + } +#endif /* FOOTERS */ + if (!PREACTION(m)) { + mchunkptr newp = try_realloc_chunk(m, oldp, nb, 0); + POSTACTION(m); + if (newp == oldp) { + check_inuse_chunk(m, newp); + mem = oldmem; + } + } + } + } + return mem; +} + +void* mspace_memalign(mspace msp, size_t alignment, size_t bytes) { + mstate ms = (mstate)msp; + if (!ok_magic(ms)) { + USAGE_ERROR_ACTION(ms,ms); + return 0; + } + if (alignment <= MALLOC_ALIGNMENT) + return mspace_malloc(msp, bytes); + return internal_memalign(ms, alignment, bytes); +} + +void* mspace_aligned_alloc(mspace msp, size_t alignment, size_t bytes) { + if (bytes % alignment) + return NULL; + return mspace_memalign(msp, alignment, bytes); +} + +int mspace_posix_memalign(mspace msp, void **memptr, size_t alignment, size_t bytes) { + if (bytes == 0) { + *memptr = NULL; + return 0; + } + void *res = mspace_memalign(msp, alignment, bytes); + if (res) { + *memptr = res; + return 0; + } + return 1; +} + +void** mspace_independent_calloc(mspace msp, size_t n_elements, + size_t elem_size, void* chunks[]) { + size_t sz = elem_size; /* serves as 1-element array */ + mstate ms = (mstate)msp; + if (!ok_magic(ms)) { + USAGE_ERROR_ACTION(ms,ms); + return 0; + } + return ialloc(ms, n_elements, &sz, 3, chunks); +} + +void** mspace_independent_comalloc(mspace msp, size_t n_elements, + size_t sizes[], void* chunks[]) { + mstate ms = (mstate)msp; + if (!ok_magic(ms)) { + USAGE_ERROR_ACTION(ms,ms); + return 0; + } + return ialloc(ms, n_elements, sizes, 0, chunks); +} + +size_t mspace_bulk_free(mspace msp, void* array[], size_t nelem) { + return internal_bulk_free((mstate)msp, array, nelem); +} + +#if MALLOC_INSPECT_ALL +void mspace_inspect_all(mspace msp, + void(*handler)(void *start, + void *end, + size_t used_bytes, + void* callback_arg), + void* arg) { + mstate ms = (mstate)msp; + if (ok_magic(ms)) { + if (!PREACTION(ms)) { + internal_inspect_all(ms, handler, arg); + POSTACTION(ms); + } + } + else { + USAGE_ERROR_ACTION(ms,ms); + } +} +#endif /* MALLOC_INSPECT_ALL */ + +int mspace_trim(mspace msp, size_t pad) { + int result = 0; + mstate ms = (mstate)msp; + if (ok_magic(ms)) { + if (!PREACTION(ms)) { + result = sys_trim(ms, pad); + POSTACTION(ms); + } + } + else { + USAGE_ERROR_ACTION(ms,ms); + } + return result; +} + +#if !NO_MALLOC_STATS +void mspace_malloc_stats(mspace msp) { + mstate ms = (mstate)msp; + if (ok_magic(ms)) { + internal_malloc_stats(ms); + } + else { + USAGE_ERROR_ACTION(ms,ms); + } +} +#endif /* NO_MALLOC_STATS */ + +void* mspace_least_addr(mspace msp) { + mstate ms = (mstate)msp; + return (void*)ms->least_addr; +} + +size_t mspace_footprint(mspace msp) { + size_t result = 0; + mstate ms = (mstate)msp; + if (ok_magic(ms)) { + result = ms->footprint; + } + else { + USAGE_ERROR_ACTION(ms,ms); + } + return result; +} + +size_t mspace_max_footprint(mspace msp) { + size_t result = 0; + mstate ms = (mstate)msp; + if (ok_magic(ms)) { + result = ms->max_footprint; + } + else { + USAGE_ERROR_ACTION(ms,ms); + } + return result; +} + +size_t mspace_footprint_limit(mspace msp) { + size_t result = 0; + mstate ms = (mstate)msp; + if (ok_magic(ms)) { + size_t maf = ms->footprint_limit; + result = (maf == 0) ? MAX_SIZE_T : maf; + } + else { + USAGE_ERROR_ACTION(ms,ms); + } + return result; +} + +size_t mspace_set_footprint_limit(mspace msp, size_t bytes) { + size_t result = 0; + mstate ms = (mstate)msp; + if (ok_magic(ms)) { + if (bytes == 0) + result = granularity_align(1); /* Use minimal size */ + if (bytes == MAX_SIZE_T) + result = 0; /* disable */ + else + result = granularity_align(bytes); + ms->footprint_limit = result; + } + else { + USAGE_ERROR_ACTION(ms,ms); + } + return result; +} + +#if !NO_MALLINFO +struct mallinfo mspace_mallinfo(mspace msp) { + mstate ms = (mstate)msp; + if (!ok_magic(ms)) { + USAGE_ERROR_ACTION(ms,ms); + } + return internal_mallinfo(ms); +} +#endif /* NO_MALLINFO */ + +size_t mspace_usable_size(const void* mem) { + if (mem != 0) { + mchunkptr p = mem2chunk(mem); + if (is_inuse(p)) + return chunksize(p) - overhead_for(p); + } + return 0; +} + +int mspace_mallopt(int param_number, int value) { + return change_mparam(param_number, value); +} + +#endif /* MSPACES */ + + +/* -------------------- Alternative MORECORE functions ------------------- */ + +/* + Guidelines for creating a custom version of MORECORE: + + * For best performance, MORECORE should allocate in multiples of pagesize. + * MORECORE may allocate more memory than requested. (Or even less, + but this will usually result in a malloc failure.) + * MORECORE must not allocate memory when given argument zero, but + instead return one past the end address of memory from previous + nonzero call. + * For best performance, consecutive calls to MORECORE with positive + arguments should return increasing addresses, indicating that + space has been contiguously extended. + * Even though consecutive calls to MORECORE need not return contiguous + addresses, it must be OK for malloc'ed chunks to span multiple + regions in those cases where they do happen to be contiguous. + * MORECORE need not handle negative arguments -- it may instead + just return MFAIL when given negative arguments. + Negative arguments are always multiples of pagesize. MORECORE + must not misinterpret negative args as large positive unsigned + args. You can suppress all such calls from even occurring by defining + MORECORE_CANNOT_TRIM, + + As an example alternative MORECORE, here is a custom allocator + kindly contributed for pre-OSX macOS. It uses virtually but not + necessarily physically contiguous non-paged memory (locked in, + present and won't get swapped out). You can use it by uncommenting + this section, adding some #includes, and setting up the appropriate + defines above: + + #define MORECORE osMoreCore + + There is also a shutdown routine that should somehow be called for + cleanup upon program exit. + + #define MAX_POOL_ENTRIES 100 + #define MINIMUM_MORECORE_SIZE (64 * 1024U) + static int next_os_pool; + void *our_os_pools[MAX_POOL_ENTRIES]; + + void *osMoreCore(int size) + { + void *ptr = 0; + static void *sbrk_top = 0; + + if (size > 0) + { + if (size < MINIMUM_MORECORE_SIZE) + size = MINIMUM_MORECORE_SIZE; + if (CurrentExecutionLevel() == kTaskLevel) + ptr = PoolAllocateResident(size + RM_PAGE_SIZE, 0); + if (ptr == 0) + { + return (void *) MFAIL; + } + // save ptrs so they can be freed during cleanup + our_os_pools[next_os_pool] = ptr; + next_os_pool++; + ptr = (void *) ((((size_t) ptr) + RM_PAGE_MASK) & ~RM_PAGE_MASK); + sbrk_top = (char *) ptr + size; + return ptr; + } + else if (size < 0) + { + // we don't currently support shrink behavior + return (void *) MFAIL; + } + else + { + return sbrk_top; + } + } + + // cleanup any allocated memory pools + // called as last thing before shutting down driver + + void osCleanupMem(void) + { + void **ptr; + + for (ptr = our_os_pools; ptr < &our_os_pools[MAX_POOL_ENTRIES]; ptr++) + if (*ptr) + { + PoolDeallocate(*ptr); + *ptr = 0; + } + } + +*/ + + +/* ----------------------------------------------------------------------- +History: + v2.8.6 Wed Aug 29 06:57:58 2012 Doug Lea + * fix bad comparison in dlposix_memalign + * don't reuse adjusted asize in sys_alloc + * add LOCK_AT_FORK -- thanks to Kirill Artamonov for the suggestion + * reduce compiler warnings -- thanks to all who reported/suggested these + + v2.8.5 Sun May 22 10:26:02 2011 Doug Lea (dl at gee) + * Always perform unlink checks unless INSECURE + * Add posix_memalign. + * Improve realloc to expand in more cases; expose realloc_in_place. + Thanks to Peter Buhr for the suggestion. + * Add footprint_limit, inspect_all, bulk_free. Thanks + to Barry Hayes and others for the suggestions. + * Internal refactorings to avoid calls while holding locks + * Use non-reentrant locks by default. Thanks to Roland McGrath + for the suggestion. + * Small fixes to mspace_destroy, reset_on_error. + * Various configuration extensions/changes. Thanks + to all who contributed these. + + V2.8.4a Thu Apr 28 14:39:43 2011 (dl at gee.cs.oswego.edu) + * Update Creative Commons URL + + V2.8.4 Wed May 27 09:56:23 2009 Doug Lea (dl at gee) + * Use zeros instead of prev foot for is_mmapped + * Add mspace_track_large_chunks; thanks to Jean Brouwers + * Fix set_inuse in internal_realloc; thanks to Jean Brouwers + * Fix insufficient sys_alloc padding when using 16byte alignment + * Fix bad error check in mspace_footprint + * Adaptations for ptmalloc; thanks to Wolfram Gloger. + * Reentrant spin locks; thanks to Earl Chew and others + * Win32 improvements; thanks to Niall Douglas and Earl Chew + * Add NO_SEGMENT_TRAVERSAL and MAX_RELEASE_CHECK_RATE options + * Extension hook in malloc_state + * Various small adjustments to reduce warnings on some compilers + * Various configuration extensions/changes for more platforms. Thanks + to all who contributed these. + + V2.8.3 Thu Sep 22 11:16:32 2005 Doug Lea (dl at gee) + * Add max_footprint functions + * Ensure all appropriate literals are size_t + * Fix conditional compilation problem for some #define settings + * Avoid concatenating segments with the one provided + in create_mspace_with_base + * Rename some variables to avoid compiler shadowing warnings + * Use explicit lock initialization. + * Better handling of sbrk interference. + * Simplify and fix segment insertion, trimming and mspace_destroy + * Reinstate REALLOC_ZERO_BYTES_FREES option from 2.7.x + * Thanks especially to Dennis Flanagan for help on these. + + V2.8.2 Sun Jun 12 16:01:10 2005 Doug Lea (dl at gee) + * Fix memalign brace error. + + V2.8.1 Wed Jun 8 16:11:46 2005 Doug Lea (dl at gee) + * Fix improper #endif nesting in C++ + * Add explicit casts needed for C++ + + V2.8.0 Mon May 30 14:09:02 2005 Doug Lea (dl at gee) + * Use trees for large bins + * Support mspaces + * Use segments to unify sbrk-based and mmap-based system allocation, + removing need for emulation on most platforms without sbrk. + * Default safety checks + * Optional footer checks. Thanks to William Robertson for the idea. + * Internal code refactoring + * Incorporate suggestions and platform-specific changes. + Thanks to Dennis Flanagan, Colin Plumb, Niall Douglas, + Aaron Bachmann, Emery Berger, and others. + * Speed up non-fastbin processing enough to remove fastbins. + * Remove useless cfree() to avoid conflicts with other apps. + * Remove internal memcpy, memset. Compilers handle builtins better. + * Remove some options that no one ever used and rename others. + + V2.7.2 Sat Aug 17 09:07:30 2002 Doug Lea (dl at gee) + * Fix malloc_state bitmap array misdeclaration + + V2.7.1 Thu Jul 25 10:58:03 2002 Doug Lea (dl at gee) + * Allow tuning of FIRST_SORTED_BIN_SIZE + * Use PTR_UINT as type for all ptr->int casts. Thanks to John Belmonte. + * Better detection and support for non-contiguousness of MORECORE. + Thanks to Andreas Mueller, Conal Walsh, and Wolfram Gloger + * Bypass most of malloc if no frees. Thanks To Emery Berger. + * Fix freeing of old top non-contiguous chunk im sysmalloc. + * Raised default trim and map thresholds to 256K. + * Fix mmap-related #defines. Thanks to Lubos Lunak. + * Fix copy macros; added LACKS_FCNTL_H. Thanks to Neal Walfield. + * Branch-free bin calculation + * Default trim and mmap thresholds now 256K. + + V2.7.0 Sun Mar 11 14:14:06 2001 Doug Lea (dl at gee) + * Introduce independent_comalloc and independent_calloc. + Thanks to Michael Pachos for motivation and help. + * Make optional .h file available + * Allow > 2GB requests on 32bit systems. + * new WIN32 sbrk, mmap, munmap, lock code from <Walter@GeNeSys-e.de>. + Thanks also to Andreas Mueller <a.mueller at paradatec.de>, + and Anonymous. + * Allow override of MALLOC_ALIGNMENT (Thanks to Ruud Waij for + helping test this.) + * memalign: check alignment arg + * realloc: don't try to shift chunks backwards, since this + leads to more fragmentation in some programs and doesn't + seem to help in any others. + * Collect all cases in malloc requiring system memory into sysmalloc + * Use mmap as backup to sbrk + * Place all internal state in malloc_state + * Introduce fastbins (although similar to 2.5.1) + * Many minor tunings and cosmetic improvements + * Introduce USE_PUBLIC_MALLOC_WRAPPERS, USE_MALLOC_LOCK + * Introduce MALLOC_FAILURE_ACTION, MORECORE_CONTIGUOUS + Thanks to Tony E. Bennett <tbennett@nvidia.com> and others. + * Include errno.h to support default failure action. + + V2.6.6 Sun Dec 5 07:42:19 1999 Doug Lea (dl at gee) + * return null for negative arguments + * Added Several WIN32 cleanups from Martin C. Fong <mcfong at yahoo.com> + * Add 'LACKS_SYS_PARAM_H' for those systems without 'sys/param.h' + (e.g. WIN32 platforms) + * Cleanup header file inclusion for WIN32 platforms + * Cleanup code to avoid Microsoft Visual C++ compiler complaints + * Add 'USE_DL_PREFIX' to quickly allow co-existence with existing + memory allocation routines + * Set 'malloc_getpagesize' for WIN32 platforms (needs more work) + * Use 'assert' rather than 'ASSERT' in WIN32 code to conform to + usage of 'assert' in non-WIN32 code + * Improve WIN32 'sbrk()' emulation's 'findRegion()' routine to + avoid infinite loop + * Always call 'fREe()' rather than 'free()' + + V2.6.5 Wed Jun 17 15:57:31 1998 Doug Lea (dl at gee) + * Fixed ordering problem with boundary-stamping + + V2.6.3 Sun May 19 08:17:58 1996 Doug Lea (dl at gee) + * Added pvalloc, as recommended by H.J. Liu + * Added 64bit pointer support mainly from Wolfram Gloger + * Added anonymously donated WIN32 sbrk emulation + * Malloc, calloc, getpagesize: add optimizations from Raymond Nijssen + * malloc_extend_top: fix mask error that caused wastage after + foreign sbrks + * Add linux mremap support code from HJ Liu + + V2.6.2 Tue Dec 5 06:52:55 1995 Doug Lea (dl at gee) + * Integrated most documentation with the code. + * Add support for mmap, with help from + Wolfram Gloger (Gloger@lrz.uni-muenchen.de). + * Use last_remainder in more cases. + * Pack bins using idea from colin@nyx10.cs.du.edu + * Use ordered bins instead of best-fit threshhold + * Eliminate block-local decls to simplify tracing and debugging. + * Support another case of realloc via move into top + * Fix error occuring when initial sbrk_base not word-aligned. + * Rely on page size for units instead of SBRK_UNIT to + avoid surprises about sbrk alignment conventions. + * Add mallinfo, mallopt. Thanks to Raymond Nijssen + (raymond@es.ele.tue.nl) for the suggestion. + * Add `pad' argument to malloc_trim and top_pad mallopt parameter. + * More precautions for cases where other routines call sbrk, + courtesy of Wolfram Gloger (Gloger@lrz.uni-muenchen.de). + * Added macros etc., allowing use in linux libc from + H.J. Lu (hjl@gnu.ai.mit.edu) + * Inverted this history list + + V2.6.1 Sat Dec 2 14:10:57 1995 Doug Lea (dl at gee) + * Re-tuned and fixed to behave more nicely with V2.6.0 changes. + * Removed all preallocation code since under current scheme + the work required to undo bad preallocations exceeds + the work saved in good cases for most test programs. + * No longer use return list or unconsolidated bins since + no scheme using them consistently outperforms those that don't + given above changes. + * Use best fit for very large chunks to prevent some worst-cases. + * Added some support for debugging + + V2.6.0 Sat Nov 4 07:05:23 1995 Doug Lea (dl at gee) + * Removed footers when chunks are in use. Thanks to + Paul Wilson (wilson@cs.texas.edu) for the suggestion. + + V2.5.4 Wed Nov 1 07:54:51 1995 Doug Lea (dl at gee) + * Added malloc_trim, with help from Wolfram Gloger + (wmglo@Dent.MED.Uni-Muenchen.DE). + + V2.5.3 Tue Apr 26 10:16:01 1994 Doug Lea (dl at g) + + V2.5.2 Tue Apr 5 16:20:40 1994 Doug Lea (dl at g) + * realloc: try to expand in both directions + * malloc: swap order of clean-bin strategy; + * realloc: only conditionally expand backwards + * Try not to scavenge used bins + * Use bin counts as a guide to preallocation + * Occasionally bin return list chunks in first scan + * Add a few optimizations from colin@nyx10.cs.du.edu + + V2.5.1 Sat Aug 14 15:40:43 1993 Doug Lea (dl at g) + * faster bin computation & slightly different binning + * merged all consolidations to one part of malloc proper + (eliminating old malloc_find_space & malloc_clean_bin) + * Scan 2 returns chunks (not just 1) + * Propagate failure in realloc if malloc returns 0 + * Add stuff to allow compilation on non-ANSI compilers + from kpv@research.att.com + + V2.5 Sat Aug 7 07:41:59 1993 Doug Lea (dl at g.oswego.edu) + * removed potential for odd address access in prev_chunk + * removed dependency on getpagesize.h + * misc cosmetics and a bit more internal documentation + * anticosmetics: mangled names in macros to evade debugger strangeness + * tested on sparc, hp-700, dec-mips, rs6000 + with gcc & native cc (hp, dec only) allowing + Detlefs & Zorn comparison study (in SIGPLAN Notices.) + + Trial version Fri Aug 28 13:14:29 1992 Doug Lea (dl at g.oswego.edu) + * Based loosely on libg++-1.2X malloc. (It retains some of the overall + structure of old version, but most details differ.) + +*/ diff --git a/src/plugins/e-acsl/demo/.gitignore b/src/plugins/e-acsl/demo/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..50f382630b547e8da2b9b64430453d553364d80a --- /dev/null +++ b/src/plugins/e-acsl/demo/.gitignore @@ -0,0 +1,4 @@ +demo +demo.sav +script +res_demo.c diff --git a/src/plugins/e-acsl/demo/TODO b/src/plugins/e-acsl/demo/TODO new file mode 100644 index 0000000000000000000000000000000000000000..eb262653db9102d2b4581636481d135daebe0783 --- /dev/null +++ b/src/plugins/e-acsl/demo/TODO @@ -0,0 +1 @@ +les TODO et assert false dans script.ml diff --git a/src/plugins/e-acsl/demo/alone.sh b/src/plugins/e-acsl/demo/alone.sh new file mode 100755 index 0000000000000000000000000000000000000000..bbe34a54cc25f8453c0a90a91570eddde3a061f3 --- /dev/null +++ b/src/plugins/e-acsl/demo/alone.sh @@ -0,0 +1,2 @@ +#! /bin/sh +frama-c demo.c -e-acsl -then-on e-acsl -print -ocode res_demo.c diff --git a/src/plugins/e-acsl/demo/clean.sh b/src/plugins/e-acsl/demo/clean.sh new file mode 100755 index 0000000000000000000000000000000000000000..857fa369f070a7b362e317751249bba64adf67a8 --- /dev/null +++ b/src/plugins/e-acsl/demo/clean.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +clean +rm -f demo.sav demo script frama_c_journal.ml res_demo.c +./compile.sh diff --git a/src/plugins/e-acsl/demo/compile.sh b/src/plugins/e-acsl/demo/compile.sh new file mode 100755 index 0000000000000000000000000000000000000000..8f56bda68fe3a3c7ebd66a83a06c833d632a6051 --- /dev/null +++ b/src/plugins/e-acsl/demo/compile.sh @@ -0,0 +1,2 @@ +#!/bin/sh +ocamlopt.opt -shared -o ./Script.cmxs -w Ly -warn-error A -I /usr/local/lib/frama-c -I . script.ml diff --git a/src/plugins/e-acsl/demo/custom_assert.c b/src/plugins/e-acsl/demo/custom_assert.c new file mode 100644 index 0000000000000000000000000000000000000000..878295dd2331298d3e1b3b3ba628e219a10f5fbc --- /dev/null +++ b/src/plugins/e-acsl/demo/custom_assert.c @@ -0,0 +1,17 @@ +#include <stdio.h> + +void e_acsl_assert(int predicate, + char *kind, + char *fct, + char *pred_txt, + int line) +{ + if (! predicate) { + FILE *f = fopen("log_file.log", "a"); + fprintf(f, + "%s failed at line %d in function %s.\n\ +The failing predicate is:\n%s.\n", + kind, line, fct, pred_txt); + fclose(f); + } +} diff --git a/src/plugins/e-acsl/demo/demo.c b/src/plugins/e-acsl/demo/demo.c new file mode 100644 index 0000000000000000000000000000000000000000..2b5cc8f7e2556ade26706573cf268cad6f2c1da8 --- /dev/null +++ b/src/plugins/e-acsl/demo/demo.c @@ -0,0 +1,29 @@ +/*@ assigns \nothing; + @ behavior even: + @ assumes m % 2 == 0; + @ ensures \result >= 1; + @ behavior odd: + @ assumes m % 2 != 0; + @ ensures n >= 0 ==> \result >= 1; + @ ensures n < 0 ==> \result <= -1; */ +int pow(int n, unsigned int m); + +int sum(int x) { + int n = 0, i; + for(i = 1; i <= x; i++) n += i; + return n; +} + +int main(void) { + int i, n = 0; + unsigned int a[100]; + n = sum(10); + /*@ loop invariant 0 <= i <= n ; + @ loop invariant \forall integer k; 0 <= k < i ==> a[k] >= 1; + @ loop assigns i,a[0..n-1]; */ + for(i = 0; i < n; i++) { + int tmp = pow(i, i); + a[i] = tmp; + } + /*@ assert \forall integer k; 0 <= k < n ==> a[k] >= 1; */ +} diff --git a/src/plugins/e-acsl/demo/demo.sh b/src/plugins/e-acsl/demo/demo.sh new file mode 100755 index 0000000000000000000000000000000000000000..a8529b2966a4d8b9378652524ee229f014612467 --- /dev/null +++ b/src/plugins/e-acsl/demo/demo.sh @@ -0,0 +1,2 @@ +#! /bin/sh +frama-c -e-acsl-prepare -save demo.sav demo.c -wp -then -val -slevel 11 -then -e-acsl -then-on e-acsl -print -ocode res_demo.c diff --git a/src/plugins/e-acsl/demo/load.sh b/src/plugins/e-acsl/demo/load.sh new file mode 100755 index 0000000000000000000000000000000000000000..ba15ee821379463e93a2359dfacc755e34fb2bc0 --- /dev/null +++ b/src/plugins/e-acsl/demo/load.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +frama-c-gui -load demo.sav diff --git a/src/plugins/e-acsl/demo/my_e_acsl.c b/src/plugins/e-acsl/demo/my_e_acsl.c new file mode 100644 index 0000000000000000000000000000000000000000..c3175d2b822bbd405b0f430f9a0237c864603bf2 --- /dev/null +++ b/src/plugins/e-acsl/demo/my_e_acsl.c @@ -0,0 +1,50 @@ +#include <stdio.h> +#include <stdlib.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <unistd.h> + +#define LEN 10 +int LAST[LEN] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }; +int IDX = 0; + +int mem(int x) { + for(int i = 0; i < LEN; i++) + if (LAST[i] == x) return x; + return -1; +} + +void e_acsl_assert(int predicate, + char *kind, + char *fct, + char *pred_txt, + int line) +{ + if (! predicate) { + if (mem(line) == -1) { + LAST[IDX] = line; + IDX++; + int cpid = fork (); + if (cpid < 0) { + printf("%s failed at line %d of function %s.\n \ +The failing predicate is:\n%s.\n", + kind, line, fct, pred_txt); + } else { + int status; + if (cpid == 0) { + char *line_string = (char*) malloc(sizeof(char)*3); + sprintf(line_string,"%d",line); + char *args[17] = { "frama-c", "-quiet", + "-load", "demo.sav", "-save", "demo.sav", + "-load-module", "./Script", "-t2p-verbose", "1", + "-ppt-fct", fct, + "-ppt-name", kind, + "-ppt-line", line_string }; + status = execvp("frama-c", args); + exit(status); + } else + wait(&status); + } + } + } +} diff --git a/src/plugins/e-acsl/demo/pow.c b/src/plugins/e-acsl/demo/pow.c new file mode 100644 index 0000000000000000000000000000000000000000..a7715ec30ec758634c4264dadcd2b9c51f96f6bb --- /dev/null +++ b/src/plugins/e-acsl/demo/pow.c @@ -0,0 +1,11 @@ +#include "stdio.h" + +int pow(int x, unsigned int n) { + unsigned int res = 1; + while (n) { + if (n & 1) res *= x; + n >>= 1; + x *= x; + } + return res; +} diff --git a/src/plugins/e-acsl/demo/run_demo.sh b/src/plugins/e-acsl/demo/run_demo.sh new file mode 100755 index 0000000000000000000000000000000000000000..38692596d290357760154ee75d30670c39f124e6 --- /dev/null +++ b/src/plugins/e-acsl/demo/run_demo.sh @@ -0,0 +1,9 @@ +#! /bin/sh + +E_ACSL_LIB=`frama-c -print-share-path`/e-acsl + +gcc -c pow.c + +gcc -std=c99 -pedantic -Wall -Wno-long-long -Wno-attributes -Wno-unused-but-set-variable -fno-builtin -o ./demo pow.o $E_ACSL_LIB/e_acsl.c $E_ACSL_LIB/memory_model/e_acsl_bittree.c $E_ACSL_LIB/memory_model/e_acsl_mmodel.c res_demo.c + +./demo diff --git a/src/plugins/e-acsl/demo/run_script.sh b/src/plugins/e-acsl/demo/run_script.sh new file mode 100755 index 0000000000000000000000000000000000000000..e5d1fd942481bfa0d9b13cfd075db80c03675092 --- /dev/null +++ b/src/plugins/e-acsl/demo/run_script.sh @@ -0,0 +1,7 @@ +#! /bin/sh + +E_ACSL_LIB=`frama-c -print-share-path`/e-acsl + +gcc -std=c99 -pedantic -Wall -Wno-long-long -Wno-attributes -Wno-unused-but-set-variable -fno-builtin -o ./script pow.c my_e_acsl.c $E_ACSL_LIB/memory_model/e_acsl_bittree.c $E_ACSL_LIB/memory_model/e_acsl_mmodel.c res_demo.c + +./script diff --git a/src/plugins/e-acsl/demo/script.ml b/src/plugins/e-acsl/demo/script.ml new file mode 100644 index 0000000000000000000000000000000000000000..03036b425d0497ce4ade6558cb4c74aa9b0f2ba7 --- /dev/null +++ b/src/plugins/e-acsl/demo/script.ml @@ -0,0 +1,116 @@ +open Cil_types + +(* ************************************************************************** *) +(* Registering the plug-in *) +(* ************************************************************************** *) + +include Plugin.Register(struct + let name = "txt2ppt" + let shortname = "t2p" + let help = "Convert E-ACSL textual properties to Frama-C properties" +end) + +(* ************************************************************************** *) +(* Defining plug-in's options *) +(* ************************************************************************** *) + +module Fct_name = + Empty_string + (struct + let option_name = "-ppt-fct" + let help = "Name of the function in which the property is defined" + let arg_name = "" + end) + +module Ppt_name = + Empty_string + (struct + let option_name = "-ppt-name" + let help = "Name of the property (assertion, ...)" + let arg_name = "" + end) + +module Ppt_line = + Zero + (struct + let option_name = "-ppt-line" + let help = "Line at which the property is defined" + let arg_name = "" + end) + +(* ************************************************************************** *) +(* Searching the property according to plug-in's options *) +(* ************************************************************************** *) + +exception Found of Property.t * int + +let search_assert_or_invariant kf = + try + Annotations.iter_all_code_annot + (fun stmt _ a -> + match a.annot_content with + | AAssert(_, _, p) | AInvariant(_, _, p) -> + let line = Ppt_line.get () in + if (fst (p.loc)).Lexing.pos_lnum = line then + raise (Found(Property.ip_of_code_annot_single kf stmt a, line)) + | _ -> ()); + assert false + with Found(ppt, line) -> + ppt, line + +let is_predicate p line = (fst (p.ip_loc)).Lexing.pos_lnum = line + +let search_funspec_part iter convert kf = + try + Annotations.iter_behaviors + (fun _ bhv -> iter (fun _ a -> convert bhv a) kf bhv.b_name) + kf; + assert false + with Found(ppt, line) -> + ppt, line + +let search_ensures kf = + search_funspec_part + Annotations.iter_ensures + (fun bhv (_, p as a) -> + let line = Ppt_line.get () in + if is_predicate p line then + raise (Found (Property.ip_of_ensures kf Kglobal bhv a, line)) ) + kf + +let search_requires kf = + search_funspec_part + Annotations.iter_requires + (fun bhv a -> + let line = Ppt_line.get () in + if is_predicate a line then + raise (Found (Property.ip_of_requires kf Kglobal bhv a, line)) ) + kf + +let search kf = match Ppt_name.get () with + | "" | "Assertion" | "Invariant" -> search_assert_or_invariant kf + | "Precondition" -> search_requires kf + | "Postcondition" -> search_ensures kf + | s -> abort "unknown property %s" s + +(* ************************************************************************** *) +(* Emitting status "invalid" for the property *) +(* ************************************************************************** *) + +let emitter = + Emitter.create "E-ACSL" [ Emitter.Property_status ] ~correctness:[] ~tuning:[] + +let emit ppt line = + feedback "@[line %d:@ %a@ is@ invalid.@]" line Property.pretty ppt; + Property_status.emit emitter ~hyps:[] ppt Property_status.False_and_reachable + +(* ************************************************************************** *) +(* Plug-in's main *) +(* ************************************************************************** *) + +let main () = + let kf = Globals.Functions.find_by_name (Fct_name.get ()) in + let ppt, line = search kf in + emit ppt line + +let () = Db.Main.extend main diff --git a/src/plugins/e-acsl/doc/Changelog b/src/plugins/e-acsl/doc/Changelog new file mode 100644 index 0000000000000000000000000000000000000000..22c406fd10dd615834f4b4543b635b4566f16613 --- /dev/null +++ b/src/plugins/e-acsl/doc/Changelog @@ -0,0 +1,319 @@ +############################################################################### +# Preliminary notes: # +# ------------------ # +# Mark "-": change with an impact for users (and possibly developers). # +# Mark "o": change with an impact for developers only. # +# Mark "+": change for Frama-C-commits audience (not in html version) # +# Mark "*": bug fixed. # +# Mark "!": change that can break compatibility with existing development. # +# '#nnn' : BTS entry #nnn # +# '#!nnn' : BTS private entry #nnn # +# For compatibility with old change log formats: # +# '#?nnn' : OLD-BTS entry #nnn # +############################################################################### +# Categories: +# E-ACSL monitor generation +# runtime C runtime library (and memory model) +# e-acsl-gcc launcher e-acsl-gcc.sh +# Makefile Makefile +# configure configure +############################################################################### + +- E-ACSL [2019/08/28] Support of rational numbers and operations. +-! E-ACSL [2019/08/28] Deactivate the unsound support of real + numbers (that are not rationals). They were previously + unsoundly converted to floating point numbers. + +############################## +Plugin E-ACSL 19.0 (Potassium) +############################## + +- E-ACSL [2019/04/29] Support for logic functions and predicates + without labels. +- runtime [2019/02/26] The behavior of __e_acsl_assert now depends on the + runtime value of the global variable __e_acsl_sound_verdict: + if 0, it means that its verdict is possibly incorrect. +- E-ACSL [2019/02/26] New option -e-acsl-instrument to instrument + only a specified set of functions. It may lead to incorrect + verdicts. +- E-ACSL [2019/02/19] New option -e-acsl-functions to monitor only + annotations in a white list of functions. +-* runtime [2019/02/04] Fix initialization of the E-ACSL runtime in + presence of multiple calls to its initializer (for + instance, if the main is a recursive function). +-* runtime [2019/01/02] Fix overlap of TLS with other memory + segments for large memory spaces. +- E-ACSL [2018/11/15] Predicates with empty quantifications + directly generate \true or \false instead of nested loops. + +########################## +Plugin E-ACSL 18.0 (Argon) +########################## + +-* E-ACSL [2018/11/13] Fix typing bug in quantifications when the + guards of the quantifier variable cannot be represented into + its type. +-* runtime [2018/11/13] Fix bug #!2405 about memory initialization + in presence of GCC constructors. +-* 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 + performing pointer subtraction. +-* E-ACSL [2018/10/04] Support for \at on purely logic variables. + Fix bug #1762 about out-of-scope variables when using \old. +-* E-ACSL [2018/10/02] Fix bug #2305 about taking the address of a + bitfield. +- E-ACSL [2018/09/18] Support for ranges in memory builtins + (\valid, \initialized, etc). + +############################### +Plugin E-ACSL Chlorine-20180501 +############################### + +- E-ACSL [2018/03/30] Support for let binding. +- E-ACSL [2018/02/21] New option -e-acsl-replace-libc-functions to + replace a few libc functions by built-ins that efficiently + detects when they are incorrectly called. +- E-ACSL [2018/02/21] New option -e-acsl-validate-format-strings to + detect format string errors in printf-like functions. +-* E-ACSL [2018/02/21] Correct support of variable-length array + (fix bug #1834). +-* runtime [2018/02/16] Function __e_acsl_offset now returns size_t. +-* E-ACSL [2018/02/07] Fix incorrect typing in presence of + comparison operators (may only be visible when directly + analyzing the E-ACSL's generated code with Frama-C without + pretty-printing it). +-* runtime [2018/01/30] E-ACSL aborted when run on a machine with a + low hard limit on the stack size. +-* E-ACSL [2018/01/08] Fix a crash when translating a postcondition + that should generate a local variable (bts #2339). +-* e-acsl-gcc [2017/11/28] Several files may be given to e-acsl-gcc.sh + (as specified). +-* E-ACSL [2017/11/27] Fix 'segmentation fault' of the generated monitor + whenever the main has a precondition depending on the memory + model. +-* E-ACSL [2017/11/27] Restore behavior of option -e-acsl-valid broken + since Phosphorus (included). + +############################# +Plugin E-ACSL Sulfur-20171101 +############################# + +-* E-ACSL [2017/10/25] Fix bug #2303 about unnamed formals in + annotated functions. +- e-acsl-gcc [2017/06/10] Add --free-valid-address option to e-acsl.gcc.sh. +- e-acsl-gcc [2017/05/29] Add --fail-with-code option to e-acsl.gcc.sh. +- e-acsl-gcc [2017/05/19] Add --temporal option to e-acsl.gcc.sh. +- E-ACSL [2017/05/19] New detection of temporal errors in E-ACSL + through -e-acsl-temporal-validity (disabled by default). +- e-acsl-gcc [2017/03/26] Add --weak-validity option to e-acsl.gcc.sh. +- e-acsl-gcc [2017/03/26] Add --rt-verbose option to e-acsl.gcc.sh. +- e-acsl-gcc [2017/03/26] Add --keep-going option to e-acsl.gcc.sh allowing + a program to continue execution after an assertion failure. +- e-acsl-gcc [2017/03/26] Add --stack-size and --heap-size options to + e-acsl-gcc.sh allowing to change the default sizes of the + respective shadow spaces. + +################################# +Plugin E-ACSL Phosphorus-20170515 +################################# + +- runtime [2017/03/29] The (much more efficient) shadow memory model is + now used by default. +-* runtime [2017/03/28] Fix backtrace when the failed instrumented programs + do not require memory model. +-! e-acsl-gcc [2017/03/19] Remove --print|-p option from e-acsl-gcc.sh +- e-acsl-gcc [2017/03/16] Add --check option to e-acsl-gcc.sh which allows + to check the integrity of the generated AST before + instrumentation. +-! e-acsl-gcc [2017/03/03] Remove precond rte option from e-acsl-gss.sh. +-* E-ACSL [2017/03/02] Fix bts #1740 about incorrect monitoring of + memory properties when early exiting a block through + goto, break or continue. +-* E-ACSL [2017/03/01] Correct support of stdin, stdout and stderr + in annotations. +-* E-ACSL [2017/02/24] Fix crash with casts from non-integral terms to + integral types (bts #2284). +-* E-ACSL [2017/02/17] Fix bug with goto which points to a labeled + statement which must be instrumented. +-* E-ACSL [2017/01/23] Fix bug #2252 about pointer arithmetic with + negative offsets. +-* E-ACSL [2017/01/23] Fix bug with typing of unary and binary + operations in a few cases: the generated code might have + overflowed. + +######################### +Plugin E-ACSL 0.8 Silicon +######################### + +-* e-acsl-gcc [2016/11/07] Added --rte-select feature to e-acsl-gcc.sh. +-* e-acsl-gcc [2016/08/02] Added --rt-debug feature to e-acsl-gcc.sh. + --enable-optimized-rtl configure option removed +-* configure [2016/08/02] Added --enable-optimized-rtl option to configure +-* e-acsl-gcc [2016/08/02] Removed --production|-P, --no-stdlib|-N and + --debug-log|-D options of e-acsl-gcc.sh. +-* E-ACSL [2016/07/21] Enable reporting of stack traces during assertion + failures in instrumented programs. +-* e-acsl-gcc [2016/07/13] Add an e-acsl-gcc.sh option (--print--models) + allowing to print the names of the supported memory models. +-* E-ACSL [2016/07/01] Add monitoring support for aligned memory + allocation via posix_memalign and aligned alloc functions. +-* runtime [2016/07/01] Add local version of GMP library customized for use + with E-ACSL runtime library. +-* runtime [2016/07/01] Add custom implementation of malloc for use with + E-ACSL runtime library (via jemalloc library). +- E-ACSL [2016/05/31] New option -e-acsl-builtins which allows to + declare pure C functions which can be used in logic + function application. +- E-ACSL [2016/05/23] Re-implementation of the type system which + improves the efficiency of the generated code over integers. +-* E-ACSL [2016/05/23] Fix bug #2191 about complicate structs and + literate string. +-* e-acsl-gcc [2016/05/22] Add an e-acsl-gcc.sh option (--rte|-a) allowing to + annotate the source program with memory-safety assertions prior + to instrumentation. +-* E-ACSL [2016/05/23] Fix bug #1395 about recursive functions. +-* Makefile [2016/04/07] Fix 'make install' when executed within Frama-C. +-* runtime [2016/03/31] Improve performance of Patricia Trie memory model. +-* Makefile [2016/02/25] Fix 'make clean' in tests. +-* runtime [2016/01/15] Fix several bugs related to incorrect partial + initialization of tracked memory blocks in the E-ACSL + memory model library. + +########################### +Plugin E-ACSL 0.6 Magnesium +########################### + +-* e-acsl-gcc [2016/01/22] Add an e-acsl-gcc.sh option allowing to skip + compilation of original sources. +-* Makefile [2016/01/15] Fix installation with custom --prefix. +-* runtime [2016/01/05] Fix bug in the memory model that caused the + tracked size of heap memory be computed incorrectly. +- e-acsl-gcc [2015/12/15] Add a convenience script e-acsl-gcc.sh for + small runs of the E-ACSL plugin. +-* E-ACSL [2015/12/08] Fix bug #1817 about incorrect initialization of + literal strings in global arrays with compound initializers. +-* runtime [2015/11/06] Fix a crash occuring when using a recent libc + while GMP headers provided by E-ACSL are used. + +######################## +Plugin E-ACSL 0.5 Sodium +######################## + +- E-ACSL [2015/06/01] Support of \freeable. Thus illegal calls to + free (e.g. double free) are detected. +-* E-ACSL [2015/05/28] Fix types of \block_length and \offset. +- E-ACSL [2015/05/27] Search .h in the E-ACSL memory model by + default (easier to use declarations like __memory_size). +- E-ACSL [2015/05/27] Compatibility with new Frama-C Sodium option + -frama-c-stdlib. +-* E-ACSL [2015/04/28] Fix bug when using fopen. +-* E-ACSL [2015/03/06] Fix bugs #1636 and #1837 about scoping of literal + strings. +o E-ACSL [2014/12/17] Export a minimal API for other plug-ins. +-* E-ACSL [2014/10/27] Add a missing cast when translating an integral + type used in a floating point/real context in an annotation. + +######################## +Plugin E-ACSL 0.4.1 Neon +######################## + +-* E-ACSL [2014/08/05] Fix bug #1838 about memset. +-* E-ACSL [2014/08/05] Fix bug #1818 about initialization of globals. +-* E-ACSL [2014/08/04] Fix bug #1696 by clarifying the manual. +-* E-ACSL [2014/08/04] Fix bug #1831 about argc and argv. +-* E-ACSL [2014/07/19] Fix bug #1836 about one-off error when + computing the block which a pointer points to. +-* E-ACSL [2014/07/08] Fix bug #1695 about using some part of the + (Frama-C) libc which prevents linking of the generated C code. +-* E-ACSL [2014/05/21] Fix bug #1782 about incorrect URL in the + documentation. +- E-ACSL [2014/03/27] Remove spurious warnings when using type real + numbers. +-* E-ACSL [2014/03/26] Fix bug #1692 about wrong localisation of + some messages. +- E-ACSL [2014/03/26] Remove a spurious warning when an annotated + function is first declared, then defined. +-* E-ACSL [2014/03/26] Fix bug #1717 about instrumentation of + labeled statements. +-* E-ACSL [2014/03/25] Fix bug #1716 with annotations in while(1). +-* E-ACSL [2014/03/25] Fix bug #1715 about -e-acsl-full-mmodel which + generates incorrect code. +-* E-ACSL [2014/03/17] Fix bug #1700 about non-ISO empty struct. + +############################### +Plugin E-ACSL 0.4 Neon_20140301 +############################### + +-* E-ACSL [2014/01/28] Fix bug #1634 occuring in presence of static + addresses. +-* E-ACSL [2013/09/26] Fix incorrectness which may occur in presence + of aliasing. +-* E-ACSL [2013/09/25] Some loop invariants were tagged as "assertions". + +################################### +Plugin E-ACSL 0.3 Fluorine_20130601 +################################### + +- E-ACSL [2013/09/18] More precise message for unsupported contract + clauses. +- E-ACSL [2013/09/18] Use GMP still less often. +-* E-ACSL [2013/09/18] Fix bug which may occur with divisions and modulos. +- runtime [2013/09/10] Improve ACSL contracts of the E-ACSL C library. +- E-ACSL [2013/09/06] Support of loop invariants. +-* E-ACSL [2013/09/04] Fix bug when monitored global variables have + initializers (bts #1478). +-* E-ACSL [2013/09/04] Fix bug when mixing -e-acsl-prepare and + running E-ACSL in another project (bts #!1473). +-* E-ACSL [2013/06/26] Fix crash with typedef on pointer types. +- E-ACSL [2013/06/21] Fewer unknown locations. +-* E-ACSL [2013/06/18] Fix bug when generating RTEs on the E-ACSL + generated project. +-* E-ACSL [2013/05/30] Fix -e-acsl-debug n, with n >= 2. + +################################### +Plugin E-ACSL 0.2 Fluorine_20130401 +################################### + +- E-ACSL [2013/01/09] New option -e-acsl-valid. By default, valid + annotation are not translated anymore. +-* E-ACSL [2013/01/09] Fix bug when translating a postcondition of a + function where the init state is the same than the final + state (bts #!1300). +- E-ACSL [2013/01/09] Support of undefined function with a contract. +- E-ACSL [2012/12/20] Support of ghost variables and statements. +-* E-ACSL [2012/12/13] Fix bug with complex term left-values. +- E-ACSL [2012/11/27] Support of \valid_read. +- E-ACSL [2012/11/27] Prevent runtime errors in annotations, except + uninitialized variables. +- E-ACSL [2012/11/19] Support of floats in annotations. Approximate + reals by floats. +- E-ACSL [2012/10/25] Support of \valid. +- E-ACSL [2012/10/25] Support of \initialized. +- E-ACSL [2012/10/25] Support of \block_length. +- E-ACSL [2012/10/25] Support of \offset. +- E-ACSL [2012/10/25] Support of \base_addr. +-* E-ACSL [2012/09/13] Fix bug with very long ACSL integer constants. +- E-ACSL [2012/06/27] Continue to convert the other pre/post-conditions + even if one fails. +- runtime [2012/04/27] Improve ACSL spec of E-ACSL' C library. +-* Makefile [2012/01/27] Fix compilation bug when configuring with + --enable-external. +- E-ACSL [2012/01/25] Nicer generated variable names. +-* E-ACSL [2012/01/24] Fix bug with lazy operators in term position. +-* E-ACSL [2012/01/24] Fix bug with boolean. +-* E-ACSL [2012/01/24] Fix bug with negation and GMP integers. +-* E-ACSL [2012/01/24] Fix bug with conditional and GMP integers. +- runtime [2012/01/24] Function e_acsl_assert now consistent with + standard assert. +- E-ACSL [2012/01/23] Support of bitwise complementation. +- E-ACSL [2012/01/20] Use GMP arithmetics only when required + (i.e. mostly never in practice). + +################################### +Plugin E-ACSL 0.1 Nitrogen_20111001 +################################### + +- E-ACSL [2012/01/06] First public release. + +################################### diff --git a/src/plugins/e-acsl/doc/doxygen/doxygen.cfg.in b/src/plugins/e-acsl/doc/doxygen/doxygen.cfg.in new file mode 100644 index 0000000000000000000000000000000000000000..5d8a49c0b4e4c89582bfc092b04b6981d3bc8171 --- /dev/null +++ b/src/plugins/e-acsl/doc/doxygen/doxygen.cfg.in @@ -0,0 +1,1194 @@ +# Doxyfile 1.4.4 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = "E-ACSL Runtime Library" + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = 0.0.6 + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = @abs_top_builddir@/doc/doxygen + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, +# Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese, +# Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian, +# Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, +# Swedish, and Ukrainian. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = NO + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = ../.. + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful is your file systems +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like the Qt-style comments (thus requiring an +# explicit @brief command for a brief description. + +JAVADOC_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the DETAILS_AT_TOP tag is set to YES then Doxygen +# will output the detailed description near the top, like JavaDoc. +# If set to NO, the detailed description appears after the member +# documentation. + +INHERIT_DOCS = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +#SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 4 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources +# only. Doxygen will then generate output that is more tailored for Java. +# For instance, namespaces will be presented as packages, qualified scopes +# will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = YES + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = YES + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or define consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and defines in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 0 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +# If the sources in your project are distributed over multiple directories +# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy +# in the documentation. The default is YES. + +SHOW_DIRECTORIES = NO + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from the +# version control system). Doxygen will invoke the program by executing (via +# popen()) the command <command> <input-file>, where <command> is the value of +# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file +# provided by doxygen. Whatever the progam writes to standard output +# is used as the file version. See the manual for examples. + +#FILE_VERSION_FILTER = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be abled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +#WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = @abs_top_srcdir@/doc/doxygen/warn.log + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = @abs_top_srcdir@/share/e-acsl \ + @abs_top_srcdir@/share/e-acsl/segment_model \ + @abs_top_srcdir@/share/e-acsl/bittree_model + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx +# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm + +FILE_PATTERNS = *.h *.c + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = NO + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = + + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or +# directories that are symbolic links (a Unix filesystem feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = YES + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command <filter> <input-file>, where <filter> +# is the value of the INPUT_FILTER tag, and <input-file> is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER +# is applied to all files. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = YES + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = NO + +# If the REFERENCED_BY_RELATION tag is set to YES (the default) +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = YES + +# If the REFERENCES_RELATION tag is set to YES (the default) +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + +#USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = YES + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 4 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = clang:: + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + +ENUM_VALUES_PER_LINE = 4 + +# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be +# generated containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, +# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are +# probably better off using the HTML help feature. + +GENERATE_TREEVIEW = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = letter + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = NO + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = NO + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. This is useful +# if you want to understand what is going on. On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = YES + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_PREDEFINED tags. + +EXPAND_ONLY_PREDEF = YES + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = __attribute__(x)= + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all function-like macros that are alone +# on a line, have an all uppercase name, and do not end with a semicolon. Such +# function macros are typically used for boiler-plate code, and will confuse +# the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = YES + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option is superseded by the HAVE_DOT option below. This is only a +# fallback. It is recommended to install and use dot, since it yields more +# powerful graphs. + +CLASS_DIAGRAMS = YES + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = NO + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = @HAVE_DOT@ + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = NO + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +#GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will +# generate a call dependency graph for every global function or class method. +# Note that enabling this option will significantly increase the time of a run. +# So in most cases it will be better to enable call graphs for selected +# functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = NO + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are png, jpg, or gif +# If left blank png will be used. + +DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width +# (in pixels) of the graphs generated by dot. If a graph becomes larger than +# this value, doxygen will try to truncate the graph, so that it fits within +# the specified constraint. Beware that most browsers cannot cope with very +# large images. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, which results in a white background. +# Warning: Depending on the platform used, enabling this option may lead to +# badly anti-aliased labels on the edges of a graph (i.e. they become hard to +# read). + +DOT_TRANSPARENT = NO + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = NO + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = NO + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to the search engine +#--------------------------------------------------------------------------- +# The SEARCHENGINE tag specifies whether or not a search engine should be +# used. If set to NO the values of all tags below this one will be ignored. + +SEARCHENGINE = NO diff --git a/src/plugins/e-acsl/doc/refman/.gitignore b/src/plugins/e-acsl/doc/refman/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..2c2b06ea7119f0233f24735f396c4f9bf3f4bd1c --- /dev/null +++ b/src/plugins/e-acsl/doc/refman/.gitignore @@ -0,0 +1,3 @@ +e-acsl.pdf +e-acsl-implementation.pdf +eacslversion.tex diff --git a/src/plugins/e-acsl/doc/refman/Makefile b/src/plugins/e-acsl/doc/refman/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..dfcd08c4719c801628d922dbe77ee2ca414a9cbd --- /dev/null +++ b/src/plugins/e-acsl/doc/refman/Makefile @@ -0,0 +1,123 @@ +########## +# Inputs # +########## + +# If in internal mode, use Frama-C's VERSION +VERSION_FILE=$(wildcard ../../../../../VERSION) +ifeq ("$(VERSION_FILE)","") +VERSION_FILE=../../VERSION +endif +EACSL_VERSION=$(shell cat $(VERSION_FILE)) + +MAIN=main +DEPS_MODERN=macros_modern.tex eacslversion.tex biblio.bib \ + intro_modern.tex speclang_modern.tex \ + libraries_modern.tex concl_modern.tex changes_modern.tex \ + term_modern.bnf binders_modern.bnf predicate_modern.bnf \ + fn_behavior_modern.bnf oldandresult_modern.bnf \ + loc_modern.bnf memory_modern.bnf list-gram.bnf \ + assertions_modern.bnf loops_modern.bnf st_contracts_modern.bnf \ + logic_modern.bnf data_invariants_modern.bnf model_modern.bnf \ + ghost_modern.bnf generalinvariants_modern.bnf iterator_modern.bnf \ + bsearch.c bsearch2.c link.c + +############## +# Main rules # +############## + +.PHONY: all e-acsl default +default: all +e-acsl: e-acsl-implementation.pdf e-acsl.pdf +all: e-acsl + +e-acsl-implementation.pdf: $(DEPS_MODERN) +e-acsl-implementation.tex: $(MAIN).tex Makefile + rm -f $@ + sed -e '/PrintRemarks/s/%--//' $^ > $@ + chmod a-w $@ + +e-acsl.pdf: $(DEPS_MODERN) +e-acsl.tex: e-acsl-implementation.tex Makefile + rm -f $@ + sed -e '/PrintImplementationRq/s/%--//' \ + -e '/ColorImplementationRq/s/%--//' \ + $^ > $@ + chmod a-w $@ + +$(MAIN).pdf: $(DEPS_MODERN) + +EACSL_DIR=../.. +DISTRIB_DIR=$(HOME)/frama-c/doc/www/distrib +install: e-acsl-implementation.pdf e-acsl.pdf + mkdir -p $(EACSL_DIR)/doc/manuals + cp -f $^ $(EACSL_DIR)/doc/manuals + +include $(EACSL_DIR)/doc/support/MakeLaTeXModern + +eacslversion.tex: Makefile $(VERSION_FILE) + rm -f $@ + printf '\\newcommand{\\eacslversion}{$(EACSL_VERSION)}' > $@ + chmod a-w $@ + +.PHONY: clean +clean: + rm -rf *~ *.aux *.log *.nav *.out *.snm *.toc *.lof *.pp *.bnf \ + *.haux *.hbbl *.htoc \ + *.cb *.cm? *.bbl *.blg *.idx *.ind *.ilg \ + transf trans.ml pp.ml pp + +######### +# Tools # +######### + +pp: pp.ml + ocamlopt -o $@ str.cmxa $^ + +transf: transf.cmo transfmain.cmo + ocamlc -o $@ $^ + +transfmain.cmo: transf.cmo + +################# +# Generic rules # +################# + +%.1: %.mp + mpost -interaction=batchmode $< + +%.mps: %.1 + mv $< $@ + +%.pp: %.tex pp + ./pp -utf8 $< > $@ + +%.pp: %.c pp + ./pp -utf8 -c $< > $@ + +%.tex: %.ctex pp + rm -f $@ + ./pp $< > $@ + chmod a-w $@ + +%.bnf: %.tex transf + rm -f $@ + ./transf $< > $@ + chmod a-w $@ + +%_modern.bnf: %.tex transf + rm -f $@ + ./transf -modern $< > $@ + chmod a-w $@ + +%.ml: %.mll + ocamllex $< + +%.pdf: %.tex + pdflatex $* + makeindex $* + bibtex $* + pdflatex $* + pdflatex $* + +%.cmo: %.ml + ocamlc -c $< diff --git a/src/plugins/e-acsl/doc/refman/assertions.tex b/src/plugins/e-acsl/doc/refman/assertions.tex new file mode 100644 index 0000000000000000000000000000000000000000..cb6a92931a6f11881d2ebff24922c092a30b9a95 --- /dev/null +++ b/src/plugins/e-acsl/doc/refman/assertions.tex @@ -0,0 +1,8 @@ +\begin{syntax} + C-compound-statement ::= "{" declaration* statement* assertion+ "}" + \ + C-statement ::= assertion statement \ + assertion-kind ::= "assert" | "check" \ + assertion ::= "/*@" assertion-kind pred ";" "*/" ; + | { "/*@" "for" id ("," id)* ":" assertion-kind pred ";" "*/" } ; +\end{syntax} diff --git a/src/plugins/e-acsl/doc/refman/at.c b/src/plugins/e-acsl/doc/refman/at.c new file mode 100644 index 0000000000000000000000000000000000000000..dad0a3819895eccf8c3eaf5cfad9a375aaf449dd --- /dev/null +++ b/src/plugins/e-acsl/doc/refman/at.c @@ -0,0 +1,15 @@ +/*@ requires \valid(p+(0..1)); + @ requires \valid(q); + @*/ +void f(int *p, int *q) { + *p = 0; + *(p+1) = 1; + *q = 0; + L1: *p = 2; + *(p+1) = 3; + *q = 1; + L2: + /*@ assert (\at(*(p+\at(*q,L1)),Here) == 2); */ + /*@ assert (\at(*(p+\at(*q,Here)),L1) == 1); */ + return ; +} diff --git a/src/plugins/e-acsl/doc/refman/at_on-purely-logic-variables.c b/src/plugins/e-acsl/doc/refman/at_on-purely-logic-variables.c new file mode 100644 index 0000000000000000000000000000000000000000..88bbc974a191e189a3fdaa7e88047b65abf6387f --- /dev/null +++ b/src/plugins/e-acsl/doc/refman/at_on-purely-logic-variables.c @@ -0,0 +1,12 @@ +main(void) { + int m = 2; + int n = 7;; + K: ; + n = 875; + /*@ assert + \let k = 3; + \exists integer u; 9 <= u < 21 && + \forall integer v; -5 < v <= (u < 15 ? u + 6 : k) ==> + \at(n + u + v > 0, K); */ ; + return 0; +} diff --git a/src/plugins/e-acsl/doc/refman/at_on-purely-logic-variables_not-yet.c b/src/plugins/e-acsl/doc/refman/at_on-purely-logic-variables_not-yet.c new file mode 100644 index 0000000000000000000000000000000000000000..dff4da97bd3e5b3fa986023c89a94a7307563cd5 --- /dev/null +++ b/src/plugins/e-acsl/doc/refman/at_on-purely-logic-variables_not-yet.c @@ -0,0 +1,2 @@ +/*@ ensures \forall int i; 0 <= i < n-1 ==> \old(t[i]) == t[i+1]; */ +void reverse(int *t, int n) { } diff --git a/src/plugins/e-acsl/doc/refman/biblio.bib b/src/plugins/e-acsl/doc/refman/biblio.bib new file mode 100644 index 0000000000000000000000000000000000000000..ee79515d0c24ac9af512b4ecbd5f71a88be3ac1f --- /dev/null +++ b/src/plugins/e-acsl/doc/refman/biblio.bib @@ -0,0 +1,83 @@ +@STRING{SV = {Springer}} + +@STRING{LNCS = {Lecture Notes in Computer Science}} + +@INPROCEEDINGS{jml, + author = {Gary T. Leavens and K. Rustan M. Leino and Erik Poll + and Clyde Ruby and Bart Jacobs}, + title = {{JML}: notations and tools supporting detailed design in {Java}}, + booktitle = {{OOPSLA} 2000 Companion, Minneapolis, Minnesota}, + pages = {105--106}, + year = 2000 +} + +@INPROCEEDINGS{chalin07, + author = {Patrice Chalin}, + title = {A Sound Assertion Semantics for the Dependable Systems Evolution + Verifying Compiler}, + booktitle = {Proceedings of the International Conference on Software + Engineering (ICSE'07)}, + pages = {23-33}, + year = 2007, + address = {Los Alamitos, CA, USA}, + publisher = {IEEE Computer Society} +} + +@INPROCEEDINGS{chalin05, + author = {Patrice Chalin}, + title = {Reassessing {JML}'s Logical Foundation}, + booktitle = {Proceedings of the 7th Workshop on Formal Techniques for + Java-like Programs (FTfJP'05)}, + year = 2005, + address = {Glasgow, Scotland}, + month = JUL +} + +@manual{acsl, + title = {{ACSL, ANSI/ISO C Specification Language}}, + author = {Patrick Baudin and Pascal Cuoq and Jean-Christophe Filliâtre and + Claude Marché and Benjamin Monate and Yannick Moy and Virgile Prevosto}, + note = {Vesion 1.12. \url{http://frama-c.com/acsl.html}}, +} + +@manual{acslimplem, + title = {{ACSL version 1.12, Implementation in Silicon-20161101}}, + author = {Patrick Baudin and Pascal Cuoq and Jean-Christophe Filliâtre and + Claude Marché and Benjamin Monate and Yannick Moy and Virgile Prevosto}, + note = {\url{http://frama-c.com/acsl.html}}, +} + +@manual{framac, + title = {Frama-C User Manual}, + author = {Loïc Correnson and Pascal Cuoq and Florent Kirchner and +André Maroneze and +Virgile Prevosto and Armand Puccetti and Julien Signoles and Boris Yakobowski}, + note = {\url{http://frama-c.com}}, +} + +@manual{eacsl-plugin, + title = {Frama-C's E-ACSL Plug-in}, + author = {Julien Signoles and Kostyantyn Vorobyov}, + note = {\url{http://frama-c.com/eacsl.html}}, +} + +@manual{value, + title = {Frama-C's value analysis plug-in}, + author = {Pascal Cuoq and Boris Yakobowski and Matthieu Lemerre and +André Maroneze and Valentin Perelle and Virgile Prevosto}, + note = {\url{http://frama-c.com/value.html}}, +} + +@BOOK{KR88, + author = {Brian Kernighan and Dennis Ritchie}, + title = {The C Programming Language (2nd Ed.)}, + publisher = {Prentice-Hall}, + year = 1988 +} + +@MANUAL{standardc99, + title = {The {ANSI C} standard ({C99})}, + organization = {International Organization for Standardization ({ISO})}, + key = {C99}, + note = {\url{http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1124.pdf}} +} diff --git a/src/plugins/e-acsl/doc/refman/binders.tex b/src/plugins/e-acsl/doc/refman/binders.tex new file mode 100644 index 0000000000000000000000000000000000000000..023fec69d0788b02b3768d5aaf530618422d7802 --- /dev/null +++ b/src/plugins/e-acsl/doc/refman/binders.tex @@ -0,0 +1,18 @@ +\begin{syntax} + binders ::= binder (, binder)* ; + \ + binder ::= type-expr variable-ident; + (,variable-ident)* + \ + type-expr ::= logic-type-expr | C-type-name + \ + logic-type-expr ::= built-in-logic-type ; + | id ; type identifier + \ + built-in-logic-type ::= "boolean" | "integer" | "real" + \ + variable-ident ::= id + | "*" variable-ident ; + | variable-ident "[]"; + | "(" variable-ident ")" +\end{syntax} diff --git a/src/plugins/e-acsl/doc/refman/bsearch.c b/src/plugins/e-acsl/doc/refman/bsearch.c new file mode 100644 index 0000000000000000000000000000000000000000..6025c21a6b8b9cdb58f29f2a2653e4c876db2cca --- /dev/null +++ b/src/plugins/e-acsl/doc/refman/bsearch.c @@ -0,0 +1,25 @@ +/*@ requires n >= 0 && \valid(t+(0..n-1)); + @ assigns \nothing; + @ ensures -1 <= \result <= n-1; + @ behavior success: + @ ensures \result >= 0 ==> t[\result] == v; + @ behavior failure: + @ assumes t_is_sorted : \forall integer k1, int k2; + @ 0 <= k1 <= k2 <= n-1 ==> t[k1] <= t[k2]; + @ ensures \result == -1 ==> + @ \forall integer k; 0 <= k < n ==> t[k] != v; + @*/ +int bsearch(double t[], int n, double v) { + int l = 0, u = n-1; + /*@ loop invariant 0 <= l && u <= n-1; + @ for failure: loop invariant + @ \forall integer k; 0 <= k < n ==> t[k] == v ==> l <= k <= u; + @*/ + while (l <= u ) { + int m = l + (u-l)/2; // better than (l+u)/2 + if (t[m] < v) l = m + 1; + else if (t[m] > v) u = m - 1; + else return m; + } + return -1; +} diff --git a/src/plugins/e-acsl/doc/refman/bsearch2.c b/src/plugins/e-acsl/doc/refman/bsearch2.c new file mode 100644 index 0000000000000000000000000000000000000000..0588ad16723c164bc050736900cd8b001d0e940b --- /dev/null +++ b/src/plugins/e-acsl/doc/refman/bsearch2.c @@ -0,0 +1,29 @@ +/*@ requires n >= 0 && \valid(t+(0..n-1)); + @ assigns \nothing; + @ ensures -1 <= \result <= n-1; + @ behavior success: + @ ensures \result >= 0 ==> t[\result] == v; + @ behavior failure: + @ assumes t_is_sorted : \forall integer k1, int k2; + @ 0 <= k1 <= k2 <= n-1 ==> t[k1] <= t[k2]; + @ ensures \result == -1 ==> + @ \forall integer k; 0 <= k < n ==> t[k] != v; + @*/ +int bsearch(double t[], int n, double v) { + int l = 0, u = n-1; + /*@ assert 0 <= l && u <= n-1; + @ for failure: assert + @ \forall integer k; 0 <= k < n ==> t[k] == v ==> l <= k <= u; + @*/ + while (l <= u ) { + int m = l + (u-l)/2; // better than (l+u)/2 + if (t[m] < v) l = m + 1; + else if (t[m] > v) u = m - 1; + else return m; + /*@ assert 0 <= l && u <= n-1; + @ for failure: assert + @ \forall integer k; 0 <= k < n ==> t[k] == v ==> l <= k <= u; + @*/ ; + } + return -1; +} diff --git a/src/plugins/e-acsl/doc/refman/cealistlogo.jpg b/src/plugins/e-acsl/doc/refman/cealistlogo.jpg new file mode 100644 index 0000000000000000000000000000000000000000..966be5a8ff6d50d9a7f50759633ca144c4c5db1c Binary files /dev/null and b/src/plugins/e-acsl/doc/refman/cealistlogo.jpg differ diff --git a/src/plugins/e-acsl/doc/refman/changes_modern.tex b/src/plugins/e-acsl/doc/refman/changes_modern.tex new file mode 100644 index 0000000000000000000000000000000000000000..ee30a79f7e0de4a4d9ae5f160c63fc98200dc495 --- /dev/null +++ b/src/plugins/e-acsl/doc/refman/changes_modern.tex @@ -0,0 +1,184 @@ +\section{Changes} + +\subsection*{Version \version} +\begin{itemize} +\item Update according to \acsl 1.14: + \begin{itemize} + \item \changeinsection{assertions}{add the keyword \texttt{check}} + \end{itemize} +\end{itemize} + +\subsection*{Version 1.13} +\begin{itemize} +\item Update according to \acsl 1.13: + \begin{itemize} + \item \changeinsection{locations}{add syntax for set membership} + \end{itemize} +\end{itemize} + +\subsection*{Version 1.12} +\begin{itemize} +\item Update according to \acsl 1.12: + \begin{itemize} + \item \changeinsection{locations}{add subsections for build-in lists} + \item \changeinsection{statement_contract}{fix syntax rule for statement + contracts in allowing completeness clauses} + \item \changeinsection{memory}{add syntax for defining a set by giving + explicitly its element} + \item \changeinsection{typedpointers}{new section} + \end{itemize} +\end{itemize} + +\subsection*{Version 1.9} + +\begin{itemize} +\item \changeinsection{alloc-dealloc}{new section} +\item Update according to \acsl 1.9. +\end{itemize} + +\subsection*{Version 1.8} + +\begin{itemize} +\item \changeinsection{locations}{fix example \ref{ex:tset}} +\item \changeinsection{pointers}{add grammar of memory-related terms and + predicates} +\end{itemize} + +\subsection*{Version 1.7} + +\begin{itemize} +\item Update according to \acsl 1.7. +\item \changeinsection{separation}{no more absent} +\end{itemize} + +\subsection*{Version 1.5-4} + +\begin{itemize} +\item Fix typos. +\item \changeinsection{expressions}{fix syntax of guards in iterators} +\item \changeinsection{semantics}{fix definition of undefined terms and + predicates} +\item \changeinsection{typing}{no user-defined types} +\item \changeinsection{builtinconstructs}{no more implementation issue for + \lstinline|\\old|} +\item \changeinsection{at}{more restrictive scoping rule for label references +in \lstinline|\\at|} +\end{itemize} + +\subsection*{Version 1.5-3} + +\begin{itemize} +\item Fix various typos. +\item Warn about features known to be difficult to implement. +\item \changeinsection{expressions}{fix semantics of ternary operator} +\item \changeinsection{expressions}{fix semantics of cast operator} +\item \changeinsection{expressions}{improve syntax of iterator quantifications} +\item \changeinsection{semantics}{improve and fix example \ref{ex:semantics}} +\item \changeinsection{loop_annot}{improve explanations about loop invariants} +\item \changeinsection{logicalstates}{add hybrid functions and predicates} +\end{itemize} + +\subsection*{Version 1.5-2} + +\begin{itemize} +\item \changeinsection{expressions}{remove laziness of operator + \lstinline|<==>|} +\item \changeinsection{expressions}{restrict guarded quantifications to integer} +\item \changeinsection{expressions}{add iterator quantifications} +\item \changeinsection{expressions}{extend unguarded quantifications to char} +\item \changeinsection{locations}{extend syntax of set comprehensions} +\item \changeinsection{loop_annot}{simplify explanations for loop invariants and + add example.} +\end{itemize} + +\subsection*{Version 1.5-1} + +\begin{itemize} +\item Fix many typos. +\item Highlight constructs with semantic changes in grammars. +\item Explain why unsupported features have been removed. +\item Indicate that experimental \acsl features are unsupported. +\item Add operations over memory like \lstinline|\valid|. +\item \changeinsection{expressions}{lazy operators \lstinline|&&|, + \lstinline+||+, \lstinline|\^\^|, \lstinline|==>| and \lstinline|<==>|} +\item \changeinsection{expressions}{allow unguarded quantification over boolean} +\item \changeinsection{expressions}{revise syntax of \lstinline|\\exists|} +\item \changeinsection{semantics}{better semantics for undefinedness} +\item \changeinsection{locations}{revise syntax of set comprehensions} +\item \changeinsection{loop_annot}{add loop invariants, but they lose their + inductive \acsl nature} +\item \changeinsection{generalmeasures}{add general measures for termination} +\item \changeinsection{specmodules}{add specification modules} +\end{itemize} + +\subsection*{Version 1.5-0} + +\begin{itemize} +\item Initial version. +\end{itemize} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\ifthenelse% + {\boolean{PrintImplementationRq}}% + { +\section{Changes in \eacsl Implementation} + +\subsection*{Version \eacslversion} + +\begin{itemize} +\item \changeinsection{reals}{support of rational numbers and operations} +\end{itemize} + +\subsection*{Version Potassium-19} + +\begin{itemize} +\item \changeinsection{logicspec}{support of logic functions and predicates} +\end{itemize} + +\subsection*{Version Argon-18} + +\begin{itemize} +\item \changeinsection{at}{support of \lstinline|\\at| on purely +logic variables} +\item \changeinsection{locations}{support of ranges in memory built-ins + (e.g. \lstinline|\\valid| or \lstinline|\\initialized|)} +\end{itemize} + +\subsection*{Version Chlorine-20180501} + +\begin{itemize} +\item \changeinsection{expressions}{support of \lstinline|\\let| binding} +\end{itemize} + +\subsection*{Version 0.5} + +\begin{itemize} +\item \changeinsection{alloc-dealloc}{support of \lstinline|\\freeable|} +\end{itemize} + +\subsection*{Version 0.3} + +\begin{itemize} +\item \changeinsection{loop_annot}{support of loop invariant} +\end{itemize} + +\subsection*{Version 0.2} + +\begin{itemize} +\item \changeinsection{expressions}{support of bitwise complementation} +\item \changeinsection{memory}{support of \lstinline|\\valid|} +\item \changeinsection{memory}{support of \lstinline|\\block_length|} +\item \changeinsection{memory}{support of \lstinline|\\base_addr|} +\item \changeinsection{memory}{support of \lstinline|\\offset|} +\item \changeinsection{dangling}{support of \lstinline|\\initialized|} +\end{itemize} + +\subsection*{Version 0.1} + +\begin{itemize} +\item Initial version. +\end{itemize} + + }% + {} diff --git a/src/plugins/e-acsl/doc/refman/concl_modern.tex b/src/plugins/e-acsl/doc/refman/concl_modern.tex new file mode 100644 index 0000000000000000000000000000000000000000..58ce943e29c189fb4d75b0098c5683e6405c834c --- /dev/null +++ b/src/plugins/e-acsl/doc/refman/concl_modern.tex @@ -0,0 +1,9 @@ + +\chapter{Conclusion} + +This document presents an Executable ANSI/ISO C Specification Language. It +provides a subset of \acsl~\cite{acsl} implemented~\cite{acslimplem} in the +\framac platform~\cite{framac} in which each construct may be evaluated at +runtime. The specification language described here is intented to evolve in the +future in two directions. First it is based on \acsl which is itself still +evolving. Second the considered subset of \acsl may also change. diff --git a/src/plugins/e-acsl/doc/refman/data_invariants.tex b/src/plugins/e-acsl/doc/refman/data_invariants.tex new file mode 100644 index 0000000000000000000000000000000000000000..6f9186f8c441db2ab04add58868491d60660b32b --- /dev/null +++ b/src/plugins/e-acsl/doc/refman/data_invariants.tex @@ -0,0 +1,13 @@ +\begin{syntax} + declaration ::= { "/*@" data-inv-decl "*/" } + \ + { data-inv-decl } ::= { data-invariant } | { type-invariant } + \ + { data-invariant } ::= { { inv-strength? } "global" "invariant" } ; + { id ":" pred ";" } + \ + { type-invariant } ::= { { inv-strength? } "type" "invariant" }; + { id "(" C-type-name id ")" "=" pred ";" } + \ + { inv-strength } ::= { "weak" } | { "strong" } +\end{syntax} diff --git a/src/plugins/e-acsl/doc/refman/fn_behavior.tex b/src/plugins/e-acsl/doc/refman/fn_behavior.tex new file mode 100644 index 0000000000000000000000000000000000000000..4cd97341aa542521fb64da755d74617ab20726a5 --- /dev/null +++ b/src/plugins/e-acsl/doc/refman/fn_behavior.tex @@ -0,0 +1,28 @@ +\begin{syntax} + [ function-contract ] ::= requires-clause*; + { decreases-clause? } simple-clause*; + named-behavior* { completeness-clause* } + \ + requires-clause ::= "requires" pred ";" + \ + { decreases-clause } ::= { "decreases" term ("for" id)? ";" } + \ + [ simple-clause ] ::= { assigns-clause } | ensures-clause + \ + { assigns-clause } ::= { "assigns" locations ";" } + \ + { locations } ::= { location ("," location) * | "\nothing" } + \ + { location } ::= { tset } + \ + ensures-clause ::= "ensures" pred ";" + \ + named-behavior ::= "behavior" id ":" behavior-body + \ + behavior-body ::= assumes-clause* requires-clause* simple-clause* + \ + assumes-clause ::= "assumes" pred ";" + \ + { completeness-clause } ::= { "complete" "behaviors" (id (","id)*)? ";" } ; + | { "disjoint" "behaviors" (id (","id)*)? ";" } +\end{syntax} diff --git a/src/plugins/e-acsl/doc/refman/frama-c-book.cls b/src/plugins/e-acsl/doc/refman/frama-c-book.cls new file mode 100644 index 0000000000000000000000000000000000000000..562571271e1660418447e02673f904e42fa8ef00 --- /dev/null +++ b/src/plugins/e-acsl/doc/refman/frama-c-book.cls @@ -0,0 +1,332 @@ +% -------------------------------------------------------------------------- +% --- LaTeX Class for Frama-C Books --- +% -------------------------------------------------------------------------- +\NeedsTeXFormat{LaTeX2e} +\ProvidesPackage{frama-c-book}[2009/02/05 LaTeX Class for Frama-C Books] +% -------------------------------------------------------------------------- +% --- Base Class management --- +% -------------------------------------------------------------------------- +\LoadClass[a4paper,11pt,twoside,openright]{report} +\DeclareOption{web}{\PassOptionsToPackage{colorlinks,urlcolor=blue}{hyperref}} +\DeclareOption{paper}{\PassOptionsToPackage{pdfborder=0 0 0}{hyperref}} +\ProcessOptions +\RequirePackage{fullpage} +\RequirePackage{hevea} +\RequirePackage{ifthen} +\RequirePackage[T1]{fontenc} +\RequirePackage[latin1]{inputenc} +\RequirePackage[a4paper,pdftex,pdfstartview=FitH]{hyperref} +\RequirePackage{amssymb} +\RequirePackage{xcolor} +\RequirePackage[pdftex]{graphicx} +\RequirePackage{xspace} +\RequirePackage{makeidx} +\RequirePackage[leftbars]{changebar} +\RequirePackage[english]{babel} +\RequirePackage{fancyhdr} +\RequirePackage{titlesec} +% -------------------------------------------------------------------------- +% --- Page Layout --- +% -------------------------------------------------------------------------- +\setlength{\voffset}{-6mm} +\setlength{\headsep}{8mm} +\setlength{\footskip}{21mm} +\setlength{\textheight}{238mm} +\setlength{\topmargin}{0mm} +\setlength{\textwidth}{155mm} +\setlength{\oddsidemargin}{2mm} +\setlength{\evensidemargin}{-2mm} +\setlength{\changebarsep}{0.5cm} +\setlength{\headheight}{13.6pt} +\def\put@bg(#1,#2)#3{\setlength\unitlength{1cm}% + \begin{picture}(0,0)(#1,#2) + \put(0,0){\includegraphics{#3}} + \end{picture}} +\fancypagestyle{plain}{% + \fancyfoot{} + \fancyhead{} + \fancyhead[LE]{\put@bg(2.4,27.425){frama-c-left.pdf}} + \fancyhead[LO]{\put@bg(2.7,27.425){frama-c-right.pdf}} + \fancyhead[CE]{\scriptsize\textsf{\leftmark}} + \fancyhead[CO]{\scriptsize\textsf{\rightmark}} + \fancyfoot[C]{\small\textsf{\thepage}} + \renewcommand{\headrulewidth}{0pt} + \renewcommand{\footrulewidth}{0pt} +} +\fancypagestyle{blank}{% + \fancyfoot{} + \fancyhead{} + \fancyhead[LE]{\put@bg(2.4,27.425){frama-c-left.pdf}} + \fancyhead[LO]{\put@bg(2.7,27.425){frama-c-right.pdf}} +} +%% Redefinition of cleardoublepage for empty page being blank +\def\cleardoublepagewith#1{\clearpage\if@twoside \ifodd\c@page\else +\hbox{} +\thispagestyle{#1} +\newpage +\fi\fi} +\def\cleardoublepage{\cleardoublepagewith{blank}} +\pagestyle{plain} + +% -------------------------------------------------------------------------- +% --- Cover Page --- +% -------------------------------------------------------------------------- +\newcommand{\coverpage}[1]{% +\thispagestyle{empty} +\setlength\unitlength{1cm} +\begin{picture}(0,0)(3.27,26.75) +\put(0,0){\includegraphics{frama-c-cover.pdf}} +\put(2.0,20.5){\makebox[8cm][l]{\fontfamily{phv}\fontseries{m}\fontsize{24}{2}\selectfont #1}} +\end{picture} +} + +% -------------------------------------------------------------------------- +% --- Title Page --- +% -------------------------------------------------------------------------- +\renewenvironment{titlepage}% +{\cleardoublepagewith{empty}\thispagestyle{empty}\begin{center}}% +{\end{center}} +\renewcommand{\title}[2]{ +\vspace{20mm} +{\Huge\bfseries #1} + +\bigskip + +{\LARGE #2} +\vspace{20mm} +} +\renewcommand{\author}[1]{ +\vspace{20mm} + +{#1} + +\medskip +} +% -------------------------------------------------------------------------- +% --- Sectionning --- +% -------------------------------------------------------------------------- +\titleformat{\chapter}[display]{\Huge\raggedleft}% +{\huge\chaptertitlename\,\thechapter}{0.5em}{} +\titleformat{\section}[hang]{\Large\bfseries}{\thesection}{1em}{}% +[\vspace{-14pt}\rule{\textwidth}{0.1pt}\vspace{-8pt}] +\titleformat{\subsubsection}[hang]{\bfseries}{}{}{}% +[\vspace{-8pt}] + +% -------------------------------------------------------------------------- +% --- Main Text Style --- +% -------------------------------------------------------------------------- +%\raggedright +\setlength\parindent{0pt} +\setlength\parskip{1ex plus 0.3ex minus 0.2ex} +\newenvironment{warning}[1][Warning:]{\small\paragraph{#1}\itshape}{\vspace{\parskip}} +\def\FramaC{\textsf{Frama-C}\xspace} +% -------------------------------------------------------------------------- +% --- Listings --- +% -------------------------------------------------------------------------- +\RequirePackage{listings} + +\lstdefinelanguage{ACSL}{% + morekeywords={assert,assigns,assumes,axiom,axiomatic,behavior,behaviors, + boolean,breaks,complete,continues,data,decreases,disjoint,ensures, + exit_behavior,ghost,global,inductive,integer,invariant,lemma,logic,loop, + model,predicate,reads,real,requires,returns,sizeof,strong,struct,terminates,type, + union,variant}, +% otherkeywords={\\at,\\base_addr,\\block_length,\\false,\\fresh,\\from, +% \\initialized,\\lambda,\\let,\\match,\\max,\\nothing,\\null, +% \\numof,\\old,\\result,\\specified,\\strlen,\\sum,\\true, +% \\valid,\\valid_range}, + keywordsprefix={\\}, + alsoletter={\\}, + morecomment=[l]{//} +} + +\lstloadlanguages{[ANSI]C,[Objective]Caml,csh,ACSL} +\definecolor{lstbg}{gray}{0.98} +\definecolor{lstfg}{gray}{0.10} +\definecolor{lstrule}{gray}{0.6} +\definecolor{lstnum}{gray}{0.4} +\definecolor{lsttxt}{rgb}{0.3,0.2,0.6} +\definecolor{lstmodule}{rgb}{0.3,0.6,0.2}%{0.6,0.6,0.2} +\definecolor{lstspecial}{rgb}{0.2,0.6,0.0} +\definecolor{lstfile}{gray}{0.85} +\newcommand{\lstbrk}{\mbox{$\color{blue}\scriptstyle\cdots$}} +\def\lp@basic{\ifmmode\normalfont\mathtt\mdseries\scriptsize\else\normalfont\ttfamily\mdseries\scriptsize\fi} +\def\lp@inline{\ifmmode\normalfont\mathtt\scriptstyle\else\normalfont\ttfamily\mdseries\small\fi} +\def\lp@keyword{} +\def\lp@special{\color{lstfg}} +\def\lp@comment{\normalfont\ttfamily\mdseries} +\def\lp@string{\color{lstfg}} \def\lp@ident{} +\def\lp@number{\rmfamily\tiny\color{lstnum}} +\lstdefinestyle{frama-c-style}{% + basicstyle=\lp@inline,% + identifierstyle=\lp@ident,% + commentstyle=\lp@comment,% + keywordstyle={\ifmmode\mathsf\else\sffamily\fi},% + keywordstyle=[2]\lp@special,% + stringstyle=\lp@string,% + emphstyle=\lp@ident\underbar,% + showstringspaces=false,% + mathescape=true,% + numberstyle=\lp@number,% + xleftmargin=6ex,xrightmargin=2ex,% + framexleftmargin=1ex,% + frame=l,% + framerule=1pt,% + rulecolor=\color{lstrule},% + backgroundcolor=\color{lstbg},% + moredelim={*[s]{/*@}{*/}},% + moredelim={*[l]{//@}}, + morecomment={[is]{//NOPP-BEGIN}{NOPP-END}}, + mathescape=true, + escapechar=` +% breaklines is broken when using a inline and background +% breaklines,prebreak={\lstbrk},postbreak={\lstbrk},breakindent=5ex % +} + +\lstdefinestyle{c}% +{language={[ANSI]C},alsolanguage=ACSL,style=frama-c-style} +\lstdefinestyle{c-basic}% +{language={[ANSI]C},alsolanguage=ACSL,style=frama-c-style,basicstyle=\lp@basic} + + +% --- C/ACSL Stuff --------------------------------------------------------- +% Make 'c' the default style +\lstset{style=c} + +\newcommand{\listinginput}[3][1]% +{\lstinputlisting[style=c-basic,numbers=left,stepnumber=#1,firstnumber=#2]{#3}} + +\lstnewenvironment{listing}[2][1]% +{\lstset{style=c-basic,numbers=left,stepnumber=#1,firstnumber=#2}}{} + +\lstnewenvironment{listing-nonumber}% +{\lstset{style=c,numbers=none,basicstyle=\lp@basic}}{} + +% --- Verbatim Stuff ------------------------------------------------------- +\lstdefinelanguage{Shell}[]{csh}% +{identifierstyle=\lp@basic,mathescape=false,backgroundcolor=,literate={\\\$}{\$}1} +\lstnewenvironment{shell}[1][]{\lstset{language=Shell,basicstyle=\lp@basic,#1}}{} + +% ---- Stdout Stuff -------------------------------------------------------- +\lstdefinelanguage{Logs}[]{csh}% +{identifierstyle=\lp@basic,backgroundcolor=} +\lstnewenvironment{logs}[1][]{\lstset{language=Logs,basicstyle=\lp@basic,#1}}{} +\newcommand{\logsinput}[1]% +{\lstinputlisting[language=Logs,basicstyle=\lp@basic]{#1}} + +% -------------------------------------------------------------------------- +% --- Developer Code Stuff --- +% -------------------------------------------------------------------------- + +\newcommand{\listingname}[1]{\colorbox{lstfile}{\footnotesize\sffamily File \bfseries #1}\vspace{-4pt}} + +% --- Style ---------------------------------------------------------------- +\lstdefinestyle{framac-code-style}{% +basicstyle=\lp@inline,% +numberstyle=\lp@number,% +keywordstyle=[1]\sffamily\color{lstmodule},% +keywordstyle=[2]\sffamily\color{lstspecial},% +keywordstyle=[3]\sffamily\bfseries,% +identifierstyle=\rmfamily,% +stringstyle=\ttfamily\color{lstfg},% +commentstyle=\rmfamily\bfseries\color{lsttxt},% +} +\lstdefinestyle{framac-shell-style}{% +mathescape=false,% +basicstyle=\lp@basic,% +numberstyle=\lp@number,% +keywordstyle=\sffamily\bfseries,% +keywordstyle=[1]\sffamily\color{lstmodule},% +keywordstyle=[2]\sffamily\color{lstspecial},% +keywordstyle=[3]\sffamily\bfseries,% +identifierstyle=\ttfamily,% +stringstyle=\ttfamily\color{lstfg},% +commentstyle=\rmfamily\bfseries\color{lsttxt},% +literate={\\\$}{\$}1,% +} +% --- Configure ------------------------------------------------------------ +\lstdefinelanguage{Configure}[]{csh}{% +style=framac-shell-style,% +morekeywords={fi},% +} +\lstnewenvironment{configurecode}[1][]% +{\lstset{language=Configure,#1}}{} +\newcommand{\configureinput}[1]{\lstinputlisting[language=Configure]{#1}} +% --- Makefile ------------------------------------------------------------ +\lstdefinelanguage{Makefile}[]{make}{% +style=framac-shell-style,% +morekeywords={include},% +} +\lstnewenvironment{makefilecode}[1][]% +{\lstset{language=Makefile,#1}}{} +\newcommand{\makefileinput}[1]{\lstinputlisting[language=Makefile]{#1}} +% --- C- for Developer ---------------------------------------------------- +\lstdefinestyle{framac-code}% + {language={[ANSI]C},alsolanguage=ACSL,style=framac-code-style,basicstyle=\lp@basic} +\lstnewenvironment{ccode}[1][]% +{\lstset{language={[ANSI]C},alsolanguage=ACSL,style=framac-code-style,basicstyle=\lp@basic,#1}}{} +\newcommand{\cinput}[1]% +{\lstinputlisting[language={[ANSI]C},alsolanguage=ACSL,style=framac-code-style,basicstyle=\lp@basic]{#1}} +\newcommand{\cinline}[1]% +{\lstinline[style=framac-code]{#1}} +% --- Ocaml ---------------------------------------------------------------- +\lstdefinelanguage{Ocaml}[Objective]{Caml}{% +style=framac-code-style,% +deletekeywords={when,module,struct,sig,begin,end},% +morekeywords=[2]{failwith,raise,when},% +morekeywords=[3]{module,struct,sig,begin,end},% +literate=% +{~}{${\scriptstyle\thicksim}$}1% +{<}{$<$}1% +{>}{$>$}1% +{->}{$\rightarrow$}1% +{<-}{$\leftarrow$}1% +{:=}{$\leftarrow$}1% +{<=}{$\leq$}1% +{>=}{$\geq$}1% +{==}{$\equiv$}1% +{!=}{$\not\equiv$}1% +{<>}{$\neq$}1% +{'a}{$\alpha$}1% +{'b}{$\beta$}1% +{'c}{$\gamma$}1% +{µ}{`{}}1% +} + +\lstdefinestyle{ocaml-basic}% +{language=Ocaml,basicstyle=\lp@basic} +\newcommand{\ocamlinput}[2][]{\lstinputlisting[style=ocaml-basic,#1]{#2}} +\lstnewenvironment{ocamlcode}[1][]{\lstset{style=ocaml-basic,#1}}{} +% -------------------------------------------------------------------------- +\lstdefinelanguage{Why}{% + morekeywords={ + type, logic, axiom, predicate, goal, + forall, let, in, + }, + morecomment=[s]{(*}{*)}, + alsoletter={_}, + literate=% + {->}{$\Rightarrow$}1% + {forall}{$\forall$}1% + {not}{$\neg$}1% + {<>}{$\neq$}1% + {...}{$\dots$}1% + %{_}{\_}1% + %{_}{{\rule[0pt]{1ex}{.2pt}}}1% + } + +\lstdefinestyle{why-style}{% +language=Why,% +style=framac-code-style,% +basicstyle=\lp@basic,% +} + +\lstnewenvironment{whycode}[1][]{\lstset{style=why-style,#1}}{} +\newcommand{\whyinput}[1]% +{\lstinputlisting[style=why-style]{#1}} +\newcommand{\whyinline}[1]% +{\lstinline[style=why-style]{#1}} + +% -------------------------------------------------------------------------- +% --- End. --- +% -------------------------------------------------------------------------- diff --git a/src/plugins/e-acsl/doc/refman/frama-c-cover.pdf b/src/plugins/e-acsl/doc/refman/frama-c-cover.pdf new file mode 100644 index 0000000000000000000000000000000000000000..c0b6101f8a9a665f5ca48783d8d1dfefc765ed4a Binary files /dev/null and b/src/plugins/e-acsl/doc/refman/frama-c-cover.pdf differ diff --git a/src/plugins/e-acsl/doc/refman/frama-c-left.pdf b/src/plugins/e-acsl/doc/refman/frama-c-left.pdf new file mode 100644 index 0000000000000000000000000000000000000000..54a64f214ddc0e9dc88eec38303070540962545d Binary files /dev/null and b/src/plugins/e-acsl/doc/refman/frama-c-left.pdf differ diff --git a/src/plugins/e-acsl/doc/refman/frama-c-right.pdf b/src/plugins/e-acsl/doc/refman/frama-c-right.pdf new file mode 100644 index 0000000000000000000000000000000000000000..13ba3e3c03fdca91713629b5b115643281f5c109 Binary files /dev/null and b/src/plugins/e-acsl/doc/refman/frama-c-right.pdf differ diff --git a/src/plugins/e-acsl/doc/refman/generalinvariants.tex b/src/plugins/e-acsl/doc/refman/generalinvariants.tex new file mode 100644 index 0000000000000000000000000000000000000000..246a377d67ff92011258af572e78b8bc3ecc0daf --- /dev/null +++ b/src/plugins/e-acsl/doc/refman/generalinvariants.tex @@ -0,0 +1,4 @@ +\begin{syntax} + assertion ::= [ "/*@" "invariant" pred ";" "*/" ] ; + | [ { "/*@" "for" id ("," id)* ":" "invariant" pred ";" "*/" } ] ; +\end{syntax} diff --git a/src/plugins/e-acsl/doc/refman/ghost.tex b/src/plugins/e-acsl/doc/refman/ghost.tex new file mode 100644 index 0000000000000000000000000000000000000000..1d6d0e9c9e6bd8ff337f7f0f3e4ba13c4085eda5 --- /dev/null +++ b/src/plugins/e-acsl/doc/refman/ghost.tex @@ -0,0 +1,36 @@ +\begin{syntax} + + ghost-type-specifier ::= C-type-specifier ; + | { logic-type } \ + declaration ::= C-declaration ; + | "/*@" "ghost" ghost-declaration "*/" \ + direct-declarator ::= C-direct-declarator ; + | direct-declarator ; + "(" C-parameter-type-list? ")"; + {"/*@" "ghost"}; + {"("ghost-parameter-list")"}; + {"*/"}; ghost args + \ + postfix-expression ::= C-postfix-expression ; + | postfix-expression ; + "(" C-argument-expression-list? ")"; + {"/*@" "ghost"} ; + { "(" ghost-argument-expression-list ")"}; + { "*/"} ; call with ghosts + \ + statement ::= C-statement ; + | statements-ghost \ + statements-ghost ::= "/*@" "ghost" ; + ghost-statement+ "*/" \ + ghost-selection-statement ::= C-selection-statement ; + | "if" "(" C-expression ")"; + statement; + {"/*@" "ghost" "else"}; + { ghost-statement+ }; + { "*/"} \ + + struct-declaration ::= C-struct-declaration ; + | {"/*@" "ghost" }; + {struct-declaration "*/"} ; ghost field + +\end{syntax} diff --git a/src/plugins/e-acsl/doc/refman/intro_modern.tex b/src/plugins/e-acsl/doc/refman/intro_modern.tex new file mode 100644 index 0000000000000000000000000000000000000000..a3bcb11f398a544313ab5e90be3d9d61bfa4df6a --- /dev/null +++ b/src/plugins/e-acsl/doc/refman/intro_modern.tex @@ -0,0 +1,88 @@ +%; whizzy-master "main.tex" +\chapter{Introduction} + +This document is a reference manual for +\ifthenelse{\boolean{PrintImplementationRq}}% +{the \eacsl implementation provided by the \eacsl plug-in~\cite{eacsl-plugin} + (version\eacslversion) of the \framac framework~\cite{framac}.}% +{E-ACSL.} +\eacsl is an acronym for ``Executable ANSI/ISO C +Specification Language''. It is an ``executable'' subset of +\emph{stable} \acsl~\cite{acsl} implemented~\cite{acslimplem} in the \framac +platform~\cite{framac}. ``Stable'' means that no experimental \acsl feature is +supported by \eacsl. Contrary to \acsl, each \eacsl specification is +executable: it may be evaluated at runtime. + +In this document, we assume that the reader has a good knowledge of both +ACSL~\cite{acsl} and the ANSI C programming language~\cite{standardc99,KR88}. + +\section{Organization of this document} + +This document is organized in the very same way that the reference manual of +\acsl~\cite{acsl}. + +Instead of being a fully new reference manual, this document points out the +differences between \eacsl and \acsl. Each \eacsl construct which is not pointed +out must be considered to have the very same semantics than its \acsl +counterpart. For clarity, each relevant grammar rules are given in BNF form +in separate figures like the \acsl reference manual does. In these rules, +constructs with semantic changes are displayed in \markdiff{blue}. + +\ifthenelse{\boolean{PrintImplementationRq}}{% +Not all of the features mentioned in this document are currently +implemented in the \framac's \eacsl plug-in. Those who aren't yet are signaled +as in the following line: +\begin{quote} +\notimplemented[Additional remarks on the feature may appear as footnote.]% +{This feature is not currently supported by \framac's \eacsl plug-in.} +\end{quote} + +As a summary, Figure~\ref{fig:notyet} synthetizes main features that are not +currently implemented into the \framac's \eacsl plug-in. +\begin{figure}[htbp]\label{fig:notyet} + \begin{center} + \begin{tabular}{|l|l|} + \hline + typing + & mathematical reals \\ + \hline + terms + & \lstinline|\\true| and \lstinline|\\false| \\ + & bitwise operators \\ + & let binding \\ + & t-sets \\ + \hline + predicates + & exclusive or operator \\ % \lstinline|^^| + & let bindings \\ + & quantifications over non-integer types \\ + & \lstinline|\\separated| \\ + & \lstinline|\\specified| + \\ + \hline + annotations + & behavior-specific annotations \\ + & loop assigns \\ + & loop variants \\ + & global annotations + \\ + \hline + behavior clauses + & assigns \\ + & decreases \\ + & abrupt termination \\ + & complete and disjoint behaviors + \\ + \hline + \end{tabular} + \end{center} + \caption{Summary of not-yet-implemented features.} +\end{figure} +}% +{} + +\section{Generalities about Annotations}\label{sec:gener-about-annot} +\nodiff + +\section{Notations for grammars} +\nodiff diff --git a/src/plugins/e-acsl/doc/refman/iterator.tex b/src/plugins/e-acsl/doc/refman/iterator.tex new file mode 100644 index 0000000000000000000000000000000000000000..156f6df939a182541e1b808cb176bcbfbc68778f --- /dev/null +++ b/src/plugins/e-acsl/doc/refman/iterator.tex @@ -0,0 +1,12 @@ +\begin{syntax} + declaration ::= [ { "//@" "iterator" id "("wildcard-param"," + wildcard-param")" ":" } ] ; + [ { "nexts" terms ";" "guards" predicates ";" } ] + \ + [ { wildcard-param } ] ::= { parameter } ; + | [ { "_" } ] + \ + [ { terms } ] ::= [ { term (, term)* } ] + \ + [ { predicates } ] ::= [ { predicate (, predicate)* } ] +\end{syntax} diff --git a/src/plugins/e-acsl/doc/refman/libraries_modern.tex b/src/plugins/e-acsl/doc/refman/libraries_modern.tex new file mode 100644 index 0000000000000000000000000000000000000000..4e828cdd1d396e51eba8b9c9a1e7d7a603a0a4d7 --- /dev/null +++ b/src/plugins/e-acsl/doc/refman/libraries_modern.tex @@ -0,0 +1,5 @@ +\chapter{Libraries} +\label{chap:lib} + +\emph{Disclaimer:} this chapter is empty on purpose. It is left here to be +consistent with the \acsl reference manual~\cite{acsl}. diff --git a/src/plugins/e-acsl/doc/refman/link.c b/src/plugins/e-acsl/doc/refman/link.c new file mode 100644 index 0000000000000000000000000000000000000000..e003ebf7ff4ddef5b22c38b3c4272061bd53c378 --- /dev/null +++ b/src/plugins/e-acsl/doc/refman/link.c @@ -0,0 +1,11 @@ +struct btree { + int val; + struct btree *left, *right; +}; + +/*@ iterator access(_, struct btree *t): + @ nexts t->left, t->right; + @ guards \valid(t->left), \valid(t->right); */ + +/*@ predicate is_even(struct btree *t) = + @ \forall struct btree *tt; access(tt, t) ==> tt->val % 2 == 0; */ diff --git a/src/plugins/e-acsl/doc/refman/list-gram.tex b/src/plugins/e-acsl/doc/refman/list-gram.tex new file mode 100644 index 0000000000000000000000000000000000000000..de081932cead22daf4ba87f59ca580258a1fff98 --- /dev/null +++ b/src/plugins/e-acsl/doc/refman/list-gram.tex @@ -0,0 +1,7 @@ +\begin{syntax} + term ::= "[|" "|]" ; empty list + | "[|" term ("," term)* "|]" ; list of elements + | term "^" term ; list concatenation (overloading bitwise-xor + ; operator) + | term "*^" term ; list repetition +\end{syntax} diff --git a/src/plugins/e-acsl/doc/refman/loc.tex b/src/plugins/e-acsl/doc/refman/loc.tex new file mode 100644 index 0000000000000000000000000000000000000000..37cdb3a22a20114794fe130e719b86daf86e6222 --- /dev/null +++ b/src/plugins/e-acsl/doc/refman/loc.tex @@ -0,0 +1,21 @@ +\begin{syntax} + tset ::= { "\empty" } ; empty set + | tset "->" id ; + | tset "." id ; + | "*" tset ; + | "&" tset ; + | tset "[" tset "]" ; + | [ term ".." term ] ; range + | { "\union" "(" tset ("," tset)* ")" } ; union of locations + | { "\inter" "(" tset ("," tset)* ")" }; intersection + | tset "+" tset ; + | "(" tset ")" ; + | {[the given term cannot itself be a set] + "{" tset "|" binders (";" pred)? "}"} ; set comprehension + | {[the given terms cannot themselves be a set] + "{" (tset ("," tset)*)? "}" }; + | term ; implicit singleton + \ + pred ::= { "\subset" "(" tset "," tset ")" } ; set inclusion + | { term "\in" tset } ; set membership +\end{syntax} diff --git a/src/plugins/e-acsl/doc/refman/logic.tex b/src/plugins/e-acsl/doc/refman/logic.tex new file mode 100644 index 0000000000000000000000000000000000000000..53b4a3aacc2270e356c6c57ebba15f2d170c648b --- /dev/null +++ b/src/plugins/e-acsl/doc/refman/logic.tex @@ -0,0 +1,19 @@ +\begin{syntax} + C-global-decl ::= "/*@" logic-def+ "*/" + \ + logic-def ::= { logic-const-def } ; + | logic-function-def ; + | logic-predicate-def ; + \ + type-expr ::= id; + \ + { logic-const-def } ::= { "logic" type-expr id "=" term ";" } + \ + logic-function-def ::= "logic" type-expr id parameters "=" term ";" + \ + logic-predicate-def ::= "predicate" id parameters? "=" pred ";" + \ + parameters ::= "(" parameter (, parameter)* ")" + \ + parameter ::= type-expr id +\end{syntax} diff --git a/src/plugins/e-acsl/doc/refman/loops.tex b/src/plugins/e-acsl/doc/refman/loops.tex new file mode 100644 index 0000000000000000000000000000000000000000..5d1fa33003cbcc7674420f0e8f2231c7e12ca625 --- /dev/null +++ b/src/plugins/e-acsl/doc/refman/loops.tex @@ -0,0 +1,28 @@ +\begin{syntax} + statement ::= "/*@" loop-annot "*/" ; + "while" "(" C-expression ")" C-statement ; + | "/*@" loop-annot "*/" ; + "for"; + "(" C-expression ";" C-expression ";" C-expression ")"; + statement ; + | "/*@" loop-annot "*/" ; + "do" C-statement ; + "while" "(" C-expression ")" ";" + \ + loop-annot ::= loop-clause* ; + { loop-behavior* } ; + { loop-variant? } + \ + loop-clause ::= loop-invariant ; + | { loop-assigns } + \ + [ loop-invariant ] ::= [ "loop" "invariant" pred ";" ] ; + \ + { loop-assigns } ::= { "loop" "assigns" locations ";" } ; + \ + { loop-behavior } ::= { "for" id ("," id)* ":" } ; + { loop-clause* } ; \hspace{-30mm} annotation for behavior $id$ + \ + { loop-variant } ::= { "loop" "variant" term ";" } ; + | { "loop" "variant" term "for" id ";" } ; \hspace{-30mm} variant for relation $id$ +\end{syntax} diff --git a/src/plugins/e-acsl/doc/refman/macros_modern.tex b/src/plugins/e-acsl/doc/refman/macros_modern.tex new file mode 100644 index 0000000000000000000000000000000000000000..86b8cd8244b4805b854fb1d1ea5450ab67ab370e --- /dev/null +++ b/src/plugins/e-acsl/doc/refman/macros_modern.tex @@ -0,0 +1,252 @@ +%%% Environnements dont le corps est suprimé, et +%%% commandes dont la définition est vide, +%%% lorsque PrintRemarks=false + +\usepackage{comment} + +\newcommand{\framac}{\textsc{Frama-C}\xspace} +\newcommand{\acsl}{\textsc{ACSL}\xspace} +\newcommand{\eacsl}{\textsc{E-ACSL}\xspace} +\newcommand{\C}{\textsc{C}\xspace} +\newcommand{\jml}{\textsc{JML}\xspace} + +\newcommand{\nodiff}{\emph{No difference with \acsl.}} +\newcommand{\except}[1]{\emph{No difference with \acsl, but #1.}} +\newcommand{\limited}[1]{\emph{Limited to #1.}} +\newcommand{\absent}{\emph{No such feature in \eacsl.}} +\newcommand{\absentwhy}[1]{\emph{No such feature in \eacsl: #1.}} +\newcommand{\absentexperimental}{\emph{No such feature in \eacsl, since it is + still experimental in \acsl.}} +\newcommand{\absentexcept}[1]{\emph{No such feature in \eacsl, but #1.}} +\newcommand{\difficultwhy}[2]{\emph{#1 is usually difficult to implement, since + it requires #2. Thus you would not wonder if most tools do not support it + (or support it partially).}} +\newcommand{\difficultswhy}[2]{\emph{#1 are usually difficult to implement, + since they require #2. Thus you would not wonder if most tools do not + support them (or support them partially).}} +\newcommand{\difficult}[1]{\emph{#1 is usually difficult to implement. Thus + you would not wonder if most tools do not support it (or support + it partially).}} +\newcommand{\difficults}[1]{\emph{#1 are usually difficult to implement. Thus + you would not wonder if most tools do not support them (or support + them partially).}} + +\newcommand{\mywarning}[1]{\paragraph{Warning:} #1} + +\newcommand{\changeinsection}[2]{\textbf{Section \ref{sec:#1}:} #2.} + +\newcommand{\todo}[1]{{\large \textbf{TODO: #1.}}} + +\newcommand{\markdiff}[1]{{\color{blue}{#1}}} +\newenvironment{markdiffenv}[1][]{% + \begin{changebar}% + \markdiff\bgroup% +}% +{\egroup\end{changebar}} + +% true = prints remarks for the ACSL working group. +% false = prints no remark for the distributed version of ASCL documents +\newboolean{PrintRemarks} +\setboolean{PrintRemarks}{false} + +% true = prints marks signaling the state of the implementation +% false = prints only the ACSL definition, without remarks on implementation. +\newboolean{PrintImplementationRq} +\setboolean{PrintImplementationRq}{true} + +% true = remarks about the current state of implementation in Frama-C +% are in color. +% false = they are rendered with an underline +\newboolean{ColorImplementationRq} +\setboolean{ColorImplementationRq}{true} + +%% \ifthenelse{\boolean{PrintRemarks}}% +%% {\newenvironment{todo}{% +%% \begin{quote}% +%% \begin{tabular}{||p{0.8\textwidth}}TODO~:\itshape}% +%% {\end{tabular}\end{quote}}}% +%% {\excludecomment{todo}} + +\ifthenelse{\boolean{PrintRemarks}}% + {\newenvironment{remark}[1]{% + \begin{quote}\itshape% + \begin{tabular}{||p{0.8\textwidth}}Remarque de {#1}~:}% + {\end{tabular}\end{quote}}}% + {\excludecomment{remark}} + +\newcommand{\oldremark}[2]{% +\ifthenelse{\boolean{PrintRemarks}}{% + %\begin{quote}\itshape% + %\begin{tabular}{||p{0.8\textwidth}}Vieille remarque de {#1}~: #2% + %\end{tabular}\end{quote}% +}% +{}} + +\newcommand{\highlightnotreviewed}{% +\color{blue}% +}% + +\newcommand{\notreviewed}[2][]{% +\ifthenelse{\boolean{PrintRemarks}}{% + \begin{changebar}% + {\highlightnotreviewed #2}% + \ifthenelse{\equal{#1}{}}{}{\footnote{#1}}% + \end{changebar}% +}% +{}} + +\ifthenelse{\boolean{PrintRemarks}}{% +\newenvironment{notreviewedenv}[1][]{% + \begin{changebar}% + \highlightnotreviewed% + \ifthenelse{\equal{#1}{}}{}{\def\myrq{#1}}% + \bgroup}% + {\egroup% + \ifthenelse{\isundefined{\myrq}}{}{\footnote{\myrq}}\end{changebar}}}% +{\excludecomment{notreviewedenv}} + +%%% Commandes et environnements pour la version relative à l'implementation +\newcommand{\highlightnotimplemented}{% +\ifthenelse{\boolean{ColorImplementationRq}}{\color{red}}% + {}% +}% + +\newcommand{\notimplemented}[2][]{% +\ifthenelse{\boolean{PrintImplementationRq}}{% + \begin{changebar}% + {\highlightnotimplemented #2}% + \ifthenelse{\equal{#1}{}}{}{\footnote{#1}}% + \end{changebar}% +}% +{#2}} + +\newenvironment{notimplementedenv}[1][]{% +\ifthenelse{\boolean{PrintImplementationRq}}{% + \begin{changebar}% + \highlightnotimplemented% + \ifthenelse{\equal{#1}{}}{}{\def\myrq{#1}}% + \bgroup +}{}}% +{\ifthenelse{\boolean{PrintImplementationRq}}{% + \egroup% + \ifthenelse{\isundefined{\myrq}}{}{\footnote{\myrq}}\end{changebar}}{}} + +%%% Environnements et commandes non conditionnelles +\newcommand{\experimental}{\textsc{Experimental}} + +\newsavebox{\fmbox} +\newenvironment{cadre} + {\begin{lrbox}{\fmbox}\begin{minipage}{0.98\textwidth}} + {\end{minipage}\end{lrbox}\fbox{\usebox{\fmbox}}} + + +\newcommand{\keyword}[1]{\lstinline|#1|\xspace} +\newcommand{\keywordbs}[1]{\lstinline|\\#1|\xspace} + +\newcommand{\integer}{\keyword{integer}} +\newcommand{\real}{\keyword{real}} +\newcommand{\bool}{\keyword{boolean}} + +\newcommand{\assert}{\keyword{assert}} +\newcommand{\terminates}{\keyword{terminates}} +\newcommand{\assume}{\keyword{assume}} +\newcommand{\requires}{\keyword{requires}} +\newcommand{\ensures}{\keyword{ensures}} +\newcommand{\exits}{\keyword{exits}} +\newcommand{\returns}{\keyword{returns}} +\newcommand{\breaks}{\keyword{breaks}} +\newcommand{\continues}{\keyword{continues}} +\newcommand{\assumes}{\keyword{assumes}} +\newcommand{\assigns}{\keyword{assigns}} +\newcommand{\reads}{\keyword{reads}} +\newcommand{\decreases}{\keyword{decreases}} + +\newcommand{\boundseparated}{\keywordbs{bound\_separated}} +\newcommand{\Exists}{\keywordbs{exists}~} +\newcommand{\Forall}{\keywordbs{forall}~} +\newcommand{\bslambda}{\keywordbs{lambda}~} +\newcommand{\freed}{\keywordbs{freed}} +\newcommand{\fresh}{\keywordbs{fresh}} +\newcommand{\fullseparated}{\keywordbs{full\_separated}} +\newcommand{\distinct}{\keywordbs{distinct}} +\newcommand{\Max}{\keyword{max}} +\newcommand{\nothing}{\keywordbs{nothing}} +\newcommand{\numof}{\keyword{num\_of}} +\newcommand{\offsetmin}{\keywordbs{offset\_min}} +\newcommand{\offsetmax}{\keywordbs{offset\_max}} +\newcommand{\old}{\keywordbs{old}} +\newcommand{\at}{\keywordbs{at}} + +\newcommand{\If}{\keyword{if}~} +\newcommand{\Then}{~\keyword{then}~} +\newcommand{\Else}{~\keyword{else}~} +\newcommand{\For}{\keyword{for}~} +\newcommand{\While}{~\keyword{while}~} +\newcommand{\Do}{~\keyword{do}~} +\newcommand{\Let}{\keywordbs{let}~} +\newcommand{\Break}{\keyword{break}} +\newcommand{\Return}{\keyword{return}} +\newcommand{\Continue}{\keyword{continue}} + +\newcommand{\exit}{\keyword{exit}} +\newcommand{\main}{\keyword{main}} +\newcommand{\void}{\keyword{void}} + +\newcommand{\struct}{\keyword{struct}} +\newcommand{\union}{\keywordbs{union}} +\newcommand{\inter}{\keywordbs{inter}} +\newcommand{\typedef}{\keyword{typedef}} +\newcommand{\result}{\keywordbs{result}} +\newcommand{\separated}{\keywordbs{separated}} +\newcommand{\sizeof}{\keyword{sizeof}} +\newcommand{\strlen}{\keywordbs{strlen}} +\newcommand{\Sum}{\keyword{sum}} +\newcommand{\valid}{\keywordbs{valid}} +\newcommand{\validrange}{\keywordbs{valid\_range}} +\newcommand{\offset}{\keywordbs{offset}} +\newcommand{\blocklength}{\keywordbs{block\_length}} +\newcommand{\baseaddr}{\keywordbs{base\_addr}} +\newcommand{\comparable}{\keywordbs{comparable}} + +\newcommand{\N}{\ensuremath{\mathbb{N}}} +\newcommand{\ra}{\ensuremath{\rightarrow}} +\newcommand{\la}{\ensuremath{\leftarrow}} + +% BNF grammar +\newcommand{\indextt}[1]{\index{#1@\protect\keyword{#1}}} +\newcommand{\indexttbs}[1]{\index{#1@\protect\keywordbs{#1}}} +\newif\ifspace +\newif\ifnewentry +\newcommand{\addspace}{\ifspace ~ \spacefalse \fi} +\newcommand{\term}[2]{\addspace\hbox{\lstinline|#1|% +\ifthenelse{\equal{#2}{}}{}{\indexttbase{#2}{#1}}}\spacetrue} +\newcommand{\nonterm}[2]{% + \ifthenelse{\equal{#2}{}}% + {\addspace\hbox{\textsl{#1}\ifnewentry\index{grammar entries!\textsl{#1}}\fi}\spacetrue}% + {\addspace\hbox{\textsl{#1}\footnote{#2}\ifnewentry\index{grammar entries!\textsl{#1}}\fi}\spacetrue}} +\newcommand{\repetstar}{$^*$\spacetrue} +\newcommand{\repetplus}{$^+$\spacetrue} +\newcommand{\repetone}{$^?$\spacetrue} +\newcommand{\lparen}{\addspace(} +\newcommand{\rparen}{)} +\newcommand{\orelse}{\addspace$\mid$\spacetrue} +\newcommand{\sep}{ \\[2mm] \spacefalse\newentrytrue} +\newcommand{\newl}{ \\ & & \spacefalse} +\newcommand{\alt}{ \\ & $\mid$ & \spacefalse} +\newcommand{\is}{ & $::=$ & \newentryfalse} +\newenvironment{syntax}{\begin{tabular}{@{}rrll@{}}\spacefalse\newentrytrue}{\end{tabular}} +\newcommand{\synt}[1]{$\spacefalse#1$} +\newcommand{\emptystring}{$\epsilon$} +\newcommand{\below}{See\; below} + +% colors + +\definecolor{darkgreen}{rgb}{0, 0.5, 0} + +% theorems + +\newtheorem{example}{Example}[chapter] + +% for texttt + +\newcommand{\bs}{\ensuremath{\backslash}} diff --git a/src/plugins/e-acsl/doc/refman/main.tex b/src/plugins/e-acsl/doc/refman/main.tex new file mode 100644 index 0000000000000000000000000000000000000000..88c2665b3138eb4593be41a543f86a070172ef12 --- /dev/null +++ b/src/plugins/e-acsl/doc/refman/main.tex @@ -0,0 +1,120 @@ +%; whizzy section -pdf -initex "pdflatex -ini" +\documentclass[web]{frama-c-book} +\usepackage{hevea} +\usepackage{ifthen} + +\input{./macros_modern} +\input{eacslversion.tex} +%Do not touch the following line. It is used in a Makefile hack to +%produce the ACSL documents for the ACSL working group. +%--\setboolean{PrintRemarks}{false} + +%Do not touch the following line. It is used in a Makefile hack to +%produce the ACSL document shipped with the Frama-C distribution. +%--\setboolean{PrintImplementationRq}{false} +%--\setboolean{ColorImplementationRq}{false} + +\usepackage{amssymb} +\usepackage{graphicx} +\usepackage{color} +\usepackage{xspace} +\usepackage{makeidx} +\usepackage[normalem]{ulem} +\usepackage[leftbars]{changebar} +\usepackage{alltt} +\makeindex + +\newcommand{\acslversion}{1.14\xspace} +\newcommand{\version}{\acslversion\xspace} + +\renewcommand{\textfraction}{0.01} +\renewcommand{\topfraction}{0.99} +\renewcommand{\bottomfraction}{0.99} + +\begin{document} +\sloppy +\hbadness=10000 + +\ifthenelse{\boolean{PrintImplementationRq}}% + {\coverpage{\vbox{\mbox{E-ACSL Version \version}\\[5mm] +\mbox{\huge{Implementation in Frama-C plug-in E-ACSL}}\\[2mm] +\mbox{\huge{version \eacslversion{}}}}}}% + {\coverpage{\vbox{\mbox{E-ACSL}\\[2mm]\vbox{\mbox{\huge{Executable ANSI/ISO C + Specification Language}}}\\[2mm] + \mbox{Version \version}}}} + +\begin{titlepage} +\includegraphics[height=14mm]{cealistlogo.jpg} +\vfill +\title{E-ACSL\\[5mm]\huge{Executable ANSI/ISO C Specification Language}}% +{Version \version{}\ifthenelse{\boolean{PrintImplementationRq}}% +{~--~Frama-C plug-in E-ACSL version \eacslversion}{}} + +\author{Julien Signoles} + +CEA LIST, Software Reliability Laboratory\\ +\vfill +\begin{flushleft} + \textcopyright 2011-2018 CEA LIST + + This work has been initially supported by the `Hi-Lite' FUI project (FUI AAP + 9). +\end{flushleft} +\end{titlepage} + +%%Contents should open on right +\cleardoublepage +\phantomsection +\label{chap:contents} +\tableofcontents + +\chapter*{Foreword} + +This document describes version \version of the \eacsl specification +language. It is based on the \acsl specification language~\cite{acsl}. Features +of both languages may still evolve in the future, even if we do our best to +preserve backward compatibility. + +\section*{Acknowledgements} + +We gratefully thank all the people who contributed to this document: +Patrick Baudin, +Bernard Botella, +Lo\"ic Correnson, +Pascal Cuoq, +Johannes Kanig, +Fonenantsoa Maurica, +David Mentr\'e, +Benjamin Monate, +Yannick Moy and +Virgile Prevosto. + +\include{intro_modern} + +\include{speclang_modern} + +\include{libraries_modern} + +\include{concl_modern} + +\appendix + +\chapter{Appendices} +\label{chap:appendix} + +\include{changes_modern} + +\cleardoublepage +\addcontentsline{toc}{chapter}{\bibname} +\bibliographystyle{plain} +\bibliography{./biblio} + +\cleardoublepage +\addcontentsline{toc}{chapter}{\listfigurename} +\listoffigures + +\cleardoublepage +\addcontentsline{toc}{chapter}{\indexname} +\printindex + +\end{document} diff --git a/src/plugins/e-acsl/doc/refman/memory.tex b/src/plugins/e-acsl/doc/refman/memory.tex new file mode 100644 index 0000000000000000000000000000000000000000..7626c08e864f13b87a275c02a23aac5f06aaef5e --- /dev/null +++ b/src/plugins/e-acsl/doc/refman/memory.tex @@ -0,0 +1,27 @@ +\begin{syntax} + term ::= "\null" ; + | "\base_addr" { one-label? } "(" term ")" ; + | "\block_length" { one-label? } "(" term ")" ; + | "\offset" { one-label? } "(" term ")" ; + | { "\allocation" one-label? "(" term ")" }; + \ + pred ::= { "\allocable" one-label? "(" term ")" }; + | "\freeable" { one-label? } "(" term ")" ; + | { "\fresh" two-labels? "(" term, term ")" }; + | "\valid" { one-label? } "(" location-address ")" ; + | "\valid_read" { one-label? } "(" location-address ")"; + | { "\separated" "(" location-address "," location-addresses ")" }; + \ + { one-label } ::= { "{" id "}" } ; + \ + { two-labels } ::= { "{" id, id "}" } ; + \ + location-addresses ::= location-address ("," location-address)* + \ + location-address ::= tset +\end{syntax} + +%%% Local Variables: +%%% mode: latex +%%% TeX-master: "main" +%%% End: diff --git a/src/plugins/e-acsl/doc/refman/model.tex b/src/plugins/e-acsl/doc/refman/model.tex new file mode 100644 index 0000000000000000000000000000000000000000..d46d192e91e764114ccadccc7a39308c6c24f33a --- /dev/null +++ b/src/plugins/e-acsl/doc/refman/model.tex @@ -0,0 +1,5 @@ +\begin{syntax} + declaration ::= C-declaration ; + | {"/*@" "model" parameter ";" "*/"} ; model variable + | { "/*@" "model" C-type-name "{" parameter ";"? "}" ";" "*/" } ; model field +\end{syntax} diff --git a/src/plugins/e-acsl/doc/refman/oldandresult.tex b/src/plugins/e-acsl/doc/refman/oldandresult.tex new file mode 100644 index 0000000000000000000000000000000000000000..1e2bfd448d38abfad87769315da0be7997359923 --- /dev/null +++ b/src/plugins/e-acsl/doc/refman/oldandresult.tex @@ -0,0 +1,11 @@ +\begin{syntax} + term ::= "\old" "(" term ")" ; old value + | "\result" ; result of a function + \ + pred ::= "\old" "(" pred ")" +\end{syntax} + +%%% Local Variables: +%%% mode: latex +%%% TeX-master: "main" +%%% End: diff --git a/src/plugins/e-acsl/doc/refman/predicate.tex b/src/plugins/e-acsl/doc/refman/predicate.tex new file mode 100644 index 0000000000000000000000000000000000000000..ae1dcfb610805a2408af395f3996ce3c00116f95 --- /dev/null +++ b/src/plugins/e-acsl/doc/refman/predicate.tex @@ -0,0 +1,40 @@ +\begin{syntax} + rel-op ::= "==" | "!=" | "<=" | ">=" | ">" | "<" + \ + pred ::= "\true" | "\false" ; + | term (rel-op term)+ ; comparisons + | { id "(" term ("," term)* ")" } ; predicate application + | "(" pred ")" ; parentheses + | [ pred "&&" pred ] ; conjunction + | [ pred "||" pred ] ; disjunction + | [ pred "==>" pred ] ; implication + | pred "<==>" pred ; equivalence + | "!" pred ; negation + | [ { pred "^^" pred } ] ; exclusive or + | [ term "?" pred ":" pred ] ; ternary condition + | [ pred "?" pred ":" pred ]; + | "\let" id "=" term ";" pred ; local binding + | { "\let" id "=" pred ";" pred }; + | [ "\forall" binders ";" ] ; + [ integer-guards "==>" pred ]; univ. integer quantification + | [ "\exists" binders ";" ]; + [ integer-guards "&&" pred ] ; exist. integer quantification + | [ { "\forall" binders ";" } ] ; + [ { iterator-guard "==>" pred } ]; univ. iterator quantification + | [ { "\exists" binders ";" } ]; + [ { iterator-guard "&&" pred } ] ; exist. iterator quantification + | [ { "\forall" binders ";" pred } ]; univ. quantification + | [ { "\exists" binders ";" pred } ]; exist. quantification + | id ":" pred ; syntactic naming + | string ":" pred ; syntactic naming + \ + [ integer-guards ] ::= [ interv ("&&" interv)* ] + \ + [ interv ] ::= [ (term integer-guard-op)+ ] ; + [ id ] ; + [ (integer-guard-op term)+ ] + \ + [ integer-guard-op ] ::= [ "<=" | "<" ] + \ + [ { iterator-guard } ] ::= [ { id "(" term"," term ")" } ] +\end{syntax} diff --git a/src/plugins/e-acsl/doc/refman/speclang_modern.tex b/src/plugins/e-acsl/doc/refman/speclang_modern.tex new file mode 100644 index 0000000000000000000000000000000000000000..c1482c0d65cbb0df19eccf95a887d310ac7a5f22 --- /dev/null +++ b/src/plugins/e-acsl/doc/refman/speclang_modern.tex @@ -0,0 +1,853 @@ +%; whizzy-master "main.tex" + +\chapter{Specification language} +\label{chap:base} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\section{Lexical rules} +\nodiff + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\section{Logic expressions} +\label{sec:expressions} + +\except{guarded quantificatication}. + +More precisely, grammars of terms and binders presented respectively +Figures~\ref{fig:gram:term} and~\ref{fig:gram:binders} are the same than the one +of \acsl, while Figure~\ref{fig:gram:pred} presents grammar of predicates. The +only difference between \eacsl and \acsl predicates are quantifications. + +\begin{figure}[htbp] + \begin{cadre} + \input{term_modern.bnf} + \end{cadre} + \caption{Grammar of terms} +\label{fig:gram:term} +\end{figure} +\begin{figure}[htbp] + \begin{cadre} + \input{predicate_modern.bnf} + \end{cadre} + \caption{Grammar of predicates} +\label{fig:gram:pred} +\end{figure} +\begin{figure}[htbp] + \fbox{\begin{minipage}{0.97\textwidth} \input{binders_modern.bnf} + \end{minipage}} + \caption{Grammar of binders and type expressions} +\label{fig:gram:binders} +\end{figure} + +\subsection*{Quantification} +\eacsl quantification must be computable. They are limited to two limited forms. + +\begin{description} +\item[Guarded integer quantification] Guarded universal quantification is + denoted by +\begin{lstlisting} +\forall $\tau$ $x_1$,$\ldots$,$x_n$; + $a_1$ <= $x_1$ <= $b_1$ $\ldots$ && $a_n$ <= $x_n$ <= $b_n$ + ==> p +\end{lstlisting} and guarded existential quantification by +\begin{lstlisting} +\exists $\tau$ $x_1$,$\ldots$,$x_n$; + $a_1$ <= $x_1$ <= $b_1$ $\ldots$ && $a_n$ <= $x_n$ <= $b_n$ + && p +\end{lstlisting} +Each variable must be guarded exactly once and the guard of $x_i$ must appear +before the guard of $x_j$ if $i < j$ (\emph{i.e.} order of guards must follow +order of binders). + +Following the definition, each quantified variable belongs to a finite +interval. Since finite interval is only computable in practice for integers, +this form of quantifier is limited to \texttt{integer} and its subtype. Thus +there is no guarded quantification over \texttt{float}, \texttt{real}, \C +pointers or logic types. + +\item[{\highlightnotimplemented{Iterator quantification}}] In order to iterate + over non-integer types, \eacsl introduces a notion of $iterators$ over types: + standard \acsl unguarded quantifications are only allowed over a type which an + iterator is attached to. + + Iterators are introduced by a specific construct which attachs two sets --- + namely \texttt{nexts} and the \texttt{guards} --- to a binary predicate over a + type $\tau$. Both sets must have the same cardinal. This construct is + described by the grammar of Figure~\ref{fig:gram:iterator}. + \begin{figure}[htbp] + \begin{cadre} + \input{iterator_modern.bnf} + \end{cadre} + \caption{Grammar of iterator declarations} + \label{fig:gram:iterator} + \end{figure} + For a type $\tau$, \texttt{nexts} is a set of terms which take an argument of + type $\tau$ and return a value of type $\tau$ which computes the next element + in this type, while \texttt{guards} is a set of predicates which take an + argument of type $\tau$ and are valid (resp. invalid) to continue (resp. stop) + the iteration. + + Furthermore, the guard of a quantification using an iterator must be the + predicate given in the definition of the iterator. This abstract binary + predicate takes two arguments of the same type. One of them must be unnamed by + using a wildcard (character underscore \texttt{'\_'}). The unnamed argument + must be binded to the guantifier, while the other corresponds to the term from + which the iteration begins. + \begin{example} + The following example introduces binary trees and a predicate which is valid + if and only if each value of a binary tree is even. + \cinput{link.c} + \end{example} + +\item[{\highlightnotimplemented{Unguarded quantification}}] They are only + allowed over boolean and char. +\end{description} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\subsection{Operators precedence} +\nodiff + +Figure~\ref{fig:precedence} summarizes operator precedences. +\begin{figure}[htbp] + \begin{center} + \begin{tabular}{|l|l|l|} + \hline + class & associativity & operators \\ + \hline + selection & left & \lstinline|[$\cdots$]| \lstinline|->| \lstinline|.| \\ + unary & right & \lstinline|!| \lstinline|~| \lstinline|+| + \lstinline|-| \lstinline|*| \lstinline|&| \lstinline|(cast)| + \lstinline|sizeof| \\ + multiplicative & left & \lstinline|*| \lstinline|/| \lstinline|%| \\ + additive & left & \lstinline|+| \lstinline|-| \\ + shift & left & \lstinline|<<| \lstinline|>>| \\ + comparison & left & \lstinline|<| \lstinline|<=| \lstinline|>| \lstinline|>=| \\ + comparison & left & \lstinline|==| \lstinline|!=| \\ + bitwise and & left & \lstinline|&| \\ + bitwise xor & left & \lstinline|^| \\ + bitwise or & left & \lstinline+|+ \\ + bitwise implies & left & \lstinline+-->+ \\ + bitwise equiv & left & \lstinline+<-->+ \\ + connective and & left & \lstinline|&&| \\ + connective xor & left & \lstinline+^^+ \\ + connective or & left & \lstinline+||+ \\ + connective implies & right & \lstinline|==>| \\ + connective equiv & left & \lstinline|<==>| \\ + ternary connective & right & \lstinline|$\cdots$?$\cdots$:$\cdots$| \\ + binding & left & \Forall{} \Exists{} \Let{} \\ + naming & right & \lstinline|:| \\ + \hline + \end{tabular} + \end{center} + \caption{Operator precedence} +\label{fig:precedence} +\end{figure} + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\subsection{Semantics} +\label{sec:semantics} + +\except{undefinedness and same laziness than \C} + +More precisely, while \acsl is a 2-valued logic with only total +functions, \eacsl is a 3-valued logic with partial functions since +terms and predicates may be ``undefined''. + +In this logic, the semantics of a term denoting a \C expression $e$ is undefined +if $e$ leads to a runtime error. Consequently the semantics of any term $t$ +(resp. predicate $p$) containing a \C expression $e$ leading to a runtime error +is undefined if $e$ has to be evaluated in order to evaluate $t$ (resp. $p$). +\begin{remark}[Julien] +$e$ always terminates, thus no termination issue. +\end{remark} +\begin{example} +The semantics of all the below predicates are undefined: +\begin{itemize} +\item \lstinline|1/0 == 1/0| +\item \lstinline|f(*p)| for any logic function \lstinline|f| and invalid pointer + \lstinline|p| +\end{itemize} +\end{example} + +Furthermore, \C-like operators \lstinline|&&|, \lstinline+||+, \lstinline|^^| +and \lstinline|_ ? _ : _| are lazy like in \C: their right members are evaluated +only if required. Thus the amount of undefinedness is limited. Consequently, +predicate \lstinline|p ==> q| is also lazy since it is equivalent +to \lstinline+!p || q+. It is also the case for guarded quantifications since +guards are conjunctions and for ternary condition since it is equivalent to a +disjunction of implications. + +\begin{example}\label{ex:semantics} +Below, the first, second and fourth predicates are invalid while the third +one is valid: +\begin{itemize} +\item \lstinline|\false && 1/0 == 1/0| +\item \lstinline|\forall integer x, -1 <= x <= 1 ==> 1/x > 0| +\item \lstinline|\forall integer x, 0 <= x <= 0 ==> \false ==> -1 <= 1/x <= 1| +\item \lstinline|\exists integer x, 1 <= x <= 0 && -1 <= 1/x <= 1| +\end{itemize} +In particular, the second one is invalid since the quantification is in fact an +enumeration over a finite number of elements, it amounts to +\lstinline|1/-1 > 0 && 1/0 > 0 && 1/1 > 0|. The first atomic proposition is +invalid, so the rest of the conjunction (and in particular 1/0) is not +evaluated. The fourth one is invalid since it is an existential quantification +over an empty range. + +\emph{A contrario} the semantics of predicates below is undefined: +\begin{itemize} +\item \lstinline|1/0 == 1/0 && \false| +\item \lstinline|-1 <= 1/0 <= 1 ==> \true| +\item \lstinline|\exists integer x, -1 <= x <= 1 && 1/x > 0 | +\end{itemize} +\end{example} + +Furthermore, casting a term denoting a \C expression $e$ to a smaller type +$\tau$ is undefined if $e$ is not representable in $\tau$. + +\begin{example} +Below, the first term is well-defined, while the second one is undefined. +\begin{itemize} +\item \lstinline|(char)127| +\item \lstinline|(char)128| +\end{itemize} +\end{example} + +\paragraph{Handling undefinedness in tools} + +It is the responsibility of each tool which interprets \eacsl to ensure that an +undefined term is never evaluated. For instance, they may exit with a proper +error message or, if they generate \C code, they may guard each generated +undefined \C expression in order to be sure that they are always safely used. + +This behavior is consistent with both \acsl~\cite{acsl} and mainstream +specification languages for runtime assertion checking like +\jml~\cite{jml}. Consistency means that, if it exists and is defined, the \eacsl +predicate corresponding to a valid (resp. invalid) \acsl predicate is valid +(resp. invalid). Thus it is possible to reuse tools interpreting \acsl like the +\framac's value analysis plug-in~\cite{value} in order to interpret \eacsl, and +it is also possible to perform runtime assertion checking of \eacsl predicates +in the same way than \jml predicates. Reader interested by the implications +(especially issues) of such a choice may read articles of Patrice +Chalin~\cite{chalin05,chalin07}. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\subsection{Typing}\label{sec:typing} +\except{no user-defined types} + +It is not possible to define logic types introduced by the specification writer +(see Section~\ref{sec:logicspec}). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\subsection{Integer arithmetic and machine integers} +\nodiff + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\subsection{Real numbers and floating point numbers} +\label{sec:reals} +\nodiff + +\difficults{Exact real numbers and even floating point numbers} + +\begin{notimplementedenv} + Real numbers beyond rationals are currently not supported by the \eacsl + plug-in. Only rationals (in $\mathbb{Q}$) and floating point numbers are + supported. +\end{notimplementedenv} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\subsection{C arrays and pointers} +\nodiff + +\difficultwhy{Ensuring validity of memory accesses}{the implementation of a + memory model} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\subsection{Structures, Unions and Arrays in logic} +\nodiff + +\difficults{\notimplemented{Logic arrays} without an explicit length} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\subsection{String literals} +\nodiff + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\section{Function contracts} +\label{sec:fn-behavior} +\index{function contract}\index{contract} + +\except{no \lstinline|terminates| and \lstinline|abrupt| clauses} + +Figure~\ref{fig:gram:contracts} shows grammar of function +contracts. This is a simplified version of \acsl one without +\lstinline|terminates| and \lstinline|abrupt| +clauses. Section~\ref{sec:termination} (resp.~\ref{sec:abrupt}) explains why +\eacsl has no \lstinline|terminates| (resp. \lstinline|abrupt|) clause. + +\begin{figure}[htbp] + \begin{cadre} + \input{fn_behavior_modern.bnf} + \end{cadre} + \caption{Grammar of function contracts} + \label{fig:gram:contracts} +\end{figure} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\subsection{Built-in constructs % + \texorpdfstring{\old}{\textbackslash{}old} % + and \texorpdfstring{\result}{\textbackslash{}result}} +\label{sec:builtinconstructs} + +\nodiff + +Figure~\ref{fig:gram:oldandresult} summarizes grammar extension of terms with +\lstinline|\old| and \lstinline|\result|. +\begin{figure}[htbp] + \begin{cadre} + \input{oldandresult_modern.bnf} + \end{cadre} + \caption{\protect\old and \protect\result in terms} + \label{fig:gram:oldandresult} +\end{figure} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\subsection{Simple function contracts} +\label{sec:simplecontracts} + +\nodiff + +\difficultwhy{\notimplemented{\lstinline|\\assigns|}}{the implementation of a + memory model} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\subsection{Contracts with named behaviors} +\label{subsec:behaviors} +\index{function behavior}\index{behavior} + +\nodiff + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\subsection{Memory locations and sets of terms} +\label{sec:locations} + +\except{ranges and \notimplemented{set comprehensions} are limited in order to + be finite} + +Figure~\ref{fig:gram:locations} describes grammar of sets of terms. The only +differences with \acsl are that both lower and upper bounds of ranges are +mandatory and that the predicate inside set comprehension must be guarded and +bind only one variable. In that way, each set of terms is finite and their +members easily identifiable. +\begin{figure}[htbp] + \fbox{\begin{minipage}{0.97\textwidth} + \input{loc_modern.bnf} + \end{minipage}} + \caption{Grammar for sets of terms} +\label{fig:gram:locations} +\end{figure} + +\begin{notimplementedenv} +\begin{example}\label{ex:tset} +The set \lstinlineµ{ x | integer x; 0 <= x <= 9 || 20 <= x <= 29 }µ denotes the +set of all integers between 0 and 9 and between 20 and 29. +\end{example} +\end{notimplementedenv} + +\begin{notimplementedenv} + Ranges are currently only supported in memory built-ins described in + Section~\ref{subsec:memory} and~\ref{sec:dangling}. + +\begin{example} +The predicate \lstinline|\valid(&t[0 .. 9])| is supported and denotes that +the ten first cells of the array \lstinline|t| are valid. Writing the term +\lstinline|&t[0 .. 9]| alone, outside any memory built-in, is not yet supported. +\end{example} +\end{notimplementedenv} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\subsection{Default contracts, multiple contracts} +\nodiff + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\section{Statement annotations} +\index{annotation} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\subsection{Assertions} +\label{sec:assertions} +\indextt{assert} +\nodiff + +Figure~\ref{fig:gram:assertions} summarizes grammar for assertions. +\begin{figure}[htbp] + \begin{cadre} + \input{assertions_modern.bnf} + \end{cadre} + \caption{Grammar for assertions} + \label{fig:gram:assertions} +\end{figure} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\subsection{Loop annotations} +\label{sec:loop_annot} + +\except{loop invariants lose their inductive nature} + +Figure~\ref{fig:gram:loops} shows grammar for loop annotations. There is no +syntactic difference with \acsl. +\begin{figure}[htbp] + \begin{cadre} + \input{loops_modern.bnf} + \end{cadre} + \caption{Grammar for loop annotations} + \label{fig:gram:loops} +\end{figure} + +\difficultwhy{\notimplemented{\lstinline|loop assigns|}}{the implementation of a + memory model} + +\subsubsection{Loop invariants} + +\index{invariant} The semantics of loop invariants is the same than the one +defined in \acsl, except that they are not inductive. More precisely, if one +does not take care of side effects (semantics of specifications about side +effects in loop is the same in \eacsl than the one in \acsl), a loop invariant +$I$ is valid in \acsl if and only if: +\begin{itemize} +\item $I$ holds before entering the loop; and +\item if $I$ is assumed true in some state where the loop condition $c$ is also + true, and if execution of the loop body in that state ends normally at the end + of the body or with a "continue" statement, $I$ is true in the resulting + state. +\end{itemize} + +In \eacsl, the same loop invariant $I$ is valid if and only if: +\begin{itemize} +\item $I$ holds before entering the loop; and +\item if execution of the loop body in that state ends normally at the end of + the body or with a "continue" statement, $I$ is true in the resulting state. +\end{itemize} + +Thus the only difference with \acsl is that \eacsl does not assume that the +invariant previously holds when one checks that it holds at the end of the loop +body. In other words a loop invariant \lstinline|I| is equivalent to put an +assertion \lstinline|I| just before entering the loop and at the very end of the +loop body. + +\begin{example} +In the following, \lstinline|bsearch(t,n,v)| searches for element \lstinline|v| +in array \lstinline|t| between indices \lstinline|0| and \lstinline|n-1|. + +\cinput{bsearch.c} + +In \eacsl, this annotated function is equivalent to the following one since +loop invariants are not inductive. + +\cinput{bsearch2.c} + +\end{example} + +\subsubsection{General inductive invariant} + +Syntax of these kinds of invariant is shown Figure~\ref{fig:advancedinvariants} +\begin{figure}[t] + \begin{cadre} + \input{generalinvariants_modern.bnf} + \end{cadre} + \caption{Grammar for general inductive invariants} + \label{fig:advancedinvariants} +\end{figure} + +In \eacsl, these kinds of invariants put everywhere in a loop body is exactly +equivalent to an assertion. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\subsection{Built-in construct \texorpdfstring{\at}{\textbackslash{}at}} +\label{sec:at}\indexttbs{at} + +\except{no forward references} + +The construct \verb|\at(t,id)| (where \verb|id| is a regular C label, a label +added within a ghost statement or a default logic label) +follows the same rule than its \acsl counterpart, except that a more restrictive +scoping rule must be respected in addition to the standard \acsl scoping rule: +when evaluating \verb|\at(t,id)| at a propram point $p$, the program point $p'$ +denoted by \verb|id| must be executed after $p$ the program execution flow. + +\begin{example} +In the following example, both assertions are accepted and valid in \acsl, but +only the first one is accepted and valid in \eacsl since evaluating the term +\verb|\at(*(p+\at(*q,Here)),L1)| at \verb|L2| requires to evaluate the term + \verb|\at(*q,Here)| at \verb|L1|: that is forbidden since \verb|L1| is executed + before \verb|L2|. +\cinput{at.c} + +\end{example} + +For the time being, \verb|\at| can be applied to any term or predicate that uses +quantified variables, let-binded variables and C variables. + +\begin{example} +The \verb|\at| construct of the following example is supported. +\cinput{at_on-purely-logic-variables.c} + +\end{example} + + +\begin{notimplementedenv} +However, quantified variables that use C variables in their bounds and +let-binded variables that use C variables in their definition +are not yet supported. + +\begin{example} +The \verb|\at| construct of the following example is \emph{not yet} supported +since the quantified variable \verb|i| uses the C variable \verb|n| in the +definition of its upper bound. +\cinput{at_on-purely-logic-variables_not-yet.c} + +\end{example} +\end{notimplementedenv} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\subsection{Statement contracts} +\label{sec:statement_contract} +\index{statement contract}\index{contract} + +\except{no \lstinline|abrupt| clauses} + +Figure~\ref{fig:gram:contracts} shows grammar of statement contracts. Like +function contracts, this is a simplified version of \acsl with no +\lstinline|abrupt| clauses. All other constructs are unchanged. + +\begin{figure}[htbp] + \begin{cadre} + \input{st_contracts_modern.bnf} + \end{cadre} + \caption{Grammar for statement contracts} + \label{fig:gram:stcontracts} +\end{figure} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\section{Termination} +\label{sec:termination} +\index{termination} + +\except{no \lstinline|terminates| clauses} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\subsection{\notimplemented{Integer measures}} +\label{sec:integermeasures} +\indexttbs{decreases}\indexttbs{variant} +\nodiff + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\subsection{\notimplemented{General measures}} +\label{sec:generalmeasures} +\nodiff + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\subsection{\notimplemented{Recursive function calls}} +\nodiff + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\subsection{Non-terminating functions} +\absentexperimental + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\section{Logic specifications} +\label{sec:logicspec} +\index{logic specification}\index{specification} + +\limited{stable and computable features} + +Figure~\ref{fig:gram:logic} presents grammar of logic definitions. This is the +same than the one of \acsl without polymorphic definitions, lemmas, nor +axiomatics. + +\begin{figure}[htbp] + \fbox{\begin{minipage}{0.97\linewidth}\vfill \input{logic_modern.bnf} + \vfill\end{minipage}} + \caption{Grammar for global logic definitions} +\label{fig:gram:logic} +\end{figure} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\subsection{Predicate and function definitions} +\nodiff + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\subsection{Lemmas} +\absentwhy{lemmas are user-given propositions. They are written usually to help + theorem provers to establish validity of specifications. Thus they are mostly + useful for verification activities based on deductive methods which are out of + the scope of \eacsl. Furthermore, they often requires human help to be proven, + although \eacsl targets are automatic tools} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\subsection{Inductive predicates}\label{sec:inductive} +\absentwhy{inductive predicates are not computable if they really use their + inductive nature} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\subsection{Axiomatic definitions} +\absentwhy{by nature, an axiomatic is not computable} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\subsection{Polymorphic logic types} +\absentexperimental + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\subsection{Recursive logic definitions} +\index{recursion} +\nodiff + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\subsection{Higher-order logic constructions} +\absentexperimental + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\subsection{Concrete logic types}\label{sec:concrete-logic-types} +\absentexperimental + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\subsection{\notimplemented{Hybrid functions and predicates}} +\label{sec:logicalstates} +\index{hybrid!function} +\index{hybrid!predicate} +\nodiff + +\difficultswhy{\notimplemented{Hybrid functions and predicates}}{the + implementation of a memory model (or at least to support \lstinline|\\at|)} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\subsection{Memory footprint specification: \texorpdfstring{\lstinline|reads|}{reads} clause} +\absentexperimental + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\subsection{\notimplemented{Specification Modules}} +\label{sec:specmodules} +\nodiff + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\section{Pointers and physical adressing} +\label{sec:pointers} + +\except{separation} + +Figure~\ref{fig:gram:memory} shows the additional constructs for terms and +predicates which are related to memory location. +\begin{figure}[htbp] + \fbox{\begin{minipage}{0.97\linewidth} + \input{memory_modern.bnf} + \end{minipage}} + \caption{Grammar extension of terms and predicates about memory} +\label{fig:gram:memory} +\end{figure} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\subsection{Memory blocks and pointer dereferencing} +\label{subsec:memory} +\label{sec:memory} % for correctness of \changeinsection in Changes +\nodiff + +\difficultswhy{\lstinline|\\base\_addr|, + \lstinline|\\block\_length|, \lstinline|\\valid|, + \lstinline|\\valid_read| and + \lstinline|\\offset|}{the implementation of a memory model} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\subsection{Separation}\label{sec:separation} +\nodiff + +\difficultswhy{\notimplemented{\lstinline|\\separated|}}{the implementation of a + memory model} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\subsection{Allocation and deallocation} +\difficultswhy{All these constructs}{the implementation of a memory model} +\label{sec:alloc-dealloc} + +\mywarning{this section is still almost experimental in \acsl. Thus it might still +evolve in the future.} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\section{Sets and lists} +\index{location} + +\subsection{Finite sets} +\nodiff + +\subsection{Finite lists} +\nodiff + +Figure~\ref{fig:gram:list} shows the notations for built-in lists. +\begin{figure}[t] + \begin{cadre} + \input{list-gram.bnf} + \end{cadre} + \caption{Notations for built-in list datatype} +\label{fig:gram:list} +\end{figure} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\section{Abrupt termination}\label{sec:abrupt} +\absentexperimental + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\section{Dependencies information} +\absentexperimental + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\section{\notimplemented{Data invariants}} +\label{sec:invariants} +\index{data invariant}\index{global invariant}\index{type invariant} +\index{invariant!data}\index{invariant!global}\index{invariant!type} + +\nodiff + +Figure~\ref{fig:gram:datainvariants} summarizes grammar for declarations of data +invariants. +\begin{figure}[htbp] + \fbox{\begin{minipage}{0.97\linewidth} + \input{data_invariants_modern.bnf} + \end{minipage}} + \caption{Grammar for declarations of data invariants} +\label{fig:gram:datainvariants} +\end{figure} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\subsection{Semantics} +\nodiff + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\subsection{\notimplemented{Model variables and model fields}} +\label{sec:model} +\index{model} + +\nodiff + +Figure~\ref{fig:gram:model} summarizes grammar for declarations of model +variables and fields. +\begin{figure}[htbp] + \fbox{\begin{minipage}{0.97\linewidth} + \input{model_modern.bnf} + \end{minipage}} + \caption{Grammar for declarations of model variables and fields} +\label{fig:gram:model} +\end{figure} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\section{Ghost variables and statements} +\label{sec:ghost} +\index{ghost} + +\except{no specific construct for volatile variables} + +Figure~\ref{fig:gram:ghost} summarizes grammar for ghost statements which is the +same than the one of \acsl. +\begin{figure}[htbp] + \fbox{\begin{minipage}{0.98\linewidth} + \input{ghost_modern.bnf} + \end{minipage}} + \caption{Grammar for ghost statements} +\label{fig:gram:ghost} +\end{figure} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\subsection{Volatile variables} +\absentexperimental + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\section{Undefined values, dangling pointers} +\label{sec:dangling} +\nodiff + +\difficultswhy{\lstinline|\\initialized| and + \notimplemented{\lstinline|\\dangling|}}{the implementation of a memory + model} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\section{Well-typed pointers} +\label{sec:typedpointers} +\absentexperimental diff --git a/src/plugins/e-acsl/doc/refman/st_contracts.tex b/src/plugins/e-acsl/doc/refman/st_contracts.tex new file mode 100644 index 0000000000000000000000000000000000000000..498e9a73899ed7fd58fe49dfa210018d10d93964 --- /dev/null +++ b/src/plugins/e-acsl/doc/refman/st_contracts.tex @@ -0,0 +1,12 @@ +\begin{syntax} + statement ::= "/*@" statement-contract "*/" statement + \ + [ statement-contract ] ::= {("for" id ("," id)* ":")?} requires-clause* ; + simple-clause* named-behavior-stmt* ; + completeness-clause* + \ + named-behavior-stmt ::= "behavior" id ":" behavior-body-stmt + \ + behavior-body-stmt ::= assumes-clause* ; + requires-clause* simple-clause-stmt* +\end{syntax} diff --git a/src/plugins/e-acsl/doc/refman/term.tex b/src/plugins/e-acsl/doc/refman/term.tex new file mode 100644 index 0000000000000000000000000000000000000000..6af096790d609911bff64586e68fff1e7e26180b --- /dev/null +++ b/src/plugins/e-acsl/doc/refman/term.tex @@ -0,0 +1,37 @@ +\begin{syntax} + literal ::= { "\true" } | { "\false" } ; boolean constants + | integer ; integer constants + | real ; real constants + | string ; string constants + | character ; character constants + \ + bin-op ::= "+" | "-" | "*" | [ "/" ] | [ "%" ] | { "<<" } | { ">>" }; + | "==" | "!=" | "<=" | ">=" | ">" | "<" ; + | [ "&&" ] | [ "||" ] | [ "^^" ] ; boolean operations + | { "&" } | { "|" } | { "-->" } | { "<-->" } | "^" ; bitwise operations + \ + unary-op ::= "+" | "-" ; unary plus and minus + | "!" ; boolean negation + | "~" ; bitwise complementation + | [ "*" ]; pointer dereferencing + | "&" ; address-of operator + \ + term ::= literal ; literal constants + | id ; variables + | unary-op term ; + | term bin-op term ; + | term "[" term "]" ; array access + | { "{" term "\with" "[" term "]" "=" term "}" } ; array functional modifier + | term "." id ; structure field access + | { "{" term "\with" "."id "=" term "}" } ; field functional modifier + | term "->" id ; + | [ "(" type-expr ")" term ] ; cast + | { id "(" term ("," term)* ")" } ; function application + | "(" term ")" ; parentheses + | [ term "?" term ":" term ] ; ternary condition + | "\let" id "=" term ";" term ; local binding + | "sizeof" "(" term ")" ; + | "sizeof" "(" C-type-name ")" ; + | id ":" term ; syntactic naming + | string ":" term ; syntactic naming +\end{syntax} diff --git a/src/plugins/e-acsl/doc/refman/transf.mll b/src/plugins/e-acsl/doc/refman/transf.mll new file mode 100644 index 0000000000000000000000000000000000000000..c56692b20e37edb33519844e84a1a84d6c96675a --- /dev/null +++ b/src/plugins/e-acsl/doc/refman/transf.mll @@ -0,0 +1,169 @@ +(* $Id: transf.mll,v 1.11 2009-03-03 09:53:08 uid562 Exp $ *) + +{ open Lexing;; + let idx = Buffer.create 5 + let full_kw = Buffer.create 5 + + let modern = ref false + + let escape_keyword s = + let buf = Buffer.create 5 in + String.iter + (function + c when ('A' <= c && c <= 'Z') || + ('a' <= c && c <= 'z') || + ('0' <= c && c <= '9') + -> Buffer.add_char buf c + | c -> Buffer.add_string buf + (Printf.sprintf "\\char%d" (int_of_char c))) s; + Buffer.contents buf + + let make_keyword () = + let keyword = Buffer.contents full_kw in + let index = Buffer.contents idx in + print_string "\\addspace"; + if !modern then + Printf.printf + "\\lstinline$%s$" keyword + else + Printf.printf "\\texttt{%s}" (escape_keyword keyword); + if index <> "" then + Printf.printf "\\indextt%s{%s}" + (if keyword.[0] = '\\' then "bs" else "") index; + print_string "\\spacetrue"; + Buffer.clear idx; + Buffer.clear full_kw +} + +rule main = parse + "\\begin{syntax}" { + print_string "\\begin{syntax}"; + syntax lexbuf } + | "\\@" { + print_string "@"; + main lexbuf } + | _ { + print_char (lexeme_char lexbuf 0); main lexbuf } + | eof { + () } + +and syntax = parse + "\\end{syntax}" { + print_string "\\end{syntax}"; + main lexbuf } + | ";" ([^ '\n']* as s) '\n' [' ''\t']* '|' { + print_string "& \\textrm{"; + print_string s; + print_string "} \\alt{}"; + syntax lexbuf } + | ";" ([^ '\n']* as s) '\n' [' ''\t']* '\\' [' ''\t']* '\n' { + print_string "& \\textrm{"; + print_string s; + print_string "} \\sep{}"; + syntax lexbuf } + | ";" ([^ '\n']* as s) '\n' { + print_string "& \\textrm{"; + print_string s; + print_string "} \\newl{}"; + syntax lexbuf } + | "@" { + print_string "}"; + main lexbuf } + | '\'' { + Buffer.clear idx; + Buffer.clear full_kw; + inquote lexbuf } + | '"' { + Buffer.clear idx; + Buffer.clear full_kw; + indoublequote lexbuf } + | "below" { print_string "\\below"; syntax lexbuf } + | "epsilon" { print_string "\\emptystring"; syntax lexbuf } + | ['A'-'Z''a'-'z''-'] + { + print_string "\\nonterm{"; + print_string (lexeme lexbuf); + print_string"}"; + check_nonterm_note lexbuf } + | '\\' ['a'-'z''A'-'Z'] + { + print_string (lexeme lexbuf); + syntax lexbuf } + | ['_' '^'] _ { + print_string (lexeme lexbuf); + syntax lexbuf } + | "*" { print_string "\\repetstar{}"; syntax lexbuf } + | "+" { print_string "\\repetplus{}"; syntax lexbuf } + | "?" { print_string "\\repetone{}"; syntax lexbuf } + | "(" { print_string "\\lparen{}"; syntax lexbuf } + | ")" { print_string "\\rparen{}"; syntax lexbuf } + | "::=" { print_string "\\is{}"; syntax lexbuf } + | "|" { print_string "\\orelse{}"; syntax lexbuf } + | "\\" { print_string "\\sep{}"; syntax lexbuf } + | "{" { print_string "\\begin{notimplementedenv}"; check_implementation_note lexbuf } + | "}" { print_string "\\end{notimplementedenv}"; syntax lexbuf } + | "[" { print_string "\\begin{markdiffenv}"; syntax lexbuf } + | "]" { print_string "\\end{markdiffenv}"; syntax lexbuf } + | _ { + print_char (lexeme_char lexbuf 0); + syntax lexbuf } + +and inquote = parse + ['A'-'Z' 'a'-'z' '0'-'9' '?'] as c { + Buffer.add_char full_kw c; + Buffer.add_char idx c; + inquote lexbuf } + | '\'' { + make_keyword (); + syntax lexbuf } + | '_' { + Buffer.add_char full_kw '_'; + Buffer.add_string idx "\\_"; + inquote lexbuf + } + | _ as c { + Buffer.add_char full_kw c; + inquote lexbuf } + +and indoublequote = parse + ['A'-'Z' 'a'-'z' '0'-'9' '?'] as c { + Buffer.add_char full_kw c; + Buffer.add_char idx c; + indoublequote lexbuf } + | '"' { + make_keyword(); + syntax lexbuf } + | '_' { + Buffer.add_char full_kw '_'; + Buffer.add_string idx "\\_"; + indoublequote lexbuf + } + | _ as c { + Buffer.add_char full_kw c; + indoublequote lexbuf } +and check_implementation_note = parse + | "[" { print_string "["; implementation_note lexbuf } + | "" { syntax lexbuf } +and implementation_note = parse + "]" { print_string "]"; syntax lexbuf } + | _ { print_char (lexeme_char lexbuf 0); + implementation_note lexbuf } +and check_nonterm_note = parse + | "[" { print_string "{"; nonterm_note lexbuf } + | "" { print_string "{}"; syntax lexbuf } +and nonterm_note = parse + "]" { print_string "}"; syntax lexbuf } + | _ { print_char (lexeme_char lexbuf 0); + nonterm_note lexbuf } + +{ + + let () = Arg.parse + [ "-modern", Arg.Set modern, "set modern style"; ] + (fun f -> + let cin = open_in f in + let lb = from_channel cin in + main lb; + close_in cin) + "transf [-modern] file"; + exit 0 + +} diff --git a/src/plugins/e-acsl/doc/refman/transfmain.ml b/src/plugins/e-acsl/doc/refman/transfmain.ml new file mode 100644 index 0000000000000000000000000000000000000000..aa3bf1f0e3f0b57f4da9b3729c9f2b8c84552d39 --- /dev/null +++ b/src/plugins/e-acsl/doc/refman/transfmain.ml @@ -0,0 +1,8 @@ +(* $Id: transfmain.ml,v 1.1 2007-05-29 08:23:19 uid562 Exp $ *) + +let main() = + let lexbuf = Lexing.from_channel stdin in + print_string "% automatically generated DO NOT EDIT\n"; + Transf.main lexbuf; flush stdout; exit 0;; + +Printexc.print main ();; diff --git a/src/plugins/e-acsl/doc/support/MakeLaTeXModern b/src/plugins/e-acsl/doc/support/MakeLaTeXModern new file mode 100644 index 0000000000000000000000000000000000000000..d1b204a14b1ea83265f8686f43d31cfa3f116629 --- /dev/null +++ b/src/plugins/e-acsl/doc/support/MakeLaTeXModern @@ -0,0 +1,25 @@ +FRAMAC_MODERN=frama-c-book.cls frama-c-cover.pdf frama-c-left.pdf frama-c-right.pdf + +frama-c-book.cls: ../frama-c-book.cls + @rm -f $@ + @cp $< . + @chmod a-w $@ + @echo "import $<" + +frama-c-cover.pdf: ../frama-c-cover.pdf + @rm -f $@ + @cp $< . + @chmod a-w $@ + @echo "import $<" + +frama-c-right.pdf: ../frama-c-right.pdf + @rm -f $@ + @cp $< . + @chmod a-w $@ + @echo "import $<" + +frama-c-left.pdf: ../frama-c-left.pdf + @rm -f $@ + @cp $< . + @chmod a-w $@ + @echo "import $<" diff --git a/src/plugins/e-acsl/doc/userman/.gitignore b/src/plugins/e-acsl/doc/userman/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..f0de8a3d55fd37efe5d3b79a83031b8ab3c1a1e3 --- /dev/null +++ b/src/plugins/e-acsl/doc/userman/.gitignore @@ -0,0 +1 @@ +main.pdf diff --git a/src/plugins/e-acsl/doc/userman/Makefile b/src/plugins/e-acsl/doc/userman/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..c881022e84f8d3f6fd6e8680fcdbd9709117b20d --- /dev/null +++ b/src/plugins/e-acsl/doc/userman/Makefile @@ -0,0 +1,97 @@ +MAIN=main + +C_CODE=$(wildcard examples/*.[ci]) +VERSION_FILE=../../../../../VERSION +ifeq ("$(wildcard $(VERSION_FILE))", "") +VERSION_FILE=../../VERSION +FC_VERSION= 18.0 +else +#internal mode +FC_VERSION=$(shell cat $(VERSION_FILE)) +endif +EACSL_VERSION= $(shell cat $(VERSION_FILE)) + +DEPS_MODERN=eacslversion.tex biblio.bib macros.tex \ + introduction.tex \ + provides.tex \ + limitations.tex \ + changes.tex \ + $(C_CODE) \ + $(VERSION_FILE) + +default: main.pdf + +main.pdf: $(DEPS_MODERN) + +EACSL_DIR=../.. +DISTRIB_DIR=$(HOME)/frama-c/doc/www/distrib +install: + mkdir -p $(EACSL_DIR)/doc/manuals/ + cp -f main.pdf $(EACSL_DIR)/doc/manuals/e-acsl-manual.pdf +# cp -f main.pdf \ + $(DISTRIB_DIR)/download/e-acsl/e-acsl-manual-$(EACSL_VERSION).pdf + +include $(EACSL_DIR)/doc/support/MakeLaTeXModern + +eacslversion.tex: Makefile + rm -f $@ + printf '\\newcommand{\\eacslversion}{$(EACSL_VERSION)\\xspace}\n' > $@ + printf '\\newcommand{\\fcversion}{$(FC_VERSION)\\xspace}\n' >> $@ + chmod a-w $@ + +%.1: %.mp + mpost -interaction=batchmode $< + +%.mps: %.1 + mv $< $@ + +%.pp: %.tex pp + ./pp -utf8 $< > $@ + +%.pp: %.c pp + ./pp -utf8 -c $< > $@ + +%.tex: %.ctex pp + rm -f $@ + ./pp $< > $@ + chmod a-w $@ + +%.bnf: %.tex transf + rm -f $@ + ./transf $< > $@ + chmod a-w $@ + +%_modern.bnf: %.tex transf + rm -f $@ + ./transf -modern $< > $@ + chmod a-w $@ + +%.ml: %.mll + ocamllex $< + +%.pdf: %.tex + pdflatex $* + makeindex $* + bibtex $* + pdflatex $* + pdflatex $* + +%.cmo: %.ml + ocamlc -c $< + +pp: pp.ml + ocamlopt -o $@ str.cmxa $^ + +transf: transf.cmo transfmain.cmo + ocamlc -o $@ $^ + +transfmain.cmo: transf.cmo + +.PHONY: clean + +clean: + rm -rf *~ *.aux *.log *.nav *.out *.snm *.toc *.lof *.pp *.bnf \ + *.haux *.hbbl *.htoc \ + *.cb* *.cm? *.bbl *.blg *.idx *.ind *.ilg \ + transf trans.ml pp.ml pp + rm -f eacslversion.tex diff --git a/src/plugins/e-acsl/doc/userman/biblio.bib b/src/plugins/e-acsl/doc/userman/biblio.bib new file mode 100644 index 0000000000000000000000000000000000000000..27d9be4791f802dbe9eebcb8cd3ed69c8cbe2139 --- /dev/null +++ b/src/plugins/e-acsl/doc/userman/biblio.bib @@ -0,0 +1,174 @@ +@manual{userman, + title = {Frama-C User Manual}, + author = {Loïc Correnson and Pascal Cuoq and Florent Kirchner and + André Maroneze and Virgile Prevosto and + Armand Puccetti and Julien Signoles and + Boris Yakobowski}, + note = {\url{http://frama-c.cea.fr/download/user-manual.pdf}} +} + +@manual{plugin-dev-guide, + author = {Julien Signoles and Loïc Correnson and Matthieu Lemerre and + Virgile Prevosto}, + title = {{Frama-C Plug-in Development Guide}}, + note = {\newline \url{http://frama-c.cea.fr/download/plugin-developer.pdf}}, +} + +@manual{eva, + author = {David B\"uhler and Pascal Cuoq and Boris Yakobowski and + Matthieu Lemerre and André Maroneze and Valentin Perelle and + Virgile Prevosto}, + title = {{EVA} -- The Evolved Value Analysis plug-in}, + note = {\mbox{\url{http://frama-c.cea.fr/download/value-analysis.pdf}}}, +} + +@manual{acsl, + author = {Baudin, Patrick and Filli\^{a}tre, Jean-Christophe and + March\'{e}, Claude and Monate, Benjamin and Moy, Yannick and + Prevosto, Virgile}, + title = {{ACSL: ANSI/ISO C Specification Language.}}, +} + +@manual{acsl-implem, + author = {Baudin, Patrick and Pascal Cuoq and Filli\^{a}tre, Jean-Christophe + and March\'{e}, Claude and Monate, Benjamin and Moy, Yannick and + Prevosto, Virgile}, + title = {ACSL: ANSI/ISO C Specification Language. --- + Frama-C Silicon implementation.}, +} + +@manual{eacsl, + author = {Julien Signoles}, + title = {E-ACSL: Executable ANSI/ISO C Specification Language.}, + note = {\mbox{\url{http://frama-c.com/download/e-acsl/e-acsl.pdf}}} +} + +@manual{eacsl-implem, + author = {Julien Signoles}, + title = {E-ACSL. Implementation in Frama-C Plug-in E-ACSL}, + note = {\mbox{\url{http://frama-c.com/download/e-acsl/e-acsl-implementation.pdf}}} +} + +@habilitation{signoles18hdr, + author = {Signoles, Julien}, + title = {{From Static Analysis to Runtime Verification with Frama-C and E-ACSL}}, + year = 2018, + month = jul, + school = {Universit\'e Paris-Sud, Orsay, France}, + note = {Habilitation Thesis}, + url = {publis/hdr.pdf} +} + +@inproceedings{rvcubes17tool, + author = {Julien Signoles and Nikolai Kosmatov and Kostyantyn Vorobyov}, + title = {{E-ACSL, a Runtime Verification Tool for Safety and Security of C +Programs. Tool Paper}}, + booktitle = {International Workshop on Competitions, Usability, Benchmarks, +Evaluation, and Standardisation for Runtime Verification Tools (RV-CuBES)}, + year = 2017, + month = sep, +} + +@inproceedings{sac13, + author = {Micka\"{e}l Delahaye and Nikolai Kosmatov and Julien Signoles}, + title = {Common Specification Language for Static and Dynamic Analysis of + {C} Programs}, + booktitle = {the 28th Annual ACM Symposium on Applied Computing ({SAC})}, + publisher = {ACM}, + year = 2013, + month = mar, + pages = {1230--1235}, +} + + +@inproceedings{rv13tutorial, + author = {Nikolaï Kosmatov and Julien Signoles}, + title = {A Lesson on Runtime Assertion Checking with {Frama-C}}, + booktitle = {International Conference on Runtime Verification ({RV 2013})}, + publisher = {Springer}, + series= {LNCS}, + volume= {8174}, + pages= {386--399}, + year = 2013, + month = sep, +} + +@manual{wp, + author = {Patrick Baudin and François Bobot and Loïc Correnson + and Zaynah Dargaye}, + title = {{Frama-C}'s {WP} plug-in}, + note = {\mbox{\url{http://frama-c.com/download/frama-c-wp-manual.pdf}}}, +} + +@manual{rte, + author = {Philippe Herrmann and Julien Signoles}, + title = {Annotation Generation: {Frama-C}'s {RTE} plug-in}, + note = {\mbox{\url{http://frama-c.com/download/frama-c-rte-manual.pdf}}}, +} + +@article{fac15, +year={2015}, +month={jan}, +journal={Formal Aspects of Computing}, +title={{Frama-C: A Software Analysis Perspective}}, +publisher={Springer}, +keywords={Formal verification; Static analysis; Dynamic analysis; C}, +author={Kirchner, Florent and Kosmatov, Nikolai and Prevosto, Virgile and +Signoles, Julien and Yakobowski, Boris}, +pages={1-37}, +} + +@article{runtime-assertion-checking, + author = {Lori A. Clarke and + David S. Rosenblum}, + title = {A historical perspective on runtime assertion checking in + software development}, + journal = {ACM SIGSOFT Software Engineering Notes}, + volume = {31}, + number = {3}, + year = {2006}, + pages = {25-37}, +} + +@inproceedings{rv13, + author = {Nikolaï Kosmatov and Guillaume Petiot and Julien Signoles}, + title = {An Optimized Memory Monitoring for Runtime Assertion Checking of + {C} Programs}, + booktitle = {International Conference on + Runtime Verification ({RV 2013})}, + publisher = {Springer}, + series = {LNCS}, + volume = {8174}, + pages = {167--182}, + year = 2013, + month = sep, +} + +@inproceedings{jfla15, + title = {{Rester statique pour devenir plus rapide, plus pr{\'e}cis et plus mince}}, + author = {Arvid Jakobsson and Nikolai Kosmatov and Julien Signoles}, + booktitle = {Journées Francophones des Langages Applicatifs (JFLA'15)}, + editor = {David Baelde and Jade Alglave}, + year = {2015}, + month = jan, + note = {In French}, +} + +@article{scp16, + title = {{Fast as a Shadow, Expressive as a Tree: Optimized Memory Monitoring +for C}}, + author = {Arvid Jakobsson and Nikolai Kosmatov and Julien Signoles}, + journal = {Science of Computer Programming}, + publisher = {Elsevier}, + pages = {226-246}, + language = {English}, + year = {2016}, + month = oct, +} + +@article{pldi16, + title = {{Shadow State Encoding for Efficient Monitoring of Block-level +Properties}}, + author = {Kostyantyn Vorobyov and Julien Signoles and Nikolai Kosmatov}, + note = {Submitted for publication}, +} diff --git a/src/plugins/e-acsl/doc/userman/cealistlogo.jpg b/src/plugins/e-acsl/doc/userman/cealistlogo.jpg new file mode 100644 index 0000000000000000000000000000000000000000..966be5a8ff6d50d9a7f50759633ca144c4c5db1c Binary files /dev/null and b/src/plugins/e-acsl/doc/userman/cealistlogo.jpg differ diff --git a/src/plugins/e-acsl/doc/userman/changes.tex b/src/plugins/e-acsl/doc/userman/changes.tex new file mode 100644 index 0000000000000000000000000000000000000000..fa7302da6bce495757ee4a33b15bf2c95c9974d8 --- /dev/null +++ b/src/plugins/e-acsl/doc/userman/changes.tex @@ -0,0 +1,93 @@ +\chapter{Changes}\label{chap:changes} + +This chapter summarizes the changes in this documentation between each \eacsl +release. First we list changes of the last release. + +\section*{E-ACSL \eacslversion} + +\begin{itemize} +\item \textbf{Runtime Monitor Behavior}: Document global variable + \texttt{\_\_e\_acsl\_sound\_verdict} usable in \texttt{\_\_e\_acsl\_assert}. +\item New section \textbf{Partial Instrumentation}. +\item New section \textbf{Providing a White List of Functions}. +\end{itemize} + +\section*{E-ACSL 18.0 Argon} + +\begin{itemize} +\item \textbf{Introduction}: Improve a bit and reference new related papers. +\item \textbf{What the Plug-in Provides}: Highlight that the memory analysis is + not yet robust. +\item \textbf{What the Plug-in Provides}: Highlight the importance of + \textbf{-e-acsl-prepare}. +\item \textbf{Known Limitations}: Replace section ``Limitations of E-ACSL + Monitoring Libraries'' by the new section ``Supported Systems''. +\item \textbf{Known Limitations}: Add limitation about monitoring of variables + with incomplete types. +\end{itemize} + +\section*{E-ACSL Chlorine-20180501} + +\begin{itemize} +\item New section \textbf{Additional Verifications}. +\item Update every section with respect to the changes introduced since \eacsl + Sulfur-20180101. +\end{itemize} + +\section*{E-ACSL Sulfur-20180101} + +\begin{itemize} +\item no changes +\end{itemize} + +\section*{E-ACSL Phosphorus-20170501} + +\begin{itemize} +\item Removed chapter \textbf{Easy Instrumentation with E-ACSL}. +\item \textbf{What the Plug-in Provides}: added section \textbf{E-ACSL Wrapper + Script}. +\item \textbf{What the Plug-in Provides}: added description of \eacsl runtime + libraries. +\item \textbf{Known Limitations}: added section \textbf{Requirements to Input + Programs}. +\item \textbf{Known Limitations}: added section \textbf{Limitations of E-ACSL Monitoring Libraries}. +\item \textbf{Recursive Functions}: remove limitation about possible uses before + being declared. +\item \textbf{Variadic Functions}: mention the \variadic plug-in. +\end{itemize} + +\section*{E-ACSL 0.6} + +\begin{itemize} +\item \textbf{Easy Instrumentation with E-ACSL}: new chapter. +\end{itemize} + +\section*{E-ACSL 0.5} + +\begin{itemize} +\item \textbf{Libc}: new section. +\item \textbf{Architecture Dependent Annotations}: add a remark about \gcc's + machdep. +\item Use \texttt{-then-last} whenever possible. +\item Update output wrt \framac Sodium changes. +\item \textbf{Bibliography:} fix incorrect links. +\end{itemize} + +\section*{E-ACSL 0.4} + +\begin{itemize} +\item No change. +\end{itemize} + +\section*{E-ACSL 0.3} +\begin{itemize} +\item \textbf{Introduction:} reference the \eacsl tutorial. +\item \textbf{Memory-related Annotations:} document the + \lstinline|E_ACSL_MACHDEP| macro. +\end{itemize} + +\section*{E-ACSL 0.2} + +\begin{itemize} +\item First release of this manual. +\end{itemize} diff --git a/src/plugins/e-acsl/doc/userman/examples/archi.c b/src/plugins/e-acsl/doc/userman/examples/archi.c new file mode 100644 index 0000000000000000000000000000000000000000..4d4861bb169af87cf9213b16ec17354f3b4f5a51 --- /dev/null +++ b/src/plugins/e-acsl/doc/userman/examples/archi.c @@ -0,0 +1,12 @@ +#define ARCH_BITS 64 /* assume a 64-bit architecture */ + +#if ARCH_BITS == 32 +#define SIZEOF_LONG 4 +#elif ARCH_BITS == 64 +#define SIZEOF_LONG 8 +#endif + +int main(void) { + /*@ assert sizeof(long) == SIZEOF_LONG; */ + return 0; +} diff --git a/src/plugins/e-acsl/doc/userman/examples/assert_sign.c b/src/plugins/e-acsl/doc/userman/examples/assert_sign.c new file mode 100644 index 0000000000000000000000000000000000000000..ce2e56c6fb9579df15f0211548e355dfcd5af08d --- /dev/null +++ b/src/plugins/e-acsl/doc/userman/examples/assert_sign.c @@ -0,0 +1,2 @@ +void __e_acsl_assert(int pred, char *kind, + char *func_name, char *pred_text, int line); diff --git a/src/plugins/e-acsl/doc/userman/examples/check.i b/src/plugins/e-acsl/doc/userman/examples/check.i new file mode 100644 index 0000000000000000000000000000000000000000..087de43466bf8d1ff86b26014b55550c433a5520 --- /dev/null +++ b/src/plugins/e-acsl/doc/userman/examples/check.i @@ -0,0 +1,6 @@ +int main(void) { + int x = 0; + /*@ assert x == 0; */ + /*@ assert x << 2 == 0; */ + return 0; +} diff --git a/src/plugins/e-acsl/doc/userman/examples/combine.i b/src/plugins/e-acsl/doc/userman/examples/combine.i new file mode 100644 index 0000000000000000000000000000000000000000..8d4288fcd45f5e8b4e4b4d95a681a6399b528ffb --- /dev/null +++ b/src/plugins/e-acsl/doc/userman/examples/combine.i @@ -0,0 +1,6 @@ +int main(void) { + int x = 0xffff; + int y = 0xfff; + int z = x + y; + return 0; +} diff --git a/src/plugins/e-acsl/doc/userman/examples/first.i b/src/plugins/e-acsl/doc/userman/examples/first.i new file mode 100644 index 0000000000000000000000000000000000000000..2d0850e1527d97a550283b54e5f1fed45bfc8568 --- /dev/null +++ b/src/plugins/e-acsl/doc/userman/examples/first.i @@ -0,0 +1,6 @@ +int main(void) { + int x = 0; + /*@ assert x == 0; */ + /*@ assert x == 1; */ + return 0; +} diff --git a/src/plugins/e-acsl/doc/userman/examples/gmp.i b/src/plugins/e-acsl/doc/userman/examples/gmp.i new file mode 100644 index 0000000000000000000000000000000000000000..cb203067964042d4da3656b1ce3362f6051242de --- /dev/null +++ b/src/plugins/e-acsl/doc/userman/examples/gmp.i @@ -0,0 +1,15 @@ +unsigned long long my_pow(unsigned int x, unsigned int n) { + int res = 1; + while (n) { + if (n & 1) res *= x; + n >>= 1; + x *= x; + } + return res; +} + +int main(void) { + unsigned long long x = my_pow(2, 63); + /*@ assert (2 * x + 1) % 2 == 1; */ + return 0; +} diff --git a/src/plugins/e-acsl/doc/userman/examples/instrument.i b/src/plugins/e-acsl/doc/userman/examples/instrument.i new file mode 100644 index 0000000000000000000000000000000000000000..74cf4d32f8f1dee4dac82aebaec6527cb6e6b452 --- /dev/null +++ b/src/plugins/e-acsl/doc/userman/examples/instrument.i @@ -0,0 +1,19 @@ +void f(int *p) { + *p = 0; +} + +void g(int *p) { + *p = 1; +} + +int main(void) { + int t[3]; + f(&t[0]); + /*@ assert \initialized(&t[0]); */ + t[1] = 1; + g(&t[1]); + g(&t[2]); + /*@ assert \initialized(&t[1]); */ + /*@ assert \initialized(&t[2]); */ + return 0; +} diff --git a/src/plugins/e-acsl/doc/userman/examples/instrumented_first.c b/src/plugins/e-acsl/doc/userman/examples/instrumented_first.c new file mode 100644 index 0000000000000000000000000000000000000000..a940f8c891f99d03379b2ab99afd8c0164958126 --- /dev/null +++ b/src/plugins/e-acsl/doc/userman/examples/instrumented_first.c @@ -0,0 +1,54 @@ +\begin{shell} +\$ frama-c -e-acsl first.i -then-last -print +[kernel] Parsing FRAMAC_SHARE/e-acsl/e_acsl_gmp_api.h (with preprocessing) +[kernel] Parsing FRAMAC_SHARE/e-acsl/e_acsl.h (with preprocessing) +[kernel] Parsing first.i (no preprocessing) +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +struct __e_acsl_mpz_struct { + int _mp_alloc ; + int _mp_size ; + unsigned long *_mp_d ; +}; +typedef struct __e_acsl_mpz_struct __e_acsl_mpz_struct; +typedef __e_acsl_mpz_struct ( __attribute__((__FC_BUILTIN__)) __e_acsl_mpz_t)[1]; +/*@ ghost extern int __e_acsl_init; */ + +/*@ requires pred != 0; + assigns \nothing; */ + __attribute__((__FC_BUILTIN__)) void __e_acsl_assert(int pred, char *kind, + char *fct, + char *pred_txt, + int line); + +/*@ assigns \nothing; */ + __attribute__((__FC_BUILTIN__)) void __e_acsl_memory_init(int *argc_ref, + char ***argv, + size_t ptr_size); + +extern size_t __e_acsl_heap_allocation_size; + +/*@ +predicate diffSize{L1, L2}(integer i) = + \at(__e_acsl_heap_allocation_size,L1) - + \at(__e_acsl_heap_allocation_size,L2) == i; + +*/ +int main(void) +{ + int __retres; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)4); + int x = 0; + /*@ assert x == 0; */ + __e_acsl_assert(x == 0,(char *)"Assertion",(char *)"main",(char *)"x == 0", + 3); + /*@ assert x == 1; */ + __e_acsl_assert(x == 1,(char *)"Assertion",(char *)"main",(char *)"x == 1", + 4); + __retres = 0; + return __retres; +} +\end{shell} diff --git a/src/plugins/e-acsl/doc/userman/examples/main.c b/src/plugins/e-acsl/doc/userman/examples/main.c new file mode 100644 index 0000000000000000000000000000000000000000..217e19c45199aa377c8434991332b95b34308886 --- /dev/null +++ b/src/plugins/e-acsl/doc/userman/examples/main.c @@ -0,0 +1,7 @@ +#include "stdio.h" + +int main(void) { + unsigned long long x = my_pow(2, 16); + printf("x = %llu\n",x); + return 0; +} diff --git a/src/plugins/e-acsl/doc/userman/examples/modified_main.c b/src/plugins/e-acsl/doc/userman/examples/modified_main.c new file mode 100644 index 0000000000000000000000000000000000000000..b3ed0376bc42f408594d3c459f094bfe51c5fea9 --- /dev/null +++ b/src/plugins/e-acsl/doc/userman/examples/modified_main.c @@ -0,0 +1,4 @@ +int main(int argc, char **argv) { + f(); + return 0; +} diff --git a/src/plugins/e-acsl/doc/userman/examples/my_assert.c b/src/plugins/e-acsl/doc/userman/examples/my_assert.c new file mode 100644 index 0000000000000000000000000000000000000000..c006779bc5b5b68796681f65c9055cf766483785 --- /dev/null +++ b/src/plugins/e-acsl/doc/userman/examples/my_assert.c @@ -0,0 +1,15 @@ +#include "stdio.h" + +extern int __e_acsl_sound_verdict; + +void __e_acsl_assert(int pred, char *kind, + char *func_name, char *pred_text, int line) { + printf("%s at line %d in function %s is %s (%s).\n\ +The verified predicate was: `%s'.\n", + kind, + line, + func_name, + pred ? "valid" : "invalid", + __e_acsl_sound_verdict ? "trustable" : "UNTRUSTABLE", + pred_text); +} diff --git a/src/plugins/e-acsl/doc/userman/examples/no_code.c b/src/plugins/e-acsl/doc/userman/examples/no_code.c new file mode 100644 index 0000000000000000000000000000000000000000..9b76ff82404876b71143faf373a2a9f980ec24f7 --- /dev/null +++ b/src/plugins/e-acsl/doc/userman/examples/no_code.c @@ -0,0 +1,14 @@ +#include "stdio.h" + +/*@ behavior even: + @ assumes n % 2 == 0; + @ ensures \result >= 1; + @ behavior odd: + @ assumes n % 2 != 0; + @ ensures \result >= 1; */ +extern unsigned long long my_pow(unsigned int x, unsigned int n); + +int main(void) { + unsigned long long x = my_pow(2, 64); + return 0; +} diff --git a/src/plugins/e-acsl/doc/userman/examples/no_main.i b/src/plugins/e-acsl/doc/userman/examples/no_main.i new file mode 100644 index 0000000000000000000000000000000000000000..9047098909a043f63b5ffacfdfcce3e56e1467f2 --- /dev/null +++ b/src/plugins/e-acsl/doc/userman/examples/no_main.i @@ -0,0 +1,17 @@ +/*@ behavior even: + @ assumes n % 2 == 0; + @ ensures \result >= 1; + @ behavior odd: + @ assumes n % 2 != 0; + @ ensures \result >= 1; */ +unsigned long long my_pow(unsigned int x, unsigned int n) { + unsigned long long res = 1; + while (n) { + if (n & 1) res *= x; + n >>= 1; + x *= x; + } + return res; +} + + diff --git a/src/plugins/e-acsl/doc/userman/examples/pointer.c b/src/plugins/e-acsl/doc/userman/examples/pointer.c new file mode 100644 index 0000000000000000000000000000000000000000..43d0fb4b088b7d84e19180568fa876c1327ffda6 --- /dev/null +++ b/src/plugins/e-acsl/doc/userman/examples/pointer.c @@ -0,0 +1,14 @@ +#include <stdlib.h> + +extern void *malloc(size_t); +extern void free(void*); + +int main(void) { + int *x; + x = (int*)malloc(sizeof(int)); + *x = 1; + /*@ assert *x == 1; */ + free(x); + /*@ assert freed: *x == 1; */ + return 0; +} diff --git a/src/plugins/e-acsl/doc/userman/examples/pow.i b/src/plugins/e-acsl/doc/userman/examples/pow.i new file mode 100644 index 0000000000000000000000000000000000000000..3deda0f62135de3c82cc43dace3849e86e8bd8d7 --- /dev/null +++ b/src/plugins/e-acsl/doc/userman/examples/pow.i @@ -0,0 +1,9 @@ +unsigned long long my_pow(unsigned int x, unsigned int n) { + unsigned long long res = 1; + while (n) { + if (n & 1) res *= x; + n >>= 1; + x *= x; + } + return res; +} diff --git a/src/plugins/e-acsl/doc/userman/examples/printf.c b/src/plugins/e-acsl/doc/userman/examples/printf.c new file mode 100644 index 0000000000000000000000000000000000000000..21ca4893ca91d97a9e241efa25dd84c98b48a753 --- /dev/null +++ b/src/plugins/e-acsl/doc/userman/examples/printf.c @@ -0,0 +1,6 @@ +#include <stdio.h> + +int main(void) { + printf("is %d really an int?", "foo"); + return 0; +} diff --git a/src/plugins/e-acsl/doc/userman/examples/rte.i b/src/plugins/e-acsl/doc/userman/examples/rte.i new file mode 100644 index 0000000000000000000000000000000000000000..9fa070ccad279c59032ba229f5c54d8e84fbbb6a --- /dev/null +++ b/src/plugins/e-acsl/doc/userman/examples/rte.i @@ -0,0 +1,14 @@ +/*@ behavior yes: + assumes x % y == 0; + ensures \result == 1; + behavior no: + assumes x % y != 0; + ensures \result == 0; */ +int is_dividable(int x, int y) { + return x % y == 0; +} + +int main(void) { + is_dividable(2, 0); + return 0; +} diff --git a/src/plugins/e-acsl/doc/userman/examples/rte_debug.i b/src/plugins/e-acsl/doc/userman/examples/rte_debug.i new file mode 100644 index 0000000000000000000000000000000000000000..f541f1e8e2af1d09998af1c76b9c662daf889ba8 --- /dev/null +++ b/src/plugins/e-acsl/doc/userman/examples/rte_debug.i @@ -0,0 +1,16 @@ +void foo(int *p) { + /*@assert \valid(p); */ + *p = 1; +} + +void bar(int *p) { + foo(p); +} + +int main(void) { + int i = 0; + int *p = &i; + bar(p+1); + return 0; +} + diff --git a/src/plugins/e-acsl/doc/userman/examples/strcpy.c b/src/plugins/e-acsl/doc/userman/examples/strcpy.c new file mode 100644 index 0000000000000000000000000000000000000000..40e530a2b30d8c37b59e245e29075f8586f32bc1 --- /dev/null +++ b/src/plugins/e-acsl/doc/userman/examples/strcpy.c @@ -0,0 +1,8 @@ +#include <stdlib.h> +#include <string.h> + +int main(void) { + char *dst = malloc(sizeof(char) * 6); + strcpy(dst, "foobar"); + return 0; +} diff --git a/src/plugins/e-acsl/doc/userman/examples/uninitialized.i b/src/plugins/e-acsl/doc/userman/examples/uninitialized.i new file mode 100644 index 0000000000000000000000000000000000000000..ba12ce1eecc229c99d2df95d2cb8a269688b46c6 --- /dev/null +++ b/src/plugins/e-acsl/doc/userman/examples/uninitialized.i @@ -0,0 +1,5 @@ +int main(void) { + int x; + /*@ assert x == 0; */ + return 0; +} diff --git a/src/plugins/e-acsl/doc/userman/examples/valid.c b/src/plugins/e-acsl/doc/userman/examples/valid.c new file mode 100644 index 0000000000000000000000000000000000000000..75ba01dce19fa9a764ed94210cc928bfdf7aea65 --- /dev/null +++ b/src/plugins/e-acsl/doc/userman/examples/valid.c @@ -0,0 +1,13 @@ +#include "stdlib.h" + +extern void *malloc(size_t); +extern void free(void*); + +int main(void) { + int *x; + x = (int*)malloc(sizeof(int)); + /*@ assert \valid(x); */ + free(x); + /*@ assert freed: \valid(x); */ + return 0; +} diff --git a/src/plugins/e-acsl/doc/userman/examples/valid_no_main.c b/src/plugins/e-acsl/doc/userman/examples/valid_no_main.c new file mode 100644 index 0000000000000000000000000000000000000000..da6dd0f055bc877a83f5479fd00d6e0a7e874674 --- /dev/null +++ b/src/plugins/e-acsl/doc/userman/examples/valid_no_main.c @@ -0,0 +1,13 @@ +#include "stdlib.h" + +extern void *malloc(size_t); +extern void free(void*); + +int f(void) { + int *x; + x = (int*)malloc(sizeof(int)); + /*@ assert \valid(x); */ + free(x); + /*@ assert freed: \valid(x); */ + return 0; +} diff --git a/src/plugins/e-acsl/doc/userman/frama-c-book.cls b/src/plugins/e-acsl/doc/userman/frama-c-book.cls new file mode 100644 index 0000000000000000000000000000000000000000..47463e1cc216eb43d7a224547eac4fef99aed78b --- /dev/null +++ b/src/plugins/e-acsl/doc/userman/frama-c-book.cls @@ -0,0 +1,332 @@ +% -------------------------------------------------------------------------- +% --- LaTeX Class for Frama-C Books --- +% -------------------------------------------------------------------------- +\NeedsTeXFormat{LaTeX2e} +\ProvidesPackage{frama-c-book}[2009/02/05 LaTeX Class for Frama-C Books] +% -------------------------------------------------------------------------- +% --- Base Class management --- +% -------------------------------------------------------------------------- +\LoadClass[a4paper,11pt,twoside,openright]{report} +\DeclareOption{web}{\PassOptionsToPackage{colorlinks,urlcolor=blue}{hyperref}} +\DeclareOption{paper}{\PassOptionsToPackage{pdfborder=0 0 0}{hyperref}} +\ProcessOptions +\RequirePackage{fullpage} +\RequirePackage{hevea} +\RequirePackage{ifthen} +\RequirePackage[T1]{fontenc} +\RequirePackage[latin1]{inputenc} +\RequirePackage[a4paper,pdftex,pdfstartview=FitH]{hyperref} +\RequirePackage{amssymb} +\RequirePackage{xcolor} +\RequirePackage[pdftex]{graphicx} +\RequirePackage{xspace} +\RequirePackage{makeidx} +\RequirePackage[leftbars]{changebar} +\RequirePackage[english]{babel} +\RequirePackage{fancyhdr} +\RequirePackage{titlesec} +% -------------------------------------------------------------------------- +% --- Page Layout --- +% -------------------------------------------------------------------------- +\setlength{\voffset}{-6mm} +\setlength{\headsep}{8mm} +\setlength{\footskip}{21mm} +\setlength{\textheight}{238mm} +\setlength{\topmargin}{0mm} +\setlength{\textwidth}{155mm} +\setlength{\oddsidemargin}{2mm} +\setlength{\evensidemargin}{-2mm} +\setlength{\changebarsep}{0.5cm} +\setlength{\headheight}{13.6pt} +\def\put@bg(#1,#2,#3)#4{\setlength\unitlength{1cm}% + \begin{picture}(0,0)(#1,#2) + \put(0,0){\includegraphics[width=#3cm]{#4}} + \end{picture}} +\fancypagestyle{plain}{% + \fancyfoot{} + \fancyhead{} + \fancyhead[LE]{\put@bg(2.4,27.425,21){frama-c-left.pdf}} + \fancyhead[LO]{\put@bg(2.7,27.425,21){frama-c-right.pdf}} + \fancyhead[CE]{\scriptsize\textsf{\leftmark}} + \fancyhead[CO]{\scriptsize\textsf{\rightmark}} + \fancyfoot[C]{\small\textsf{\thepage}} + \renewcommand{\headrulewidth}{0pt} + \renewcommand{\footrulewidth}{0pt} +} +\fancypagestyle{blank}{% + \fancyfoot{} + \fancyhead{} + \fancyhead[LE]{\put@bg(2.4,27.425,21){frama-c-left.pdf}} + \fancyhead[LO]{\put@bg(2.7,27.425,21){frama-c-right.pdf}} +} +%% Redefinition of cleardoublepage for empty page being blank +\def\cleardoublepagewith#1{\clearpage\if@twoside \ifodd\c@page\else +\hbox{} +\thispagestyle{#1} +\newpage +\fi\fi} +\def\cleardoublepage{\cleardoublepagewith{blank}} +\pagestyle{plain} + +% -------------------------------------------------------------------------- +% --- Cover Page --- +% -------------------------------------------------------------------------- +\newcommand{\coverpage}[1]{% +\thispagestyle{empty} +\setlength\unitlength{1cm} +\begin{picture}(0,0)(3.27,26.75) +\put(0.58,0.70){\includegraphics[width=20.9cm]{frama-c-cover.pdf}} +\put(2.0,20.5){\makebox[8cm][l]{\fontfamily{phv}\fontseries{m}\fontsize{24}{2}\selectfont #1}} +\end{picture} +} + +% -------------------------------------------------------------------------- +% --- Title Page --- +% -------------------------------------------------------------------------- +\renewenvironment{titlepage}% +{\cleardoublepagewith{empty}\thispagestyle{empty}\begin{center}}% +{\end{center}} +\renewcommand{\title}[2]{ +\vspace{20mm} +{\Huge\bfseries #1} + +\bigskip + +{\LARGE #2} +\vspace{20mm} +} +\renewcommand{\author}[1]{ +\vspace{20mm} + +{#1} + +\medskip +} +% -------------------------------------------------------------------------- +% --- Sectionning --- +% -------------------------------------------------------------------------- +\titleformat{\chapter}[display]{\Huge\raggedleft}% +{\huge\chaptertitlename\,\thechapter}{0.5em}{} +\titleformat{\section}[hang]{\Large\bfseries}{\thesection}{1em}{}% +[\vspace{-14pt}\rule{\textwidth}{0.1pt}\vspace{-8pt}] +\titleformat{\subsubsection}[hang]{\bfseries}{}{}{}% +[\vspace{-8pt}] + +% -------------------------------------------------------------------------- +% --- Main Text Style --- +% -------------------------------------------------------------------------- +%\raggedright +\setlength\parindent{0pt} +\setlength\parskip{1ex plus 0.3ex minus 0.2ex} +\newenvironment{warning}[1][Warning:]{\small\paragraph{#1}\itshape}{\vspace{\parskip}} +\def\FramaC{\textsf{Frama-C}\xspace} +% -------------------------------------------------------------------------- +% --- Listings --- +% -------------------------------------------------------------------------- +\RequirePackage{listings} + +\lstdefinelanguage{ACSL}{% + morekeywords={allocates,assert,assigns,assumes,axiom,axiomatic,behavior,behaviors, + boolean,breaks,complete,continues,data,decreases,disjoint,ensures, + exit_behavior,frees,ghost,global,inductive,integer,invariant,lemma,logic,loop, + model,predicate,reads,real,requires,returns,sizeof,strong,struct,terminates,type, + union,variant}, + keywordsprefix={\\}, + alsoletter={\\}, + morecomment=[l]{//} +} + +\lstloadlanguages{[ANSI]C,[Objective]Caml,csh,ACSL} +\definecolor{lstbg}{gray}{0.98} +\definecolor{lstfg}{gray}{0.10} +\definecolor{lstrule}{gray}{0.6} +\definecolor{lstnum}{gray}{0.4} +\definecolor{lsttxt}{rgb}{0.3,0.2,0.6} +\definecolor{lstmodule}{rgb}{0.3,0.6,0.2}%{0.6,0.6,0.2} +\definecolor{lstspecial}{rgb}{0.2,0.6,0.0} +\definecolor{lstfile}{gray}{0.85} +\newcommand{\lstbrk}{\mbox{$\color{blue}\scriptstyle\cdots$}} +\def\lp@basic{\ifmmode\normalfont\mathtt\mdseries\scriptsize\else\normalfont\ttfamily\mdseries\scriptsize\fi} +\def\lp@inline{\ifmmode\normalfont\mathtt\scriptstyle\else\normalfont\ttfamily\mdseries\small\fi} +\def\lp@keyword{} +\def\lp@special{\color{lstfg}} +\def\lp@comment{\normalfont\ttfamily\mdseries} +\def\lp@string{\color{lstfg}} \def\lp@ident{} +\def\lp@number{\rmfamily\tiny\color{lstnum}} +\lstdefinestyle{frama-c-style}{% + basicstyle=\lp@inline,% + identifierstyle=\lp@ident,% + commentstyle=\lp@comment,% + keywordstyle={\ifmmode\mathsf\else\sffamily\fi},% + keywordstyle=[2]\lp@special,% + stringstyle=\lp@string,% + emphstyle=\lp@ident\underbar,% + showstringspaces=false,% + mathescape=true,% + numberstyle=\lp@number,% + xleftmargin=6ex,xrightmargin=2ex,% + framexleftmargin=1ex,% + frame=l,% + framerule=1pt,% + rulecolor=\color{lstrule},% + backgroundcolor=\color{lstbg},% + moredelim={*[s]{/*@}{*/}},% + moredelim={*[l]{//@}},% + morecomment={[il]{//NOPP-LINE}},% invisible comment until end of line + morecomment={[is]{//NOPP-BEGIN}{NOPP-END\^^M}},% no space after NOPP-END + mathescape=true, + escapechar=` +% breaklines is broken when using a inline and background +% breaklines,prebreak={\lstbrk},postbreak={\lstbrk},breakindent=5ex % +} + +\lstdefinestyle{c}% +{language={[ANSI]C},alsolanguage=ACSL,style=frama-c-style} +\lstdefinestyle{c-basic}% +{language={[ANSI]C},alsolanguage=ACSL,style=frama-c-style,basicstyle=\lp@basic} + + +% --- C/ACSL Stuff --------------------------------------------------------- +% Make 'c' the default style +\lstset{style=c} + +\newcommand{\listinginput}[3][1]% +{\lstinputlisting[style=c-basic,numbers=left,stepnumber=#1,firstnumber=#2]{#3}} + +\newcommand{\listinginputcaption}[4][1]% +{\lstinputlisting[style=c-basic,numbers=left,stepnumber=#1,firstnumber=#2,title=#3]{#4}} + +\lstnewenvironment{listing}[2][1]% +{\lstset{style=c-basic,numbers=left,stepnumber=#1,firstnumber=#2}}{} + +\lstnewenvironment{listing-nonumber}% +{\lstset{style=c,numbers=none,basicstyle=\lp@basic}}{} + +% --- Verbatim Stuff ------------------------------------------------------- +\lstdefinelanguage{Shell}[]{csh}% +{identifierstyle=\lp@basic,mathescape=false,backgroundcolor=,literate={\\\$}{\$}1} +\lstnewenvironment{shell}[1][]{\lstset{language=Shell,basicstyle=\lp@basic,#1}}{} + +% ---- Stdout Stuff -------------------------------------------------------- +\lstdefinelanguage{Logs}[]{csh}% +{identifierstyle=\lp@basic,backgroundcolor=} +\lstnewenvironment{logs}[1][]{\lstset{language=Logs,basicstyle=\lp@basic,#1}}{} +\newcommand{\logsinput}[1]% +{\lstinputlisting[language=Logs,basicstyle=\lp@basic]{#1}} + +% -------------------------------------------------------------------------- +% --- Developer Code Stuff --- +% -------------------------------------------------------------------------- + +\newcommand{\listingname}[1]{\colorbox{lstfile}{\footnotesize\sffamily File \bfseries #1}\vspace{-4pt}} + +% --- Style ---------------------------------------------------------------- +\lstdefinestyle{framac-code-style}{% +basicstyle=\lp@inline,% +numberstyle=\lp@number,% +keywordstyle=[1]\sffamily\color{lstmodule},% +keywordstyle=[2]\sffamily\color{lstspecial},% +keywordstyle=[3]\sffamily\bfseries,% +identifierstyle=\rmfamily,% +stringstyle=\ttfamily\color{lstfg},% +commentstyle=\rmfamily\bfseries\color{lsttxt},% +} +\lstdefinestyle{framac-shell-style}{% +mathescape=false,% +basicstyle=\lp@basic,% +numberstyle=\lp@number,% +keywordstyle=\sffamily\bfseries,% +keywordstyle=[1]\sffamily\color{lstmodule},% +keywordstyle=[2]\sffamily\color{lstspecial},% +keywordstyle=[3]\sffamily\bfseries,% +identifierstyle=\ttfamily,% +stringstyle=\ttfamily\color{lstfg},% +commentstyle=\rmfamily\bfseries\color{lsttxt},% +literate={\\\$}{\$}1,% +} +% --- Configure ------------------------------------------------------------ +\lstdefinelanguage{Configure}[]{csh}{% +style=framac-shell-style,% +morekeywords={fi},% +} +\lstnewenvironment{configurecode}[1][]% +{\lstset{language=Configure,#1}}{} +\newcommand{\configureinput}[1]{\lstinputlisting[language=Configure]{#1}} +% --- Makefile ------------------------------------------------------------ +\lstdefinelanguage{Makefile}[]{make}{% +style=framac-shell-style,% +morekeywords={include},% +} +\lstnewenvironment{makefilecode}[1][]% +{\lstset{language=Makefile,#1}}{} +\newcommand{\makefileinput}[1]{\lstinputlisting[language=Makefile]{#1}} +% --- C- for Developer ---------------------------------------------------- +\lstdefinestyle{framac-code}% + {language={[ANSI]C},alsolanguage=ACSL,style=framac-code-style,basicstyle=\lp@basic} +\lstnewenvironment{ccode}[1][]% +{\lstset{language={[ANSI]C},alsolanguage=ACSL,style=framac-code-style,basicstyle=\lp@basic,#1}}{} +\newcommand{\cinput}[1]% +{\lstinputlisting[language={[ANSI]C},alsolanguage=ACSL,style=framac-code-style,basicstyle=\lp@basic]{#1}} +\newcommand{\cinline}[1]% +{\lstinline[style=framac-code]{#1}} +% --- Ocaml ---------------------------------------------------------------- +\lstdefinelanguage{Ocaml}[Objective]{Caml}{% +style=framac-code-style,% +deletekeywords={when,module,struct,sig,begin,end},% +morekeywords=[2]{failwith,raise,when},% +morekeywords=[3]{module,struct,sig,begin,end},% +literate=% +{~}{${\scriptstyle\thicksim}$}1% +{<}{$<$}1% +{>}{$>$}1% +{->}{$\rightarrow$}1% +{<-}{$\leftarrow$}1% +{:=}{$\leftarrow$}1% +{<=}{$\leq$}1% +{>=}{$\geq$}1% +{==}{$\equiv$}1% +{!=}{$\not\equiv$}1% +{<>}{$\neq$}1% +{'a}{$\alpha$}1% +{'b}{$\beta$}1% +{'c}{$\gamma$}1% +{µ}{`{}}1% +} + +\lstdefinestyle{ocaml-basic}% +{language=Ocaml,basicstyle=\lp@basic} +\newcommand{\ocamlinput}[2][]{\lstinputlisting[style=ocaml-basic,#1]{#2}} +\lstnewenvironment{ocamlcode}[1][]{\lstset{style=ocaml-basic,#1}}{} +% -------------------------------------------------------------------------- +\lstdefinelanguage{Why}{% + morekeywords={ + type, logic, axiom, predicate, goal, + forall, let, in, + }, + morecomment=[s]{(*}{*)}, + alsoletter={_}, + literate=% + {->}{$\Rightarrow$}1% + {forall}{$\forall$}1% + {not}{$\neg$}1% + {<>}{$\neq$}1% + {...}{$\dots$}1% + %{_}{\_}1% + %{_}{{\rule[0pt]{1ex}{.2pt}}}1% + } + +\lstdefinestyle{why-style}{% +language=Why,% +style=framac-code-style,% +basicstyle=\lp@inline,% +} + +\lstnewenvironment{whycode}[1][]{\lstset{style=why-style,#1}}{} +\newcommand{\whyinput}[1]% +{\lstinputlisting[style=why-style,basicstyle=\lp@basic]{#1}} +\newcommand{\whyinline}[1]% +{\lstinline[style=why-style]{#1}} + +% -------------------------------------------------------------------------- +% --- End. --- +% -------------------------------------------------------------------------- diff --git a/src/plugins/e-acsl/doc/userman/frama-c-cover.pdf b/src/plugins/e-acsl/doc/userman/frama-c-cover.pdf new file mode 100644 index 0000000000000000000000000000000000000000..4e14243c8064ca92d696fd354476dcdb31092895 Binary files /dev/null and b/src/plugins/e-acsl/doc/userman/frama-c-cover.pdf differ diff --git a/src/plugins/e-acsl/doc/userman/frama-c-left.pdf b/src/plugins/e-acsl/doc/userman/frama-c-left.pdf new file mode 100644 index 0000000000000000000000000000000000000000..ddf8888d292539177ab81c1b33d6411edf51c820 Binary files /dev/null and b/src/plugins/e-acsl/doc/userman/frama-c-left.pdf differ diff --git a/src/plugins/e-acsl/doc/userman/frama-c-right.pdf b/src/plugins/e-acsl/doc/userman/frama-c-right.pdf new file mode 100644 index 0000000000000000000000000000000000000000..db9b236dfdb19d9a6631ec55eee63f431f8d6f0d Binary files /dev/null and b/src/plugins/e-acsl/doc/userman/frama-c-right.pdf differ diff --git a/src/plugins/e-acsl/doc/userman/introduction.tex b/src/plugins/e-acsl/doc/userman/introduction.tex new file mode 100644 index 0000000000000000000000000000000000000000..1f263c145d11bfd25907b8fb67e7b1b62498321e --- /dev/null +++ b/src/plugins/e-acsl/doc/userman/introduction.tex @@ -0,0 +1,47 @@ +\chapter{Introduction} + +\framac~\cite{userman,fac15} is a modular analysis framework for the C +programming language which supports the ACSL specification +language~\cite{acsl}. This manual documents the \eacsl plug-in of \framac, +version \eacslversion. The \eacsl version you are using is indicated by the +command \texttt{frama-c -e-acsl-version}\optionidx{-}{e-acsl-version}. \eacsl +automatically translates an annotated C program into another program that fails +at runtime if an annotation is violated. If no annotation is violated, the +behavior of the new program is exactly the same as the one of the original +program. + +\eacsl translation brings several benefits. First, it allows a user to monitor +\C code and perform what is usually referred to as ``runtime assertion +checking''~\cite{runtime-assertion-checking}\footnote{In our context, ``runtime + annotation checking'' would be more precise.}. This is the primary goal of +\eacsl. Indirectly, in combination with the \rte plug-in~\cite{rte} of \framac, +this +usage allows the user to detect undefined behaviors in its \C code. Second, it +allows to combine \framac and its existing analyzers with other \C analyzers +that do not natively understand the \acsl specification language. Third, the +possibility to detect invalid annotations during a concrete execution may be +very helpful while writing a correct specification of a given program, +\emph{e.g.} for later program proving. Finally, an executable specification +makes it possible to check assertions that cannot be verified statically and +thus to establish a link between runtime monitoring and static analysis tools +such as \Eva~\cite{eva}\index{Eva} or \wpplugin~\cite{wp}\index{Wp}. + +Annotations used by the plug-in must be written in the \eacsl specification +language~\cite{eacsl,sac13} -- a subset of \acsl. \eacsl plug-in is still in a +preliminary state: some parts of the \eacsl specification language are not yet +supported. Annotations supported by the plugin are described in a separate +document~\cite{eacsl-implem}. It is worth noting that the annotations that aim +to be dynamically verified are not necessarily hand-written, but may be +automatically generated instead. That is for instance the case when checking the +absence of undefined behaviors in combination with RTE, as mentionned in the +previous paragraph. Using \eacsl this way is therefore a fully automatic +process. Many usages, including automatic usages, are described in companion +research papers~\cite{rv13tutorial,rvcubes17tool,signoles18hdr}. + +This manual does \emph{not} explain how to install the \eacsl plug-in. For +installation instructions please refer to the \texttt{INSTALL} file in the +\eacsl distribution. \index{Installation} Furthermore, even though this manual +provides examples, it is \emph{not} a full comprehensive tutorial on +\framac or \eacsl. +% You can still refer to any external +% tutorial~\cite{rv13tutorial} for additional examples. diff --git a/src/plugins/e-acsl/doc/userman/limitations.tex b/src/plugins/e-acsl/doc/userman/limitations.tex new file mode 100644 index 0000000000000000000000000000000000000000..ec0d86ba6c26d28e71a791c5268787dcd87b2908 --- /dev/null +++ b/src/plugins/e-acsl/doc/userman/limitations.tex @@ -0,0 +1,213 @@ +\chapter{Known Limitations} + +The development of the \eacsl plug-in is still ongoing. First, the \eacsl +reference manual~\cite{eacsl} is not yet fully supported. Which annotations can +already be translated into \C code and which cannot is defined in a separate +document~\cite{eacsl-implem}. Second, even though we do our best to avoid them, +bugs may exist. If you find a new one, please report it on the bug tracking +system\footnote{\url{http://bts.frama-c.com}} (see Chapter 10 of the \framac +User Manual~\cite{userman}). Third, there +are some additional known limitations, which could be annoying for the user in +some cases, but are tedious to lift. Please contact us if you are interested in +lifting these limitations\footnote{Read \url{http://frama-c.com/support.html} + for additional details.}. + +\section{Supported Systems} + +\begin{important} +The only well-supported system is a Linux distribution on a 64-bit architecture. +\end{important} + +\subsection{Operating Systems} + +Non-Linux systems are almost not yet experimented. It might work but there are +most probably issues, in particular if using a non-standard +libc\index{Libc}. For instance, there are known bugs under Mac OS +X\index{Mac OS X}\footnote{See for instance at + \url{https://bts.frama-c.com/view.php?id=2369}}. + +\subsection{Architectures and Runtime Library} + +The segment-based memory model (used by default for monitoring memory properties +such as \lstinline|\valid|) assumes little-endian architecture and has very +limited support for 32-bit architectures. When using a 32-bit machine or +big-endians, we recomend using the bittree-based memory model instead. + +\begin{important} +The runtime library is also \emph{not} thread-safe. +\end{important} + +\section{Uninitialized Values} +\index{Uninitialized value} + +As explained in Section~\ref{sec:runtime-error}, the \eacsl plug-in should never +translate an annotation into \C code which can lead to a runtime error. This is +enforced, except for uninitialized values which are values read before having +been written. + +\listingname{uninitialized.i} +\cinput{examples/uninitialized.i} + +If you generate the instrumented code, compile it, and finally execute it, you +may get no runtime error depending on your \C compiler, but the behavior is +actually undefined because the assertion reads the uninitialized variable +\lstinline|x|. You should be caught by the \eacsl plug-in, but that is not +the case yet. +\begin{shell} + +\$ e-acsl-gcc.sh uninitialized.i -c -Omonitored_uninitialized +monitored_uninitialized.i: In function 'main': +monitored_uninitialized.i:44:16: warning: 'x' is used uninitialized in this function +[-Wuninitialized] +\$ ./monitored_uninitialized.e-acsl +\end{shell} + +This is more a design choice than a limitation: should the \eacsl plug-in +generate additional instrumentation to prevent such values from being evaluated, +the generated code would be much more verbose and slower. + +If you really want to track such uninitializations in your annotation, you have +to manually add calls to the \eacsl predicate +\lstinline|\initialized|~\cite{eacsl}. + +\section{Incomplete Programs} + +Section~\ref{sec:incomplete} explains how the \eacsl plug-in is able to handle +incomplete programs, which are either programs without main, or programs +containing undefined functions (\emph{i.e.} functions without body). + +However, if such programs contain memory-related annotations, the generated code +may be incorrect. That is made explicit by a warning displayed when the \eacsl +plug-in is running (see examples of Sections~\ref{sec:no-main} and +\ref{sec:no-code}). + +\subsection{Programs without Main} +\index{Program!Without main} +\label{sec:limits:no-main} + +The instrumentation in the generated program is partial for every program +without main containing memory-related annotations, except if the option +\optionuse{-}{e-acsl-full-mmodel} or the \eacsl plug-in (of \shortopt{M} option +of \eacslgcc) is provided. In that case, violations of such annotations are +undetected. + +Consider the following example. + +\listingname{valid\_no\_main.c} +\cinput{examples/valid_no_main.c} + +You can generate the instrumented program as follows. +\begin{shell} +\$ e-acsl-gcc.sh -ML -omonitored_valid_no_main.i valid_no_main.c +<skip preprocessing commands> +[e-acsl] beginning translation. +<skip warnings about annotations from the Frama-C libc + which cannot be translated> +[kernel] warning: no entry point specified: + you must call function `__e_acsl_memory_init' by yourself. +[e-acsl] translation done in project "e-acsl". +\end{shell} + +The last warning states an important point: if this program is linked against +another file containing \texttt{main} function, then this main function must +be modified to insert a call to the function \texttt{\_\_e\_acsl\_memory\_init} +\index{e\_acsl\_memory\_init@\texttt{\_\_e\_acsl\_memory\_init}} at the very +beginning. This function plays a very important role: it initializes metadata +storage used for tracking of memory blocks. Unless this call is inserted the +run of a modified program is likely to fail. + +While it is possible to add such intrumentation manually we recommend using +\eacslgcc. Consider the following incomplete program containing \T{main}: + +\listingname{modified\_main.c} +\cinput{examples/modified_main.c} + +Then just compile and run it as explained in Section~\ref{sec:memory}. + +\begin{shell} +\$ e-acsl-gcc.sh -M -omonitored_modified_main.i modified_main.c +\$ e-acsl-gcc.sh -C -Ovalid_no_main monitored_modified_main.i monitored_valid_no_main.i +\$ ./valid_no_main.e-acsl +Assertion failed at line 11 in function f. +The failing predicate is: +freed: \valid(x). +Aborted +\end{shell} + +Also, if the unprovided main initializes some variables, running the +instrumented code (linked against this main) could print some warnings from the +\eacsl memory library\footnote{see + \url{https://bts.frama-c.com/view.php?id=1696} for an example}. + +\subsection{Undefined Functions} +\label{sec:limits:no-code} +\index{Function!Undefined} + +The instrumentation in the generated program is partial for a program $p$ if $p$ +contains a memory-related annotation $a$ and an undefined function +$f$ such that: +\begin{itemize} +\item either $f$ has an (even indirect) effect on a left-value occurring in $a$; +\item or $a$ is one of the post-conditions of $f$. +\end{itemize} +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 +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} +\index{Function!Recursive} + +Programs containing recursive functions have the same limitations as the ones +containing undefined functions (Section~\ref{sec:limits:no-code}) and +memory-related annotations. + +%% JS: this issue should have been fixed: +%% Also, even though there is no such annotations, the generated code may call a +%% function before it is declared. When this behavior appears remains +%% unspecifed. The generated code is however easy to fix by hand. + +\section{Variadic Functions} +\index{Function!Variadic} + +Programs containing undefined variadic functions with contracts +are not yet supported. Using the \variadic plug-in of \framac could be a +solution in some cases, but its generated code cannot always be compiled. + +\section{Function Pointers} +\index{Function!Pointer} + +Programs containing function pointers have the same limitations on +memory-related annotations as the ones containing undefined or recursive +functions. + +\section{Requirements to Input Programs} +\index{Function!Input} + +\subsection{\eacsl Namespace} +While \eacsl uses source-to-source transformations and not binary +instrumentations it is important that the source code provided at input does +not contain any variables or functions prefixed \T{\_\_e\_acsl\_}. \eacsl +reserves this namespace for its transformations, and therefore an input program +containing such symbols beforehand may fail to be instrumented or compiled. + +\subsection{Memory Management Functions} +Programs providing custom definitions of \T{syscall}, \T{mmap} or +\T{sbrk} should be rejected. Also, an input programs should not modify +memory-management functions namely \T{malloc}, \T{calloc}, \T{realloc}, +\T{free}, \T{cfree}, \T{posix\_memalign} and \T{aligned\_alloc}. \eacsl relies +on these functions in order to track heap memory. Further, correct heap memory +monitoring requires to limit allocation and deallocation of heap memory to +POSIX-compliant memory management functions +listed above. Monitoring of programs that allocate memory using non-standard or +obsolete functions (e.g., \T{valloc}, \T{memalign}, \T{pvalloc}) may not work +correctly. diff --git a/src/plugins/e-acsl/doc/userman/macros.tex b/src/plugins/e-acsl/doc/userman/macros.tex new file mode 100644 index 0000000000000000000000000000000000000000..fd7bfa93e0321a07884ee12b0dc1c3b2853d3955 --- /dev/null +++ b/src/plugins/e-acsl/doc/userman/macros.tex @@ -0,0 +1,296 @@ +%%% Environnements dont le corps est suprimé, et +%%% commandes dont la définition est vide, +%%% lorsque PrintRemarks=false + +\usepackage{comment} + +\newcommand{\framac}{\textsc{Frama-C}\xspace} +\newcommand{\acsl}{\textsc{ACSL}\index{ACSL}\xspace} +\newcommand{\eacsl}{\textsc{E-ACSL}\xspace} +\newcommand{\eacslgcc}{\texttt{e-acsl-gcc.sh}\xspace} +\newcommand{\rte}{\textsc{RTE}\index{RTE}\xspace} +\newcommand{\C}{\textsc{C}\xspace} +\newcommand{\jml}{\textsc{JML}\index{JML}\xspace} +\newcommand{\Eva}{\textsc{Eva}\index{Eva}\xspace} +\newcommand{\variadic}{\textsc{Variadic}\index{Variadic}\xspace} +\newcommand{\wpplugin}{\textsc{Wp}\index{WP}\xspace} +\newcommand{\pathcrawler}{\textsc{PathCrawler}\index{PathCrawler}\xspace} +\newcommand{\gcc}{\textsc{Gcc}\xspace} +\newcommand{\gmp}{\textsc{GMP}\index{GMP}\xspace} +\newcommand{\dlmalloc}{\textsc{dlmalloc}\index{dlmalloc}\xspace} + +\newcommand{\nodiff}{\emph{No difference with \acsl.}} +\newcommand{\except}[1]{\emph{No difference with \acsl, but #1.}} +\newcommand{\limited}[1]{\emph{Limited to #1.}} +\newcommand{\absent}{\emph{No such feature in \eacsl.}} +\newcommand{\absentwhy}[1]{\emph{No such feature in \eacsl: #1.}} +\newcommand{\absentexperimental}{\emph{No such feature in \eacsl, since it is + still experimental in \acsl.}} +\newcommand{\absentexcept}[1]{\emph{No such feature in \eacsl, but #1.}} +\newcommand{\difficultwhy}[2]{\emph{#1 is usually difficult to implement, since + it requires #2. Thus you would not wonder if most tools do not support it + (or support it partially).}} +\newcommand{\difficultswhy}[2]{\emph{#1 are usually difficult to implement, + since they require #2. Thus you would not wonder if most tools do not + support them (or support them partially).}} +\newcommand{\difficult}[1]{\emph{#1 is usually difficult to implement. Thus + you would not wonder if most tools do not support it (or support + it partially).}} +\newcommand{\difficults}[1]{\emph{#1 are usually difficult to implement. Thus + you would not wonder if most tools do not support them (or support + them partially).}} +\newcommand{\experimental}[1]{\emph{#1 is still an experimental feature. It may +evolve in the future and/or not work as expected.}} + +\newcommand{\changeinsection}[2]{\textbf{Section \ref{sec:#1}:} #2.} + +\newcommand{\todo}[1]{{\large \textbf{TODO: #1.}}} + +\newcommand{\markdiff}[1]{{\color{blue}{#1}}} +\newenvironment{markdiffenv}[1][]{% + \begin{changebar}% + \markdiff\bgroup% +}% +{\egroup\end{changebar}} + +% true = prints remarks for the ACSL working group. +% false = prints no remark for the distributed version of ASCL documents +\newboolean{PrintRemarks} +\setboolean{PrintRemarks}{false} + +% true = prints marks signaling the state of the implementation +% false = prints only the ACSL definition, without remarks on implementation. +\newboolean{PrintImplementationRq} +\setboolean{PrintImplementationRq}{true} + +% true = remarks about the current state of implementation in Frama-C +% are in color. +% false = they are rendered with an underline +\newboolean{ColorImplementationRq} +\setboolean{ColorImplementationRq}{true} + +%% \ifthenelse{\boolean{PrintRemarks}}% +%% {\newenvironment{todo}{% +%% \begin{quote}% +%% \begin{tabular}{||p{0.8\textwidth}}TODO~:\itshape}% +%% {\end{tabular}\end{quote}}}% +%% {\excludecomment{todo}} + +\ifthenelse{\boolean{PrintRemarks}}% + {\newenvironment{remark}[1]{% + \begin{quote}\itshape% + \begin{tabular}{||p{0.8\textwidth}}Remarque de {#1}~:}% + {\end{tabular}\end{quote}}}% + {\excludecomment{remark}} + +\newcommand{\oldremark}[2]{% +\ifthenelse{\boolean{PrintRemarks}}{% + %\begin{quote}\itshape% + %\begin{tabular}{||p{0.8\textwidth}}Vieille remarque de {#1}~: #2% + %\end{tabular}\end{quote}% +}% +{}} + +\newcommand{\highlightnotreviewed}{% +\color{blue}% +}% + +\newcommand{\notreviewed}[2][]{% +\ifthenelse{\boolean{PrintRemarks}}{% + \begin{changebar}% + {\highlightnotreviewed #2}% + \ifthenelse{\equal{#1}{}}{}{\footnote{#1}}% + \end{changebar}% +}% +{}} + +\ifthenelse{\boolean{PrintRemarks}}{% +\newenvironment{notreviewedenv}[1][]{% + \begin{changebar}% + \highlightnotreviewed% + \ifthenelse{\equal{#1}{}}{}{\def\myrq{#1}}% + \bgroup}% + {\egroup% + \ifthenelse{\isundefined{\myrq}}{}{\footnote{\myrq}}\end{changebar}}}% +{\excludecomment{notreviewedenv}} + +%%% Commandes et environnements pour la version relative à l'implementation +\newcommand{\highlightnotimplemented}{% +\ifthenelse{\boolean{ColorImplementationRq}}{\color{red}}% + {\ul}% +}% + +\newcommand{\notimplemented}[2][]{% +\ifthenelse{\boolean{PrintImplementationRq}}{% + \begin{changebar}% + {\highlightnotimplemented #2}% + \ifthenelse{\equal{#1}{}}{}{\footnote{#1}}% + \end{changebar}% +}% +{#2}} + +\newenvironment{notimplementedenv}[1][]{% +\ifthenelse{\boolean{PrintImplementationRq}}{% + \begin{changebar}% + \highlightnotimplemented% + \ifthenelse{\equal{#1}{}}{}{\def\myrq{#1}}% + \bgroup +}{}}% +{\ifthenelse{\boolean{PrintImplementationRq}}{% + \egroup% + \ifthenelse{\isundefined{\myrq}}{}{\footnote{\myrq}}\end{changebar}}{}} + +%%% Environnements et commandes non conditionnelles +\newcommand{\experimentalword}{\textsc{Experimental}} + +\newsavebox{\fmbox} +\newenvironment{cadre} + {\begin{lrbox}{\fmbox}\begin{minipage}{0.98\textwidth}} + {\end{minipage}\end{lrbox}\fbox{\usebox{\fmbox}}} + + +\newcommand{\keyword}[1]{\lstinline|#1|\xspace} +\newcommand{\keywordbs}[1]{\lstinline|\\#1|\xspace} + +\newcommand{\integer}{\keyword{integer}} +\newcommand{\real}{\keyword{real}} +\newcommand{\bool}{\keyword{boolean}} + +\newcommand{\assert}{\keyword{assert}} +\newcommand{\terminates}{\keyword{terminates}} +\newcommand{\assume}{\keyword{assume}} +\newcommand{\requires}{\keyword{requires}} +\newcommand{\ensures}{\keyword{ensures}} +\newcommand{\exits}{\keyword{exits}} +\newcommand{\returns}{\keyword{returns}} +\newcommand{\breaks}{\keyword{breaks}} +\newcommand{\continues}{\keyword{continues}} +\newcommand{\assumes}{\keyword{assumes}} +\newcommand{\assigns}{\keyword{assigns}} +\newcommand{\reads}{\keyword{reads}} +\newcommand{\decreases}{\keyword{decreases}} + +\newcommand{\boundseparated}{\keywordbs{bound\_separated}} +\newcommand{\Exists}{\keywordbs{exists}~} +\newcommand{\Forall}{\keywordbs{forall}~} +\newcommand{\bslambda}{\keywordbs{lambda}~} +\newcommand{\freed}{\keywordbs{freed}} +\newcommand{\fresh}{\keywordbs{fresh}} +\newcommand{\fullseparated}{\keywordbs{full\_separated}} +\newcommand{\distinct}{\keywordbs{distinct}} +\newcommand{\Max}{\keyword{max}} +\newcommand{\nothing}{\keywordbs{nothing}} +\newcommand{\numof}{\keyword{num\_of}} +\newcommand{\offsetmin}{\keywordbs{offset\_min}} +\newcommand{\offsetmax}{\keywordbs{offset\_max}} +\newcommand{\old}{\keywordbs{old}} +\newcommand{\at}{\keywordbs{at}} + +\newcommand{\If}{\keyword{if}~} +\newcommand{\Then}{~\keyword{then}~} +\newcommand{\Else}{~\keyword{else}~} +\newcommand{\For}{\keyword{for}~} +\newcommand{\While}{~\keyword{while}~} +\newcommand{\Do}{~\keyword{do}~} +\newcommand{\Let}{\keywordbs{let}~} +\newcommand{\Break}{\keyword{break}} +\newcommand{\Return}{\keyword{return}} +\newcommand{\Continue}{\keyword{continue}} + +\newcommand{\exit}{\keyword{exit}} +\newcommand{\main}{\keyword{main}} +\newcommand{\void}{\keyword{void}} + +\newcommand{\struct}{\keyword{struct}} +\newcommand{\union}{\keywordbs{union}} +\newcommand{\inter}{\keywordbs{inter}} +\newcommand{\typedef}{\keyword{typedef}} +\newcommand{\result}{\keywordbs{result}} +\newcommand{\separated}{\keywordbs{separated}} +\newcommand{\sizeof}{\keyword{sizeof}} +\newcommand{\strlen}{\keywordbs{strlen}} +\newcommand{\Sum}{\keyword{sum}} +\newcommand{\valid}{\keywordbs{valid}} +\newcommand{\validrange}{\keywordbs{valid\_range}} +\newcommand{\offset}{\keywordbs{offset}} +\newcommand{\blocklength}{\keywordbs{block\_length}} +\newcommand{\baseaddr}{\keywordbs{base\_addr}} +\newcommand{\comparable}{\keywordbs{comparable}} + +\newcommand{\N}{\ensuremath{\mathbb{N}}} +\newcommand{\ra}{\ensuremath{\rightarrow}} +\newcommand{\la}{\ensuremath{\leftarrow}} + +% BNF grammar +\newcommand{\indextt}[1]{\index{#1@\protect\keyword{#1}}} +\newcommand{\indexttbs}[1]{\index{#1@\protect\keywordbs{#1}}} +\newif\ifspace +\newif\ifnewentry +\newcommand{\addspace}{\ifspace ~ \spacefalse \fi} +\newcommand{\term}[2]{\addspace\hbox{\lstinline|#1|% +\ifthenelse{\equal{#2}{}}{}{\indexttbase{#2}{#1}}}\spacetrue} +\newcommand{\nonterm}[2]{% + \ifthenelse{\equal{#2}{}}% + {\addspace\hbox{\textsl{#1}\ifnewentry\index{grammar entries!\textsl{#1}}\fi}\spacetrue}% + {\addspace\hbox{\textsl{#1}\footnote{#2}\ifnewentry\index{grammar entries!\textsl{#1}}\fi}\spacetrue}} +\newcommand{\repetstar}{$^*$\spacetrue} +\newcommand{\repetplus}{$^+$\spacetrue} +\newcommand{\repetone}{$^?$\spacetrue} +\newcommand{\lparen}{\addspace(} +\newcommand{\rparen}{)} +\newcommand{\orelse}{\addspace$\mid$\spacetrue} +\newcommand{\sep}{ \\[2mm] \spacefalse\newentrytrue} +\newcommand{\newl}{ \\ & & \spacefalse} +\newcommand{\alt}{ \\ & $\mid$ & \spacefalse} +\newcommand{\is}{ & $::=$ & \newentryfalse} +\newenvironment{syntax}{\begin{tabular}{@{}rrll@{}}\spacefalse\newentrytrue}{\end{tabular}} +\newcommand{\synt}[1]{$\spacefalse#1$} +\newcommand{\emptystring}{$\epsilon$} +\newcommand{\below}{See\; below} + +% colors + +\definecolor{darkgreen}{rgb}{0, 0.5, 0} + +% theorems + +\newtheorem{example}{Example}[chapter] + +% for texttt + +\newcommand{\bs}{\ensuremath{\backslash}} + +% Index + +\newcommand{\optionidx}[2]{\index{#2@\texttt{#1#2}}} +\newcommand{\codeidx}[1]{\index{#1@\texttt{#1}}} +\newcommand{\scodeidx}[2]{\index{#1@\texttt{#1}!#2@\texttt{#2}}} +\newcommand{\sscodeidx}[3]{% + \index{#1@\texttt{#1}!#2@\texttt{#2}!#3@\texttt{#3}}} +\newcommand{\bfit}[1]{\textbf{\textit{\hyperpage{#1}}}} +\newcommand{\optionidxdef}[2]{\index{#2@\texttt{#1#2}|bfit}} +\newcommand{\codeidxdef}[1]{\index{#1@\texttt{#1}|bfit}} +\newcommand{\scodeidxdef}[2]{\index{#1@\texttt{#1}!#2@\texttt{#2}|bfit}} +\newcommand{\sscodeidxdef}[3]{% + \index{#1@\texttt{#1}!#2@\texttt{#2}!#3@\texttt{#3}|bfit}} + +\newcommand{\pragmadef}[1]{\texttt{#1}\index{Pragma!#1@\texttt{#1}}} +\newcommand{\optiondef}[2]{\texttt{#1#2}\optionidxdef{#1}{#2}} +\newcommand{\textttdef}[1]{\texttt{#1}\codeidxdef{#1}} + +\newcommand{\optionuse}[2]{\texttt{#1#2}\optionidx{#1}{#2}} +\newcommand{\textttuse}[1]{\texttt{#1}\codeidx{#1}} +\newcommand{\shortopt}[1]{\optionuse{-}{#1}} +\newcommand{\longopt}[1]{\optionuse{{-}{-}}{#1}} +% Shortcuts for truetype, italic and bold +\newcommand{\T}[1]{\texttt{#1}} +\newcommand{\I}[1]{\textit{#1}} +\newcommand{\B}[1]{\textbf{#1}} + +\definecolor{gris}{gray}{0.85} +\makeatletter +\newenvironment{important}% +{\hspace{5pt plus \linewidth minus \marginparsep}% + \begin{lrbox}{\@tempboxa}% + \begin{minipage}{\linewidth - 2\fboxsep}} +{\end{minipage}\end{lrbox}\colorbox{gris}{\usebox{\@tempboxa}}} diff --git a/src/plugins/e-acsl/doc/userman/main.tex b/src/plugins/e-acsl/doc/userman/main.tex new file mode 100644 index 0000000000000000000000000000000000000000..9cfb3ba30b59cadc796b60f3481b39be770c362a --- /dev/null +++ b/src/plugins/e-acsl/doc/userman/main.tex @@ -0,0 +1,87 @@ +\documentclass[web]{frama-c-book} + +\usepackage{graphicx} +\usepackage{calc} + +\include{macros} +\include{eacslversion} + +\makeindex + +\begin{document} + +\coverpage{\eacsl User Manual} + +\begin{titlepage} +\begin{flushleft} +\includegraphics[height=14mm]{cealistlogo.jpg} +\end{flushleft} +\vfill +\title{\eacsl Plug-in}{Release \eacslversion + \ifthenelse{\equal{\eacslversion}{\fcversion}}{}{% + \\[1em] compatible with \framac \fcversion}} +\author{Julien Signoles and Kostyantyn Vorobyov} +\begin{center} +CEA LIST\\ Software Reliability \& Security Laboratory +\end{center} +\vfill +\begin{flushleft} + \textcopyright 2013-2018 CEA LIST +%% + %% This work has been supported by the `Hi-Lite' FUI project (FUI AAP 9). +\end{flushleft} +\end{titlepage} + +\tableofcontents + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\chapter*{Foreword} +\markright{} +\addcontentsline{toc}{chapter}{Foreword} + +This is the user manual of the \framac plug-in +\eacsl\footnote{\url{https://frama-c.com/eacsl.html}}. The contents of this +document correspond to its version \eacslversion compatible with +\fcversion version of \framac~\cite{userman,fac15}. The development of +the \eacsl plug-in is still ongoing. Features described by this document may +evolve in the future. + +\section*{Acknowledgements} + +We gratefully thank the people who contributed to this document: +Pierre-Lo\"ic Garoche, Jens Gerlach, Florent Kirchner, Nikola\"i Kosmatov, +Andr\'e Oliveira Maroneze, Fonenantsoa Maurica, and Guillaume Petiot. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\include{introduction} +\include{provides} +\include{limitations} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\appendix + +\include{changes} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\cleardoublepage +\addcontentsline{toc}{chapter}{\bibname} +\bibliographystyle{plain} +\bibliography{./biblio} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% \cleardoublepage +%% \addcontentsline{toc}{chapter}{\listfigurename} +%% \listoffigures + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\cleardoublepage +\addcontentsline{toc}{chapter}{\indexname} +\printindex + +\end{document} diff --git a/src/plugins/e-acsl/doc/userman/provides.tex b/src/plugins/e-acsl/doc/userman/provides.tex new file mode 100644 index 0000000000000000000000000000000000000000..18df5fe9d39c61acac7b65e4a931299f9e7f7c71 --- /dev/null +++ b/src/plugins/e-acsl/doc/userman/provides.tex @@ -0,0 +1,1129 @@ +\chapter{What the Plug-in Provides} + +This chapter is the core of this manual and describes how to use the \eacsl +plug-in. +% You can still call the option \shortopt{e-acsl-help} to get the list of +% available options with few lines of documentation. +First, Section~\ref{sec:simple} shows how to run the plug-in on a toy example, +compile the generated code with the \gcc compiler and detect invalid +annotations at runtime. Further, Section~\ref{sec:wrapper} describes \eacslgcc\ +-- a convenience wrapper script around \framac and \gcc. The aim of this script +is to simplify instrumentation and compilation of the instrumented code. +Section~\ref{sec:exec-env} gives additional details on the execution of the +generated code. Next, Section~\ref{sec:incomplete} focuses on how to deal with +incomplete programs, \emph{i.e.} in which some functions are not defined or in +which there are no main function. Section~\ref{sec:combine} explains how to +combine the \eacsl plug-in with other \framac plug-ins. Finally, +Section~\ref{sec:custom} introduces how to customize the plug-in, and +Section~\ref{sec:verbose} details the verbosing policy of the plug-in. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\section{Simple Example} % <<< +\label{sec:simple} + +This section is a mini-tutorial which explains from scratch how to use the +\eacsl plug-in to detect whether an \eacsl annotation is violated at runtime. + +% All tool invocations and code listings shown in this section assume a Linux +% distribution with system-wide \framac installation. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\subsection{Running \eacsl} +\label{sec:run} + +Consider the following program containing two \eacsl assertions such that +the first assertion is valid, whereas the second one is not. + +\listingname{first.i} +\cinput{examples/first.i} + +Running \eacsl on \texttt{first.i} consists of adding \shortopt{e-acsl} option +to the \framac command line: +\begin{shell} +\$ frama-c -e-acsl first.i +[kernel] Parsing FRAMAC_SHARE/libc/__fc_builtin_for_normalization.i (no preprocessing) +[kernel] Parsing FRAMAC_SHARE/e-acsl/e_acsl.h (with preprocessing) +[kernel] Parsing FRAMAC_SHARE/e-acsl/e_acsl_gmp.h (with preprocessing) +[kernel] Parsing FRAMAC_SHARE/e-acsl/e_acsl_mmodel_api.h (with preprocessing) +[kernel] Parsing first.i (no preprocessing) +[e-acsl] beginning translation. +<skip a warning when translating the Frama-C libc> +[e-acsl] translation done in project "e-acsl". +\end{shell} + +Even though \texttt{first.i} has already been pre-processed, \eacsl first asks +the \framac kernel to process and combine it against several header files +provided by the \eacsl plug-in. Further \eacsl translates the annotated code +into a new \framac project named \texttt{e-acsl}\footnote{The notion of +\emph{project} is explained in Section 8.1 of the \framac user +manual~\cite{userman}.}. By default, the option \shortopt{e-acsl} does nothing +more. It is however possible to have a look at the generated code in the +\framac GUI. This is also possible through the command line thanks to the +kernel options \shortopt{then-last} and \shortopt{print}. The former +switches to the last generated project, while the latter pretty prints the \C +code~\cite{userman}: + +\input{examples/instrumented_first.c} + +As you can see, the generated code contains additional type declarations, +constant declarations and global \acsl annotations not present in the initial +file \texttt{first.i}. They are part of the \eacsl monitoring library. You can +safely ignore them for now. The translated \texttt{main} function of +\texttt{first.i} is displayed at the end. After each \eacsl annotation, +a call to \texttt{\_\_e\_acsl\_assert}\codeidx{e\_acsl\_assert} has been added. + +\begin{minipage}{\linewidth} +\begin{ccode} + /*@ assert x == 0; */ + __e_acsl_assert(x == 0,(char *)"Assertion",(char *)"main",(char *)"x == 0",3); + /*@ assert x == 1; */ + __e_acsl_assert(x == 1,(char *)"Assertion",(char *)"main",(char *)"x == 1",4); +\end{ccode} +\end{minipage} + +Each call to \texttt{\_\_e\_acsl\_assert}\codeidx{e\_acsl\_assert}, function +defined by the \eacsl monitoring library, dynamically verifies the validity of +the corresponding assertion. In other words, it checks that its first argument +(here \texttt{x == 0} or \texttt{x == 1}) is not equal to 0 and fails +otherwise. The extra arguments are used to display error reports as shown in +Section~\ref{sec:exec}. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\subsection{Executing the generated code} +\label{sec:exec} + +Using \shortopt{ocode} \framac~\cite{userman} option, the code generated by the +\eacsl plug-in can be redirected into a file as follows: +\begin{shell} +\$ frama-c -e-acsl first.i -then-last -print -ocode monitored_first.c +\end{shell} + +\framac uses architecture-dependent configuration which +affects sizes of integer types, endianness and potentially other features. It +can be seen that the code generated from \texttt{first.i} (shown in the +previous section) defines \C type \texttt{size\_t} as \texttt{unsigned int}, whereas +in 64-bit architectures \texttt{size\_t} is typically defined as +\texttt{unsigned long}. Architecture used during \framac translation is +controlled through \framac \shortopt{machdep} option that specifies the +architecture type to use during translation. The default value of +\shortopt{machdep} is \texttt{x86\_32} (a generic 32-bit x86 architecture). +Note that since code generated by \eacsl is aimed at being compiled it is +important that the architecture used by \framac matches the architecture +corresponding to your compiler and your system. For instance, in a 64-bit +machine you should also pass +\shortopt{machdep} \texttt{x86\_64} option as follows: +\begin{shell} + \$ frama-c -machdep x86_64 -e-acsl first.i -then-last \ + -print -ocode monitored_first.c +\end{shell} + +This file can be compile with a \C compiler (for instance \gcc), as follows: + +\lstset{escapechar=£} +\begin{shell} +\$ gcc -c -Wno-attributes monitored_first.c +\end{shell} + +However, creating an executable through a proper invokation to \gcc is painful +and is not documented. Instead, \eacsl comes with a companion wrapper script for +this purpose. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%>>> +\section{\eacsl Wrapper Script} % <<< +\label{sec:wrapper} + +\begin{important}\index{Gcc} + Presently, \eacslgcc is a recommended way of running the \eacsl plug-in. + This manual further describes features of the \eacsl plug-in using \eacslgcc + as its main driver for source code instrumentation and compilation of the + instrumented programs. +\end{important} + +In this section we describe \eacslgcc and provide several examples of its use. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\subsection{Standard Usage} + +The default behaviour of \eacslgcc is to instrument an annotated C program +with runtime assertions via a run of \framac. + +\begin{shell} + \$ e-acsl-gcc.sh -omonitored_first.i first.i +\end{shell} + +The above command instruments \texttt{first.i} with runtime assertions and +outputs the generated code to \texttt{monitored\_first.i}. Unless the name of +the output file is specified via the \shortopt{o} option (i.e., +\shortopt{-omonitored\_first.i} in the above example), the generated +code is placed to a file named \texttt{a.out.frama.c}. + +Compilation and Linking of the original and the instrumented sources +is enabled using the \shortopt{c} option. For instance, command + +\begin{shell} + \$ e-acsl-gcc.sh -c -omonitored_first.i first.i +\end{shell} + +instruments the code in \texttt{first.i}, outputs it to +\texttt{monitored\_first.i} and produces 2 executables: \texttt{a.out} and +\texttt{a.out.e-acsl}, such that \texttt{a.out} is an executable compiled from +\texttt{first.i}, while \texttt{a.out.e-acsl} is an executable compiled from +\texttt{monitored\_first.i} generated by \eacsl. + +You can execute the generate binaries, in particular \texttt{a.out.e-acsl} which +detects at runtime the incorrect annotation. +\begin{shell} +\$ ./a.out.e-acsl +Assertion failed at line 4 in function main. +The failing predicate is: +x == 1. +Aborted +\$ echo \$? +134 +\end{shell} +The execution aborts with a non-zero exit code (134) and an error message +indicating \eacsl annotation that has been violated. There is no output for the +valid \eacsl annotation. That is, the run of an executable generated from the +instrumented source file (i.e., \texttt{monitored\_first.i}) detects that the +second annotation in the initial program is invalid, whereas the first +annotation holds for this execution. + +Named executables can be created using the \shortopt{O} option. This is such +that a value supplied to the \shortopt{O} option is used to name the executable +generated from the original program and the executable generated from the +\eacsl-instrumented code is suffixed \texttt{.e-acsl}. + +For example, command +\begin{shell} + \$ e-acsl-gcc.sh -c -omonitored_first.i -Omonitored_first first.i +\end{shell} +names the executables generated from \texttt{first.i} and +\texttt{monitored\_first.i}: \texttt{monitored\_first} and +\texttt{monitored\_first.e-acsl} respectively. + +The \eacslgcc \shortopt{C} option allows to skip the instrumentation step and +compile a given program as if it was already instrumented by the \eacsl +plug-in. This option is useful if one makes changes to an already +instrumented source file by hand and only wants to recompile it. + +\begin{shell} + \$ e-acsl-gcc.sh -C -Omonitored_first monitored_first.i +\end{shell} + +The above command generates a single executable named +\texttt{monitored\_first.e-acsl}. This is because \texttt{monitored\_first.i} is +considered to be instrumented code and thus no original program is provided. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\subsection{Customising \framac and \gcc Invocations} + +By default \eacslgcc uses \T{frama-c} and \T{gcc} executables by looking them +up in a system's path. If either of the tools are not found the script fails +with an appropriate error message. Paths to \framac and \gcc executables can +also be passed using \shortopt{I} and \shortopt{G} options +respectively, for instance as follows: + +\begin{shell} + \$ e-acsl-gcc.sh -I/usr/local/bin/frama-c -G/usr/bin/gcc6 foo.c +\end{shell} + +Runs of \framac and \gcc issued by \eacslgcc can further be customized by using +additional flags. \framac flags can be passed using the \shortopt{F} option, +while \shortopt{l} and \shortopt{e} options allow for passing additional +pre-processor and linker flags during \gcc invocations. For example, command + +\begin{shell} + \$ e-acsl-gcc.sh -c -F"-unicode" -e"-I/bar -I/baz" foo.c +\end{shell} + +yields an instrumented program \texttt{a.out.frama.c} where ACSL formulas +are output using the UTF-8 character set. Further, during the compilation of +\texttt{a.out.frama.c} \gcc adds directories \texttt{/bar} and +\texttt{/baz} to the list of directories to be searched for header files. + +It is worth mentioning that \eacslgcc implements several convenience flags for +setting some of the \framac options. For instance, \shortopt{E} can be used to +pass additional arguments to the \framac pre-processor (see +Section~\ref{sec:eacsl-gcc:doc}). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\subsection{Verbosity Levels and Output Redirection} + +By default \eacslgcc prints the executed \framac and \gcc commands and pipes +their output to the terminal. The verbosity of \framac output can be changed +using \shortopt{v} and \shortopt{d} options used to pass values to +\shortopt{verbose} and \shortopt{debug} flags of \framac respectively. For +instance, to increase the verbosity of plug-ins but suppress the verbosity of +the \framac kernel while instrumenting \texttt{foo.c} one can use the following +command: + +\begin{shell} + \$ e-acsl-gcc.sh -v5 -F"-kernel-verbose 0" foo.c +\end{shell} + +Verbosity of the \eacslgcc output can also be reduced using the \shortopt{q} +option that suppresses any output except errors or warnings issued by \gcc, +\framac, and \eacslgcc itself. + +The output of \eacslgcc can also be redirected to a specified file using the +\shortopt{s} option. For example, the following command redirects all +output during instrumentation and compilation of \texttt{foo.c} to the +file named \texttt{/tmp/log}. + +\begin{shell} + \$ e-acsl-gcc.sh -c -s/tmp/log foo.c +\end{shell} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\subsection{Architecture Dependency} + +As pointed out in Section~\ref{sec:exec} the execution of a \C program depends +on the underlying machine architecture it is executed on. The program must be +compiled on the very same architecture (or cross-compiled for it) for the +compiler being able to generate a correct binary. + +\framac makes assumptions about the machine architecture when analyzing source +code. By default, it assumes an X86 32-bit platform, but it can be customized +through \shortopt{machdep} switch~\cite{userman}. This option is of primary +importance when using the \eacsl plug-in: it must be set to the value +corresponding to the machine architecture which the generated code will be +executed on, otherwise the generated program is likely to fail to link against +the \eacsl library. Note that the library is built using the default +machine architecture. + +One of the benefits of using the wrapper script is that it makes sure that +\framac is invoked with the correct \shortopt{machdep} option. By default +\eacslgcc uses \shortopt{machdep gcc\_x86\_64} for 64-bit architectures and +\shortopt{machdep gcc\_x86\_32} for 32-bit ones. Compiler invocations are +further passed \shortopt{m64} or \shortopt{m32} options to generate code using +64-bit or 32-bit ABI respectively. + +At the present stage of implementation \eacsl does not support generating +executables with ABI different to the default one. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\subsection{Documentation}\label{sec:eacsl-gcc:doc} + +For full up-to-date documentation of \eacslgcc see its man page: + +\begin{shell} + \$ man e-acsl-gcc.sh +\end{shell} + +Alternatively, you can also use the \shortopt{h} option of \eacslgcc: + +\begin{shell} + \$ man e-acsl-gcc.sh -h +\end{shell} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%>>> +\section{Execution Environment of the Generated Code} %<<< +\label{sec:exec-env} + +The environment in which the code is executed is not necessarily the same as +the one assumed by \framac. You should take care of that when running the \eacsl +plug-in and when compiling the generated code with \gcc. In this aspect, the +plug-in offers a few possibilities of customization. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\subsection{Runtime Errors in Annotations} +\label{sec:runtime-error} +\index{Runtime Error} + +The major difference between \acsl~\cite{acsl} and \eacsl~\cite{eacsl} +specification languages is that the logic is total in the former while it is +partial in the latter one: the semantics of a logic construct $c$ denoting a \C +expression $e$ +is undefined if $e$ leads to a runtime error and, consequently, the semantics of +any term $t$ (resp. predicate $p$) containing such a construct $c$ is +undefined as soon as $e$ has to be evaluated in order to evaluate $t$ +(resp. $p$). The \eacsl Reference Manual also states that \emph{``it is the +responsibility of each tool which interprets \eacsl to ensure that an +undefined term is never evaluated''}~\cite{eacsl}. + +Accordingly, the \eacsl plug-in prevents an undefined term from being +evaluated. If an annotation contains such a term, \eacsl will report a proper +error at runtime instead of evaluating it. + +Consider for instance the following annotated program. + +\listingname{rte.i} +\cinput{examples/rte.i} + +The terms and predicates containing the modulo `\%' in the \T{assumes} clause +are undefined in the context of the \T{main} function call since the second +argument is equal to 0. However, we can generate an instrumented code and +compile it using the following command: + +\begin{shell} +\$ e-acsl-gcc.sh -c -omonitored_rte.i -Orte rte.i +\end{shell} + +Now, when \T{rte.e-acsl} is executed, you get the following output indicating +that your function contract is invalid because it contains a division by zero. + +\begin{shell} +\$ ./rte.e-acsl +RTE failed at line 5 in function is_dividable. +The failing predicate is: +division_by_zero: y != 0. +Aborted +\end{shell} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\subsection{Libc}\index{Libc} + +By default, \framac uses its own standard library (\emph{aka} libc) instead of +the one of your system. If you do not want to use it, you have to add the option +\shortopt{no-framac-stdlib}\optionidx{-}{framac-stdlib} to the \framac command +line. + +It might be particularly useful in one of the following contexts: +\begin{itemize} +\item several libc functions used by the analyzed program are still not defined + in the \framac libc; or +\item your system libc and the \framac libc mismatch about several function + types (for instance, your system libc is not 100\% POSIX compliant); or +\item several \framac lib functions get a contract and you are not interested in + verifying them (for instance, only checking undefine behaviors matters). +\end{itemize} + +\begin{important} +Notably, \eacslgcc disables \framac libc by default. This is because most of +its functions are annotated with \eacsl contracts and generating code for +these contracts results in additional runtime overheads. To enforce default +\framac contracts with \eacslgcc you can pass \shortopt{L} option to the wrapper +script. +\end{important} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\subsection{Integers} +\label{sec:integers} +\index{GMP} + +\eacsl uses an \texttt{integer}\codeidx{integer} type corresponding to +mathematical integers which does not fit in any integral \C type. To circumvent +this issue, \eacsl uses the \gmp library\footnote{\url{http://gmplib.org}}. +Thus, even if \eacsl does its best to use standard integral types instead of +\gmp~\cite{sac13,jfla15}, it may generate such integers from time to time. It is +notably the case if your program contains \lstinline|long long|, either signed +or unsigned. + +Consider for instance the following program. + +\listingname{gmp.i} +\cinput{examples/gmp.i} + +Even on a 64-bit machine, it is not possible to compute the assertion with a +standard \C type. In this case, the \eacsl plug-in generates \gmp code. Note +that E-ACSL library already includes \gmp, thus no additional arguments need to +be provided. We can generate and execute the instrumented code as usual via +the following command: + +\begin{shell} +\$ e-acsl-gcc.sh -omonitored_gmp.i -Ogmp gmp.i +\$ ./gmp.e-acsl +\end{shell} + +Since the assertion is valid, there is no output in this case. + +Note that it is possible to use \gmp arithmetic in all cases (even if not +required). This option is controlled through \shortopt{g} switch of \eacslgcc +which passes the \shortopt{e-acsl-gmp-only} option to the \eacsl +plug-in. However it could slow down the execution of the instrumented program +significantly. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\subsection{Memory-related Annotations} +\label{sec:memory} + +The \eacsl plug-in handles memory-related annotations such as +\lstinline|\valid|. Consider for instance the following program. + +\listingname{valid.c} +\cinput{examples/valid.c} + +Even though the first annotation holds, the second annotation (labelled +\I{freed}) is invalid. This is because at the point of its execution memory +allocated via \texttt{malloc} has been deallocated and \T{x} is a stale pointer +referencing unallocated memory. The execution of the instrumented program thus +reports the violation of the second annotation: + +\begin{shell} +\$ e-acsl-gcc.sh -c -Ovalid valid.c +\$ ./valid.e-acsl +Assertion failed at line 11 in function main. +The failing predicate is: +freed: \valid(x). +Aborted +\end{shell} + +To check memory-related predicates (such as \lstinline|\valid|) \eacsl tracks +memory allocated by a program at runtime. \eacsl records memory blocks in a +meta-storage tracking each block's boundaries (i.e., its base address and +length), per-byte initialization and the notion of an address being freeable +(i.e., whether it can be safely passed to the \texttt{free} function). During +an execution of the instrumented program code injected by \eacsl +transformations queries the meta-storage to identify properties of an address +in question. For instance, during the execution of the above program the +monitor injected by \eacsl first records information about the memory block +allocated via a call to \texttt{malloc}. Further, during the execution of the +first assertion the monitor queries the meta-storage about the address of the +memory location pointed to by \texttt{x}. Since the location belongs to an +allocated memory block, the meta-storage identifies it as belonging to the +tracked allocation. Consequently, the assertion evaluates to true and the +monitors allows the execution to continue. The second assertion, however, +fails. This is because the block pointed to by \T{x} has been removed from the +meta-storage by a call to \T{free}, and thus a meta-storage query identifies +location \T{x} as belonging unallocated memory space. + +\subsubsection{\eacsl Memory Models} + +Memory tracking implemented by the \eacsl library comes in two flavours dubbed +\I{bittree-based} and \I{segment-based} memory models. With the bittree-based +model meta-storage is implemented as a compact prefix trie called Patricia +trie~\cite{rv13}, whereas segment-based memory model +\footnote{Segment-based model of \eacsl has not yet appeared in the literature.} +is based on shadow memory~\cite{pldi16}. The functionality of the provided +memory models is equivalent, however they differ in performance. We further +discuss performance considerations. + +The \eacsl models allocate heap memory using a customized version of the +\dlmalloc\footnote{\url{http://dlmalloc.net/}} memory allocator replacing +system-wide \T{malloc} and similar functions (e.g., \T{calloc} or \T{free}). + +At the level of \eacslgcc you can choose between different memory models using +the \shortopt{m} switch followed by the name of the memory model to link +against. For instance, command +\begin{shell} +\$ e-acsl-gcc.sh -mbittree -c -Ovalid valid.c +\end{shell} +links a program generated from \T{valid.c} against the library implementing the +bittree-based memory model, whereas the following invocation uses shadow-based +tracking: +\begin{shell} +\$ e-acsl-gcc.sh -msegment -c -Ovalid valid.c +\end{shell} +It is also possible to generate executables using both models as follows: +\begin{shell} +\$ e-acsl-gcc.sh -msegment,bittree -c -Ovalid valid.c +\end{shell} +In this case, \eacslgcc produces 3 executables: \T{valid}, +\T{valid.e-acsl-segment} and \T{valid.e-acsl-bittree} corresponding to an +executable generated from the original source code, and the executables +generated from the \eacsl-instrumented sources linked against +segment-based and bittree-based memory models. + +Unless specified, \eacsl defaults to the segment-based memory model. + +\subsubsection{Performance Considerations} +\label{sec:perf} + +As pointed out in the previous section the functionalities provided by both +segment-based and bittree-based memory models are equivalent but differ in +performance. The bittree-based model uses compact memory representation of +metadata. The segment-based model on the other hand uses significantly more +memory. You can expect over 2x times memory overheads when using it. However It +is often an order of magnitude faster than the bittree-based +model~\cite{pldi16}. + +%[Need ref here with comparison of the performance. Ideally a reference to the PLDI paper]. + +\subsubsection{Maximized Memory Tracking} + +By default \eacsl uses static analysis to reduce instrumentation and therefore +runtime and memory overheads~\cite{scp16}. With respect to memory tracking this +means that +\eacsl may omit recording memory blocks irrelevant for runtime analysis. It +is, however, still possible to systematically instrument the code for handling +potential memory-related annotations even when it is not required. This +feature can be enabled using the \shortopt{M} switch of \eacslgcc or +\shortopt{e-acsl-full-mmodel} option of the \eacsl plug-in. + +\begin{important} +The above-mentioned static analysis is probably the less robust part of \eacsl +for the time being. When handling a large piece of code, it might be necessary +to deactivate it and systematically instrument the code as explained above. +\end{important} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% \subsection{Debug Libraries} +%% \label{sec:runtime-debug} + +%% \eacsl memory models mentioned in Section~\ref{sec:memory} are optimized for +%% performance (via \shortopt{-O2} compiler flag). An \eacsl installation also +%% provides unoptimized versions of these libraries (suffixed \T{-dbg.a}) aimed at +%% being used during debugging. + +%% The main difference between unoptimized (debug) and optimized (production) +%% libraries is that debug libraries include assertions validating the correctness +%% of the RTL itself. For instance, during memory tracking such assertions ensure +%% that during a run of a program all tracked memory blocks are disjoint. + +%% Consider the following program that violates an annotation +%% in function \T{foo} via a call \T{bar(p+1)} in the main function: + +%% \listingname{rte\_debug.i} +%% \cinput{examples/rte_debug.i} + +%% A monitored executable linked against a debug version of \eacsl RTL +%% can ge generated using +%% \longopt{rt-debug} flag of \eacslgcc as follows: + +%% \begin{shell} +%% \$ e-acsl-gcc.sh --rt-debug -c -omonitored_rte_debug.c -Orte_debug rte_debug.i +%% \end{shell} + +%% A run of the monitored executable shows violation of the \eacsl annotation. +%% \begin{shell} +%% \$ rte_debug.e-acsl +%% Assertion failed at line 2 in function foo. +%% The failing predicate is: +%% \valid(p). +%% /** Backtrace **************************/ +%% trace at e_acsl_trace.h:45 +%% - exec_abort at e_acsl_assert.h:58 +%% - runtime_assert at e_acsl_assert.h:93 +%% - foo at monitored_rte_debug.c:92 +%% - bar at monitored_rte_debug.c:102 +%% - main at monitored_rte_debug.c:119 +%% /***************************************/ +%% Aborted +%% \end{shell} + +%% A run of an executable linked against an unoptimized RTL shows a stack trace on +%% the instrumented program saved to \T{monitored\_rte\_debug.c}. In the example +%% above calls to \T{exec\_abort} and \T{runtime\_assert} belong to the \eacsl +%% RTL, whereas calls to \T{foo}, \T{bar} and \T{main} belong to the input +%% program. + +%% It should be noted that because debug versions of \eacsl RTL are compiled +%% without compile-time optimizations and execute additional assertions the +%% runtime overheads of the instrumented programs linked against the debug +%% versions of \eacsl RTL can be up to 10 times greater than those linked against +%% the production versions. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\subsection{Runtime Monitor Behavior} +\label{sec:monitor-behavior} + +When a predicate is checked at runtime, function +\texttt{\_\_e\_acsl\_assert}\codeidxdef{e\_acsl\_assert} is called. By default +this function does nothing if the predicate is valid, and prints an error +message and aborts the execution (by raising an \texttt{ABORT} signal via a call +to the \C function \texttt{abort}) if the predicate is invalid. If \eacsl +detects that its verdict is not trustable (see +Section~\ref{sec:partial-instrumentation}), it prints a warning with its guess +and continues the execution. + +The default behavior of \texttt{\_\_e\_acsl\_assert}\codeidxdef{e\_acsl\_assert} +can be altered using \longopt{fail-with-code=CODE} option of \eacslgcc +that uses \texttt{exit(CODE)} instead of \texttt{abort}. + +For instance, the program generated using the following command +exits with code \texttt{5} on a predicate violation. +\begin{shell} + \$ e-acsl-gcc.sh -c --fail-with-code=5 foo.c +\end{shell} + +Forceful termination of a monitored program can be disabled using +\longopt{keep-going} option. If specified, \eacslgcc generates code that +reports each property violated at runtime but allows the monitored program to +continue execution. \longopt{keep-going} should be used with caution: +such unterminated executions may lead to incorrect verification results. + +\eacslgcc also provides a way to use an alternative definition of +\texttt{\_\_e\_acsl\_assert}\codeidxdef{e\_acsl\_assert}. + +Custom implementation of \texttt{\_\_e\_acsl\_assert}\codeidxdef{e\_acsl\_assert} +should be provided in a separate \C (or object file) and respect the +following signature: + +\cinput{examples/assert_sign.c} + +Additionally, it may depends on the global variable +\texttt{\_\_e\_acsl\_sound\_verdict}\codeidxdef{e\_acsl\_sound\_verdict}. This +variable of type \texttt{int} is set to \texttt{0} as soon as the verdict +provided by \eacsl is not trustable anymore (see +Section~\ref{sec:partial-instrumentation}). + +Below is an example which prints the validity status of each property but never +exits. + +\listingname{my\_assert.c} +\cinput{examples/my_assert.c} + +A monitored program that uses custom definition of +\texttt{\_\_e\_acsl\_assert}\codeidxdef{e\_acsl\_assert} can then be generated +as follows using \longopt{external-assert} option of \eacslgcc to replace the +default implementation of \texttt{\_\_e\_acsl\_assert}\codeidxdef{e\_acsl\_assert} +with the customized one specified in \texttt{my\_assert.c} + +\begin{shell} +\$ e-acsl-gcc.sh -c -X first.i -Ofirst --external-assert=my_assert.c +\$ ./first.e-acsl +Assertion at line 3 in function main is valid (trustable). +The verified predicate was: `x == 0'. +Assertion at line 4 in function main is invalid (trustable). +The verified predicate was: `x == 1'. +\end{shell} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%>>> +\section{Additional Verifications} % <<< + +In addition to checking annotations at runtime, \eacsl is able to detect a few +errors at runtime. + +\subsection{Format String Vulnerabilities} +\index{Format String Vulnerabilities} + +Whenever option \longopt{validate-format-strings} of \eacslgcc is set, \eacsl +detects format-string vulnerabilities in \texttt{printf}-like function. Below is +an example which incorrectly tries to print a string through a \texttt{\%d} +format. + +\listingname{printf.c} +\cinput{examples/printf.c} + +This error can be detected by \eacsl as follows. + +\begin{shell} +\$ e-acsl-gcc.sh -Oprintf -c --validate-format-strings printf.c +\$ ./printf.e-acsl +printf: directive 1 ('%d') expects argument of type 'int' but the corresponding +argument has type 'char*' +Abort +\end{shell} + +\subsection{Incorrect Usage of Libc Functions} +\index{Libc} + +Whenever option \longopt{libc-replacements} of \eacslgcc is set, \eacsl is +able to detect incorrect usage of the following libc functions: +\begin{itemize} +\item \texttt{memcmp} +\item \texttt{memcpy} +\item \texttt{memmove} +\item \texttt{memset} +\item \texttt{strcat} +\item \texttt{strncat} +\item \texttt{strcmp} +\item \texttt{strcpy} +\item \texttt{strncpy} +\item \texttt{strlen} +\end{itemize} + +For instance, the program below incorrectly uses \texttt{strcpy} because the +destination string should contain at least 7 \texttt{char} (and not only 6). + +\listingname{strcpy.c} +\cinput{examples/strcpy.c} + +This error can be reported by \eacsl as follows. + +\begin{shell} +\$ e-acsl-gcc.sh -Ostrcpy -c --libc-replacements strcpy.c +\$ ./strcpy.e-acsl +strlen: insufficient space in destination string, at least 7 bytes required +Abort +\end{shell} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%>>> +\section{Incomplete Verification} % <<< +\label{sec:incomplete} + +Executing a \C program requires to have a complete application. However, the +\eacsl plug-in does not necessarily require to have it to generate the +instrumented code. It is still possible to instrument a partial program with no +entry point (Section~\ref{sec:no-main}) or in which some functions remain +undefined (Section~\ref{sec:no-code}). + +It is also possible to partially instrument an application in order to reduce +the runtime overhead. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\subsection{Programs with no Main Function} +\label{sec:no-main} +\index{Program!Without main} + +The \eacsl plug-in can instrument a program without the \T{main} function. +Consider for instance the following annotated program without \texttt{main}. + +\listingname{no\_main.i} +\cinput{examples/no_main.i} + +The instrumented code is generated as usual, even though you get an additional +warning. +\begin{shell} +\$ e-acsl-gcc.sh no_main.i -omonitored_no_main.i +<skip preprocessing command line> +[e-acsl] beginning translation. +[e-acsl] warning: cannot find entry point `main'. + Please use option `-main' for specifying a valid entry point. + The generated program may miss memory instrumentation. + if there are memory-related annotations. +[e-acsl] translation done in project "e-acsl". +\end{shell} + +This warning indicates that the instrumentation could be incorrect if the +program contains memory-related annotations (see +Section~\ref{sec:limits:no-main}). That is not the case here, so you can +safely ignore it. Now, it is possible to compile the generated code with a \C +compiler in a standard way, and even link it against additional files such as +the following: + +\listingname{main.c} +\cinput{examples/main.c} + +\begin{shell} +\$ e-acsl-gcc.sh -C monitored_no_main.i main.c -Owith_main +\$ ./with_main.e-acsl +x = 65536 +\end{shell} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\subsection{Undefined Functions} +\label{sec:no-code} +\index{Function!Undefined} + +Similar to the above section \eacsl is capable of instrumenting a program which +has definitions of arbitrary functions missing. Consider for instance the +following annotated program for which the implementation of the function +\texttt{my\_pow} is not provided. + +\listingname{no\_code.c} +\cinput{examples/no_code.c} + +The instrumented code is generated as usual, even though you get an additional +warning. +\begin{shell} +\$ e-acsl-gcc.sh -omonitored_no_code.i no_code.c +[e-acsl] beginning translation. +[e-acsl] warning: annotating undefined function `my_pow': + the generated program may miss memory instrumentation + if there are memory-related annotations. +no_code.c:9:[kernel] warning: No code nor implicit assigns clause for function my_pow, +generating default assigns from the prototype +[e-acsl] translation done in project "e-acsl". +\end{shell} + +Similar to the previous Section the warning indicates that the instrumentation +could be incorrect if the program contains memory-related annotations (see +Section~\ref{sec:limits:no-code}). That is still not the case here, so you can +safely ignore it. + +\listingname{pow.i} +\cinput{examples/pow.i} + +Similar to the example shown in the previous section you can generate the +executable by providing definition of \T{my\_pow}. + +\begin{shell} +\$ e-acsl-gcc.sh -C -Ono_code pow.i monitored_no_code.i +\$ ./no_code.e-acsl +Postcondition failed at line 5 in function my_pow. +The failing predicate is: +\old(n % 2 == 0) ==> \result >= 1. +Aborted +\end{shell} + +The execution of the corresponding binary fails at runtime: actually, our +implementation of the function \texttt{my\_pow} overflows in case of large +exponentiations. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\subsection{Providing a White List of Functions} +\label{sec:white-list} +\index{Function!White List} + +By default, the E-ACSL plug-in generates code for checking at runtime all the +annotations of the analyzed files. Yet, it is possible to handle only +annotations of a given set of functions through the option +\shortopt{e-acsl-functions}. This way, no runtime check is generated for +annotations of all the other functions. It allows the user to focus on a +particular part of the code, while reducing the global runtime overhead. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\subsection{Partial Instrumentation (\experimentalword)} +\label{sec:partial-instrumentation} +\index{Function!Not Instrumented} + +\experimental{Partial instrumentation} + +By default, the E-ACSL plug-in generates all the necessary pieces of code for +checking at runtime the provided annotations. This amount of instrumentation +may be quite large. It is possible to reduce it by manually specifying the set +of functions to be instrumented through the option \shortopt{e-acsl-instrument}. + +This way, contrary to the option \shortopt{e-acsl-functions}, all the +annotations are still checked at runtime. However, since less code is generated, +the generated program usually runs faster. However, it may lead to unsound +verdicts if it would have been necessary to generate the instrumentation for one +of the uninstrumented functions. + +A typical usage of this option consists in specifying the set of functions to be +\emph{not} instrumented. For instance, to instrument all functions except +functions \texttt{f} and \texttt{g}, you should specify +\texttt{-e-acsl-instrument=+@all,-f,-g}. + +Consider the following example in which all assertions are valid. + +\listingname{partial.i} +\cinput{examples/instrument.i} + +One can ask to not instrument function \texttt{g} (\emph{i.e.} to instrument +only functions \texttt{f} and \texttt{main}) through the following command. +\begin{shell} +\$ e-acsl-gcc.sh \ + -c --oexec-e-acsl partial.out \ + --e-acsl-extra="-e-acsl-instrument=+@all,-g"' \ + partial.i +\end{shell} + +Therefore, running the generated executable \texttt{partial.out} leads to the +following verdicts. +\begin{shell} +\$ ./partial.out +warning: no sound verdict (guess: ok) at line 16 (function main). +The considered predicate is: +\initialized(&t[1]). +warning: no sound verdict (guess: FAIL) at line 17 (function main). +The considered predicate is: +\initialized(&t[2]). +\end{shell} + +First, there is no message for the first assertion about the initialization of +\texttt{\&t[0]}, meaning that this assertion is silently checked as valid by +\eacsl (see Section~\ref{sec:monitor-behavior}). It was made possible because of +the complete instrumentation of functions \texttt{f} and \texttt{main}. + +Second, since function \texttt{g} was not instrumented, no sound verdict may be +provided after executing it. It leads to the printed warnings for the two last +assertions. The indicated guesses (\texttt{ok} for the first assertion and +\texttt{FAIL} for the second one) are the verdicts computed by \eacsl. They can +be trusted if and only if the \eacsl instrumentation is not necessary for +validating the considered annotations. In that particular case, it is not +true. For instance, the second guess is incorrect since \texttt{\&t[2]} is +actually initialized through function \texttt{g}. \eacsl missed it since this +function is not instrumented.. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%>>> +\section{Combining E-ACSL with Other Plug-ins} % <<< +\label{sec:combine} + +As the \eacsl plug-in generates a new \framac project, it is easy to run any +plug-in on the generated program, either in the same \framac session (thanks to +the option \shortopt{then} or through the GUI), or in another one. The only +issue might be that, depending on the plug-in, the analysis may be imperfect if +the generated program uses \gmp or the dedicated memory library: both make +intensive use of dynamic structures which are usually difficult to handle by +analysis tools. + +Another way to combine \eacsl with other plug-ins is to run \eacsl last. For +instance, the \rte plug-in~\cite{rte} may be used to generate annotations +corresponding to runtime errors. Then the \eacsl plug-in may generate an +instrumented program to verify that there are no such runtime errors during the +execution of the program. + +Consider the following program. + +\listingname{combine.i} +\cinput{examples/combine.i} +To check at runtime that this program does not perform any runtime error (which +are potential overflows in this case), just do: + +\begin{shell} +\$ frama-c -rte combine.i -then -e-acsl -then-last -print + -ocode monitored_combine.i +\$ e-acsl-gcc.sh -C -Ocombine monitored_combine.i +\$ ./combine. +\end{shell} + +Automatic assertion generation can also be enabled via \eacslgcc directly via +the following command: +\begin{shell} +\$ e-acsl-gcc.sh -c -Ocombine -omonitored_combine.i --rte=all +\end{shell} + +Note the use of \eacslgcc \longopt{rte} option which asks \framac to combine +\eacsl with \rte plug-in. This plug-in automatically instruments the input +program with runtime +assertions before running the \eacsl plug-in on it. \longopt{rte} option of +\eacslgcc also accepts a comma-separated list of arguments indicating the types +of assertions to generate. Consult the \eacslgcc man page for a detailed +list of arguments accepted by \longopt{rte}. + +The present implementation of \eacslgcc does not fully support combining \eacsl +with other \framac plug-ins. However it is still possible to instrument programs +with \eacsl directly and use \eacslgcc to compile the generated code. + +If you run the \eacsl plug-in after another one, it first generates +a new temporary project in which it links the analyzed program against its own +library in order to generate the \framac internal representation of the \C +program (\emph{aka} AST), as explained in Section~\ref{sec:run}. Consequently, +even if the \eacsl plug-in keeps the maximum amount of information, the results +of already executed analyzers (such as validity status of annotations) are not +known in this new project. + +\begin{important} +If you want to keep results of former analysis, you have to set the option +\shortopt{e-acsl-prepare} when the first analysis is asked for. The standard +example is running \eacsl after \Eva\index{Eva}: in such a case, +\shortopt{e-acsl-prepare} must be provided together with the \Eva's +\shortopt{val} option. +\end{important} + +In this context, the \eacsl plug-in does not generate code for annotations +proven valid by another plug-in, except if you explicitly set the option +\shortopt{e-acsl-valid}. For instance, \Eva~\cite{eva} is able to +prove that there is no potential overflow in the previous program, so the \eacsl +plug-in does not generate additional code for checking them if you run the +following command. +\begin{shell} +\$ frama-c -e-acsl-prepare -rte combine.i -then -val -then -e-acsl \ + -then-last -print -ocode monitored_combine.i +\end{shell} +The additional code will be generated with one of the two following commands. +\begin{shell} +\$ frama-c -e-acsl-prepare -rte combine.i -then -val -then -e-acsl \ + -e-acsl-valid -then-last -print -ocode monitored_combine.i +\$ frama-c -rte combine.i -then -val -then -e-acsl \ + -then-last -print -ocode monitored_combine.i +\end{shell} +In the first case, that is because it is explicitly required by the option +\shortopt{e-acsl-valid} while, in the second case, that is because the option +\shortopt{e-acsl-prepare} is not provided on the command line which results in +the fact that the result of the value analysis are unknown when the \eacsl +plug-in is running. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%>>> +\section{Customization} % <<< +\label{sec:custom} + +There are several ways to customize the \eacsl plug-in. + +First, the name of the generated project -- which is \texttt{e-acsl} by default +-- may be changed by setting the option \shortopt{e-acsl-project} option of the +\eacsl plug-in. While there is not direct support for this option in \eacslgcc +you can pass it using \shortopt{F} switch: + +\listingname{check.i} +\cinput{examples/check.i} + +\begin{shell} +\$ e-acsl-gcc.sh -F"-e-acsl-project foobar" check.i +<skip preprocessing commands> +[e-acsl] beginning translation. +check.i:4:[e-acsl] warning: E-ACSL construct `right shift' is not yet supported. + Ignoring annotation. +[e-acsl] translation done in project "foobar". +\end{shell} + +Further, the \eacsl plug-in option \shortopt{e-acsl-check} does not generate a +new project but verifies that each annotation is translatable. Then it produces +a summary as shown in the following example (left or right shifts in annotations +are not yet supported by the \eacsl plug-in~\cite{eacsl-implem}). + +\begin{shell} +\$ frama-c -e-acsl-check check.i +<skip preprocessing commands> +check.i:4:[e-acsl] warning: E-ACSL construct `left/right shift' is not yet supported. + Ignoring annotation. +[e-acsl] 0 annotation was ignored, being untypable. +[e-acsl] 1 annotation was ignored, being unsupported. +\end{shell} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%>>> +\section{Verbosity Policy} % <<< +\label{sec:verbose} + +By default, \eacsl does not provide much information when it is running. Mainly, +it prints a message when it begins the translation, and another one when the +translation is done. It may also display warnings when something requires the +attention of the user, for instance if it is not able to translate an +annotation. Such information is usually enough but, in some cases, you might +want to get additional control on what is displayed. As quite usual with +\framac plug-ins, \eacsl offers two different ways to do this: the verbosity +level which indicates the \emph{amount} of information to display, and the +message categories which indicate the \emph{kind} of information to display. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\subsection{Verbosity Level} + +The amount of information displayed by the \eacsl plug-in is settable by the +option \shortopt{e-acsl-verbose}. It is 1 by default. Below is indicated +which information is displayed according to the verbosing level. The level $n$ +also displays the information of all the lower levels. + +\begin{center} +\begin{tabular}{|l|l|} +\hline +\shortopt{e-acsl-verbose 0}& only warnings and errors\\ +\hline +\shortopt{e-acsl-verbose 1}& beginning and ending of the translation\\ +\hline +\shortopt{e-acsl-verbose 2}& different parts of the translation and + functions-related information\\ +\hline +\shortopt{e-acsl-verbose 3}& predicates- and statements-related information\\ +\hline +\shortopt{e-acsl-verbose 4}& terms- and expressions-related information +\\ +\hline +\end{tabular} +\end{center} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\subsection{Message Categories} + +The kind of information to display is settable by the option +\shortopt{e-acsl-msg-key} (and unsettable by the option +\shortopt{e-acsl-msg-key-unset}). The different keys refer to different +parts of the translation, as detailed below. + +\begin{center} +\begin{tabular}{|l|l|} +\hline +analysis & minimization of the instrumentation for memory-related annotation +(section~\ref{sec:memory}) \\ +\hline +duplication & duplication of functions with contracts +(section~\ref{sec:no-code}) \\ +\hline +translation & translation of an annotation into \C code\\ +\hline +typing & minimization of the instrumentation for integers +(section~\ref{sec:integers}) \\ +\hline +\end{tabular} +\end{center} +% >>> diff --git a/src/plugins/e-acsl/headers/close-source/CEA_LGPL_OR_PROPRIETARY.E_ACSL b/src/plugins/e-acsl/headers/close-source/CEA_LGPL_OR_PROPRIETARY.E_ACSL new file mode 100644 index 0000000000000000000000000000000000000000..7387695e04be306cbd81a9eeb6ccf17efe3b3696 --- /dev/null +++ b/src/plugins/e-acsl/headers/close-source/CEA_LGPL_OR_PROPRIETARY.E_ACSL @@ -0,0 +1,10 @@ + +This file is part of the Frama-C's E-ACSL plug-in. + +Copyright (C) 2012-2018 + CEA (Commissariat à l'énergie atomique et aux énergies + alternatives) + +All rights reserved. +Contact CEA LIST for licensing. + diff --git a/src/plugins/e-acsl/headers/close-source/MODIFIED_DLMALLOC b/src/plugins/e-acsl/headers/close-source/MODIFIED_DLMALLOC new file mode 100644 index 0000000000000000000000000000000000000000..216b3e540f1f03b186ef2909330729fc54645ba3 --- /dev/null +++ b/src/plugins/e-acsl/headers/close-source/MODIFIED_DLMALLOC @@ -0,0 +1,14 @@ + +This is a version (aka dlmalloc) of malloc/free/realloc written by +Doug Lea and released to the public domain, as explained at +http://creativecommons.org/publicdomain/zero/1.0/ Send questions, +comments, complaints, performance data, etc to dl@cs.oswego.edu + +Version 2.8.6 Wed Aug 29 06:57:58 2012 Doug Lea +Note: There may be an updated version of this malloc obtainable at + ftp://gee.cs.oswego.edu/pub/misc/malloc.c + Check before installing! + +File modified by CEA (Commissariat à l'énergie atomique et aux + énergies alternatives). + diff --git a/src/plugins/e-acsl/headers/close-source/MODIFIED_LIB_GMP b/src/plugins/e-acsl/headers/close-source/MODIFIED_LIB_GMP new file mode 100644 index 0000000000000000000000000000000000000000..6ca6c4f658f0705c1a491e350a80421c323c226d --- /dev/null +++ b/src/plugins/e-acsl/headers/close-source/MODIFIED_LIB_GMP @@ -0,0 +1,36 @@ + + mini-gmp, a minimalistic implementation of a GNU GMP subset. + + Contributed to the GNU project by Niels Möller + +Copyright 1991-1997, 1999-2015 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of either: + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at your + option) any later version. + +or + + * the GNU General Public License as published by the Free Software + Foundation; either version 2 of the License, or (at your option) any + later version. + +or both in parallel, as here. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received copies of the GNU General Public License and the +GNU Lesser General Public License along with the GNU MP Library. If not, +see https://www.gnu.org/licenses/. + +File modified by CEA (Commissariat à l'énergie atomique et aux + énergies alternatives). + diff --git a/src/plugins/e-acsl/headers/close-source/MODIFIED_SPARETIMELABS b/src/plugins/e-acsl/headers/close-source/MODIFIED_SPARETIMELABS new file mode 100644 index 0000000000000000000000000000000000000000..98f92575c04e48b1f47c95d55caa89e6b30d1ee1 --- /dev/null +++ b/src/plugins/e-acsl/headers/close-source/MODIFIED_SPARETIMELABS @@ -0,0 +1,35 @@ + +Copyright (c) 2004,2012 Kustaa Nyholm / SpareTimeLabs + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +Neither the name of the Kustaa Nyholm or SpareTimeLabs nor the names +of its contributors may be used to endorse or promote products derived +from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +File modified by CEA (Commissariat à l'énergie atomique et aux + énergies alternatives). + diff --git a/src/plugins/e-acsl/headers/header_spec.txt b/src/plugins/e-acsl/headers/header_spec.txt new file mode 100644 index 0000000000000000000000000000000000000000..46910169ea99df784d6b3c149c3bc41fc022f526 --- /dev/null +++ b/src/plugins/e-acsl/headers/header_spec.txt @@ -0,0 +1,103 @@ +E_ACSL.mli: CEA_LGPL_OR_PROPRIETARY.E_ACSL +INSTALL: .ignore +Makefile.in: CEA_LGPL_OR_PROPRIETARY.E_ACSL +README: .ignore +VERSION: .ignore +configure.ac: CEA_LGPL_OR_PROPRIETARY.E_ACSL +contrib/libdlmalloc/dlmalloc.c: MODIFIED_DLMALLOC +doc/Changelog: .ignore +doc/doxygen/doxygen.cfg.in: .ignore +license/CEA_LGPL: .ignore +license/LGPLv2.1: .ignore +license/SPARETIMELABS: .ignore +license/headache_config.txt: .ignore +man/e-acsl-gcc.sh.1: CEA_LGPL_OR_PROPRIETARY.E_ACSL +scripts/e-acsl-gcc.sh: CEA_LGPL_OR_PROPRIETARY.E_ACSL +scripts/testrun.sh: CEA_LGPL_OR_PROPRIETARY.E_ACSL +share/e-acsl/bittree_model/e_acsl_bittree.h: CEA_LGPL_OR_PROPRIETARY.E_ACSL +share/e-acsl/bittree_model/e_acsl_bittree_api.h: CEA_LGPL_OR_PROPRIETARY.E_ACSL +share/e-acsl/bittree_model/e_acsl_bittree_mmodel.c: CEA_LGPL_OR_PROPRIETARY.E_ACSL +share/e-acsl/e_acsl.h: CEA_LGPL_OR_PROPRIETARY.E_ACSL +share/e-acsl/e_acsl_alias.h: CEA_LGPL_OR_PROPRIETARY.E_ACSL +share/e-acsl/e_acsl_assert.h: CEA_LGPL_OR_PROPRIETARY.E_ACSL +share/e-acsl/e_acsl_bits.h: CEA_LGPL_OR_PROPRIETARY.E_ACSL +share/e-acsl/e_acsl_debug.h: CEA_LGPL_OR_PROPRIETARY.E_ACSL +share/e-acsl/e_acsl_floating_point.h: CEA_LGPL_OR_PROPRIETARY.E_ACSL +share/e-acsl/e_acsl_format.h: CEA_LGPL_OR_PROPRIETARY.E_ACSL +share/e-acsl/e_acsl_gmp_api.h: CEA_LGPL_OR_PROPRIETARY.E_ACSL +share/e-acsl/e_acsl_leak.h: CEA_LGPL_OR_PROPRIETARY.E_ACSL +share/e-acsl/e_acsl_libc_replacements.h: CEA_LGPL_OR_PROPRIETARY.E_ACSL +share/e-acsl/e_acsl_malloc.h: CEA_LGPL_OR_PROPRIETARY.E_ACSL +share/e-acsl/e_acsl_printf.h: MODIFIED_SPARETIMELABS +share/e-acsl/e_acsl_rtl.c: CEA_LGPL_OR_PROPRIETARY.E_ACSL +share/e-acsl/e_acsl_safe_locations.h: CEA_LGPL_OR_PROPRIETARY.E_ACSL +share/e-acsl/e_acsl_shexec.h: CEA_LGPL_OR_PROPRIETARY.E_ACSL +share/e-acsl/e_acsl_string.h: CEA_LGPL_OR_PROPRIETARY.E_ACSL +share/e-acsl/e_acsl_temporal.h: CEA_LGPL_OR_PROPRIETARY.E_ACSL +share/e-acsl/e_acsl_temporal_timestamp.h: CEA_LGPL_OR_PROPRIETARY.E_ACSL +share/e-acsl/e_acsl_trace.h: CEA_LGPL_OR_PROPRIETARY.E_ACSL +share/e-acsl/segment_model/e_acsl_segment_mmodel.c: CEA_LGPL_OR_PROPRIETARY.E_ACSL +share/e-acsl/segment_model/e_acsl_segment_tracking.h: CEA_LGPL_OR_PROPRIETARY.E_ACSL +share/e-acsl/segment_model/e_acsl_shadow_layout.h: CEA_LGPL_OR_PROPRIETARY.E_ACSL +src/analyses/exit_points.ml: CEA_LGPL_OR_PROPRIETARY.E_ACSL +src/analyses/exit_points.mli: CEA_LGPL_OR_PROPRIETARY.E_ACSL +src/analyses/interval.ml: CEA_LGPL_OR_PROPRIETARY.E_ACSL +src/analyses/interval.mli: CEA_LGPL_OR_PROPRIETARY.E_ACSL +src/analyses/literal_strings.ml: CEA_LGPL_OR_PROPRIETARY.E_ACSL +src/analyses/literal_strings.mli: CEA_LGPL_OR_PROPRIETARY.E_ACSL +src/analyses/lscope.ml: CEA_LGPL_OR_PROPRIETARY.E_ACSL +src/analyses/lscope.mli: CEA_LGPL_OR_PROPRIETARY.E_ACSL +src/analyses/mmodel_analysis.ml: CEA_LGPL_OR_PROPRIETARY.E_ACSL +src/analyses/mmodel_analysis.mli: CEA_LGPL_OR_PROPRIETARY.E_ACSL +src/analyses/rte.ml: CEA_LGPL_OR_PROPRIETARY.E_ACSL +src/analyses/rte.mli: CEA_LGPL_OR_PROPRIETARY.E_ACSL +src/analyses/typing.ml: CEA_LGPL_OR_PROPRIETARY.E_ACSL +src/analyses/typing.mli: CEA_LGPL_OR_PROPRIETARY.E_ACSL +src/code_generator/at_with_lscope.ml: CEA_LGPL_OR_PROPRIETARY.E_ACSL +src/code_generator/at_with_lscope.mli: CEA_LGPL_OR_PROPRIETARY.E_ACSL +src/code_generator/env.ml: CEA_LGPL_OR_PROPRIETARY.E_ACSL +src/code_generator/env.mli: CEA_LGPL_OR_PROPRIETARY.E_ACSL +src/code_generator/gmp.ml: CEA_LGPL_OR_PROPRIETARY.E_ACSL +src/code_generator/gmp.mli: CEA_LGPL_OR_PROPRIETARY.E_ACSL +src/code_generator/label.ml: CEA_LGPL_OR_PROPRIETARY.E_ACSL +src/code_generator/label.mli: CEA_LGPL_OR_PROPRIETARY.E_ACSL +src/code_generator/logic_functions.ml: CEA_LGPL_OR_PROPRIETARY.E_ACSL +src/code_generator/logic_functions.mli: CEA_LGPL_OR_PROPRIETARY.E_ACSL +src/code_generator/loops.ml: CEA_LGPL_OR_PROPRIETARY.E_ACSL +src/code_generator/loops.mli: CEA_LGPL_OR_PROPRIETARY.E_ACSL +src/code_generator/mmodel_translate.ml: CEA_LGPL_OR_PROPRIETARY.E_ACSL +src/code_generator/mmodel_translate.mli: CEA_LGPL_OR_PROPRIETARY.E_ACSL +src/code_generator/quantif.ml: CEA_LGPL_OR_PROPRIETARY.E_ACSL +src/code_generator/quantif.mli: CEA_LGPL_OR_PROPRIETARY.E_ACSL +src/code_generator/rational.ml: CEA_LGPL_OR_PROPRIETARY.E_ACSL +src/code_generator/rational.mli: CEA_LGPL_OR_PROPRIETARY.E_ACSL +src/code_generator/temporal.ml: CEA_LGPL_OR_PROPRIETARY.E_ACSL +src/code_generator/temporal.mli: CEA_LGPL_OR_PROPRIETARY.E_ACSL +src/code_generator/translate.ml: CEA_LGPL_OR_PROPRIETARY.E_ACSL +src/code_generator/translate.mli: CEA_LGPL_OR_PROPRIETARY.E_ACSL +src/code_generator/visit.ml: CEA_LGPL_OR_PROPRIETARY.E_ACSL +src/code_generator/visit.mli: CEA_LGPL_OR_PROPRIETARY.E_ACSL +src/libraries/builtins.ml: CEA_LGPL_OR_PROPRIETARY.E_ACSL +src/libraries/builtins.mli: CEA_LGPL_OR_PROPRIETARY.E_ACSL +src/libraries/error.ml: CEA_LGPL_OR_PROPRIETARY.E_ACSL +src/libraries/error.mli: CEA_LGPL_OR_PROPRIETARY.E_ACSL +src/libraries/functions.ml: CEA_LGPL_OR_PROPRIETARY.E_ACSL +src/libraries/functions.mli: CEA_LGPL_OR_PROPRIETARY.E_ACSL +src/libraries/gmp_types.ml: CEA_LGPL_OR_PROPRIETARY.E_ACSL +src/libraries/gmp_types.mli: CEA_LGPL_OR_PROPRIETARY.E_ACSL +src/libraries/misc.ml: CEA_LGPL_OR_PROPRIETARY.E_ACSL +src/libraries/misc.mli: CEA_LGPL_OR_PROPRIETARY.E_ACSL +src/libraries/varname.ml: CEA_LGPL_OR_PROPRIETARY.E_ACSL +src/libraries/varname.mli: CEA_LGPL_OR_PROPRIETARY.E_ACSL +src/local_config.mli: CEA_LGPL_OR_PROPRIETARY.E_ACSL +src/main.ml: CEA_LGPL_OR_PROPRIETARY.E_ACSL +src/options.ml: CEA_LGPL_OR_PROPRIETARY.E_ACSL +src/options.mli: CEA_LGPL_OR_PROPRIETARY.E_ACSL +src/project_initializer/dup_functions.ml: CEA_LGPL_OR_PROPRIETARY.E_ACSL +src/project_initializer/dup_functions.mli: CEA_LGPL_OR_PROPRIETARY.E_ACSL +src/project_initializer/keep_status.ml: CEA_LGPL_OR_PROPRIETARY.E_ACSL +src/project_initializer/keep_status.mli: CEA_LGPL_OR_PROPRIETARY.E_ACSL +src/project_initializer/prepare_ast.ml: CEA_LGPL_OR_PROPRIETARY.E_ACSL +src/project_initializer/prepare_ast.mli: CEA_LGPL_OR_PROPRIETARY.E_ACSL +tests/print.ml: CEA_LGPL_OR_PROPRIETARY.E_ACSL +tests/test_config.in: .ignore diff --git a/src/plugins/e-acsl/headers/open-source/CEA_LGPL_OR_PROPRIETARY.E_ACSL b/src/plugins/e-acsl/headers/open-source/CEA_LGPL_OR_PROPRIETARY.E_ACSL new file mode 100644 index 0000000000000000000000000000000000000000..c081974e6b385f65f99272b11af814bbd41b628d --- /dev/null +++ b/src/plugins/e-acsl/headers/open-source/CEA_LGPL_OR_PROPRIETARY.E_ACSL @@ -0,0 +1,19 @@ + +This file is part of the Frama-C's E-ACSL plug-in. + +Copyright (C) 2012-2018 + CEA (Commissariat à l'énergie atomique et aux énergies + alternatives) + +you can redistribute it and/or modify it under the terms of the GNU +Lesser General Public License as published by the Free Software +Foundation, version 2.1. + +It is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +See the GNU Lesser General Public License version 2.1 +for more details (enclosed in the file licenses/LGPLv2.1). + diff --git a/src/plugins/e-acsl/headers/open-source/MODIFIED_DLMALLOC b/src/plugins/e-acsl/headers/open-source/MODIFIED_DLMALLOC new file mode 100644 index 0000000000000000000000000000000000000000..216b3e540f1f03b186ef2909330729fc54645ba3 --- /dev/null +++ b/src/plugins/e-acsl/headers/open-source/MODIFIED_DLMALLOC @@ -0,0 +1,14 @@ + +This is a version (aka dlmalloc) of malloc/free/realloc written by +Doug Lea and released to the public domain, as explained at +http://creativecommons.org/publicdomain/zero/1.0/ Send questions, +comments, complaints, performance data, etc to dl@cs.oswego.edu + +Version 2.8.6 Wed Aug 29 06:57:58 2012 Doug Lea +Note: There may be an updated version of this malloc obtainable at + ftp://gee.cs.oswego.edu/pub/misc/malloc.c + Check before installing! + +File modified by CEA (Commissariat à l'énergie atomique et aux + énergies alternatives). + diff --git a/src/plugins/e-acsl/headers/open-source/MODIFIED_LIB_GMP b/src/plugins/e-acsl/headers/open-source/MODIFIED_LIB_GMP new file mode 100644 index 0000000000000000000000000000000000000000..6ca6c4f658f0705c1a491e350a80421c323c226d --- /dev/null +++ b/src/plugins/e-acsl/headers/open-source/MODIFIED_LIB_GMP @@ -0,0 +1,36 @@ + + mini-gmp, a minimalistic implementation of a GNU GMP subset. + + Contributed to the GNU project by Niels Möller + +Copyright 1991-1997, 1999-2015 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of either: + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at your + option) any later version. + +or + + * the GNU General Public License as published by the Free Software + Foundation; either version 2 of the License, or (at your option) any + later version. + +or both in parallel, as here. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received copies of the GNU General Public License and the +GNU Lesser General Public License along with the GNU MP Library. If not, +see https://www.gnu.org/licenses/. + +File modified by CEA (Commissariat à l'énergie atomique et aux + énergies alternatives). + diff --git a/src/plugins/e-acsl/headers/open-source/MODIFIED_SPARETIMELABS b/src/plugins/e-acsl/headers/open-source/MODIFIED_SPARETIMELABS new file mode 100644 index 0000000000000000000000000000000000000000..98f92575c04e48b1f47c95d55caa89e6b30d1ee1 --- /dev/null +++ b/src/plugins/e-acsl/headers/open-source/MODIFIED_SPARETIMELABS @@ -0,0 +1,35 @@ + +Copyright (c) 2004,2012 Kustaa Nyholm / SpareTimeLabs + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +Neither the name of the Kustaa Nyholm or SpareTimeLabs nor the names +of its contributors may be used to endorse or promote products derived +from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +File modified by CEA (Commissariat à l'énergie atomique et aux + énergies alternatives). + diff --git a/src/plugins/e-acsl/known_bugs/README b/src/plugins/e-acsl/known_bugs/README new file mode 100644 index 0000000000000000000000000000000000000000..b47adbfd58270055225cb5a4ccf310e47361357f --- /dev/null +++ b/src/plugins/e-acsl/known_bugs/README @@ -0,0 +1,5 @@ +A comprehensive up-to-date list of known bugs is available on + + https://bts.frama-c.com + +in the category "Plug-in > E-ACSL". diff --git a/src/plugins/e-acsl/known_bugs/bts1354_logical_at.i b/src/plugins/e-acsl/known_bugs/bts1354_logical_at.i new file mode 100644 index 0000000000000000000000000000000000000000..32d290b5c95b7c6622562bcca282f9bc1885dbd2 --- /dev/null +++ b/src/plugins/e-acsl/known_bugs/bts1354_logical_at.i @@ -0,0 +1,4 @@ + +/*@ ensures \forall int i; 0 <= i < n-1 ==> \old(t[i]) == t[i+1]; */ +void reverse(int * t, int n) { +} diff --git a/src/plugins/e-acsl/known_bugs/bts1379_read_address.c b/src/plugins/e-acsl/known_bugs/bts1379_read_address.c new file mode 100644 index 0000000000000000000000000000000000000000..5e78d533ae8c57d8518e6402995f12e85434056e --- /dev/null +++ b/src/plugins/e-acsl/known_bugs/bts1379_read_address.c @@ -0,0 +1,39 @@ + +#include "stdio.h" + +int x = 2, y = 3, z = 5, t[2]; + +int main() { + //@ assert \valid(&x) && \valid(&y) && \valid(&z); + int * p = &t; + + //@ assert \valid(p); + //@ assert \base_addr(p) == \base_addr(&t); + *p = 4; + p++; + + //@ assert \valid(p); + //@ assert \base_addr(p) == \base_addr(&t); + *p = 12; + p++; + + //@ assert !\valid(p); + printf("%i %i\n", t[0], t[1]); + + //=================================== + p = &y; + printf("%p %p %p %p\n", &x, &y, &z, p); + printf("%i %i %i %i\n", x, y, z, *p); + + //@ assert \valid(p); + p++; + + printf("%p %p %p %p\n", &x, &y, &z, p); + printf("%i %i %i %i\n", x, y, z, *p); + + //@ assert \valid(p); + //@ assert \base_addr(p) == \base_addr(&y); + *p = 100; + printf("%i %i %i %i\n", x, y, z, *p); + return 0; +} diff --git a/src/plugins/e-acsl/known_bugs/bts1386_complex_flowgraph.c b/src/plugins/e-acsl/known_bugs/bts1386_complex_flowgraph.c new file mode 100644 index 0000000000000000000000000000000000000000..d04c742e75b9c290b3966422718697cf4c3f00a3 --- /dev/null +++ b/src/plugins/e-acsl/known_bugs/bts1386_complex_flowgraph.c @@ -0,0 +1,113 @@ +/* MDH WCET BENCHMARK SUITE. File version $Id: duff.c,v 1.4 2005/12/21 09:43:07 jgn Exp $ */ + +/*---------------------------------------------------------------------- + * WCET Benchmark created by Jakob Engblom, Uppsala university, + * February 2000. + * + * The purpose of this benchmark is to force the compiler to emit an + * unstructured loop, which is usually problematic for WCET tools to + * handle. + * + * The execution time should be constant. + * + * The original code is "Duff's Device", see the Jargon File, e.g. at + * http://www.tf.hut.fi/cgi-bin/jargon. Created in the early 1980s + * as a way to express loop unrolling in C. + * + *----------------------------------------------------------------------*/ + + /* + * Changes: JG 2005/12/21: Changed type of main to int + Indented program. + */ + +#include "stdio.h" + +#define ARRAYSIZE 100 +#define INVOCATION_COUNT 43 /* exec time depends on this one! */ + + +void +duffcopy(char *to, char *from, int count) +{ + + int n = (count + 7) / 8; + switch (count % 8) { + case 0: + do { + *to++ = *from++; + case 7: + *to++ = *from++; + case 6: + *to++ = *from++; + case 5: + *to++ = *from++; + case 4: + *to++ = *from++; + case 3: + *to++ = *from++; + case 2: + *to++ = *from++; + case 1: + *to++ = *from++; + + } while (--n > 0); + } +} + + +void +initialize(char *arr, int length) +{ + int i; + for (i = 0; i < length; i++) { + arr[i] = length - i; + } +} + + +char source[ARRAYSIZE]; +char target[ARRAYSIZE]; + +int +main(void) +{ + initialize(source, ARRAYSIZE); + duffcopy(source, target, INVOCATION_COUNT); + return 0; +} + + +/*------------------------------------------------------------ + * $Id: duff.c,v 1.4 2005/12/21 09:43:07 jgn Exp $ + *------------------------------------------------------------ + * $Log: duff.c,v $ + * Revision 1.4 2005/12/21 09:43:07 jgn + * Changes... + * + * Revision 1.3 2005/11/11 10:29:45 ael01 + * updated + * + * Revision 1.2 2005/04/04 11:34:58 csg + * again + * + * Revision 1.1 2005/03/29 09:34:13 jgn + * New file. + * + * Revision 1.8 2000/10/16 07:48:15 jakob + * *** empty log message *** + * + * Revision 1.7 2000/05/22 11:02:18 jakob + * Fixed minor errors. + * + * Revision 1.6 2000/02/27 16:56:52 jakob + * *** empty log message *** + * + * Revision 1.5 2000/02/15 14:09:24 jakob + * no message + * + * Revision 1.2 2000/02/15 13:32:16 jakob + * Added duff's device to benchmark suite for LCTES 00 paper. + * + * + *------------------------------------------------------------*/ diff --git a/src/plugins/e-acsl/known_bugs/bts1395_recursive_function.i b/src/plugins/e-acsl/known_bugs/bts1395_recursive_function.i new file mode 100644 index 0000000000000000000000000000000000000000..27110c4d058f37cbbf4fa61fc60e3551191f5242 --- /dev/null +++ b/src/plugins/e-acsl/known_bugs/bts1395_recursive_function.i @@ -0,0 +1,13 @@ +// handling recursive functions (implicit call to __e_acsl_rec_id) + +/*@ ensures x >= 0 ==> \result == x; */ +int rec_id(int x) { + int tmp; + if (x <= 0) return 0; + return 1 + rec_id(x - 1); +} + +int main(void) { + int x = rec_id(4); + return 0; +} diff --git a/src/plugins/e-acsl/known_bugs/bts1636_memory_leak_literal_strings.i b/src/plugins/e-acsl/known_bugs/bts1636_memory_leak_literal_strings.i new file mode 100644 index 0000000000000000000000000000000000000000..8817fd839d63c551ae1f1233c36ce9a538729902 --- /dev/null +++ b/src/plugins/e-acsl/known_bugs/bts1636_memory_leak_literal_strings.i @@ -0,0 +1,9 @@ +int main(void) +{ + char *s; + for(int i = 0; i < 10; i++) { + s = "012"; + } + /*@ assert s[1] == '1'; */ + return 0; +} diff --git a/src/plugins/e-acsl/known_bugs/decl_in_switch.c b/src/plugins/e-acsl/known_bugs/decl_in_switch.c new file mode 100644 index 0000000000000000000000000000000000000000..16ddbbf61bb37e21594a834a8130c0b82062fb0c --- /dev/null +++ b/src/plugins/e-acsl/known_bugs/decl_in_switch.c @@ -0,0 +1,17 @@ +/* run.config_ci + DONTRUN: + COMMENT: Variables declared in the body of switch statements so far cannot + COMMENT: be tracked +*/ + +int main(int argc, char **argv) { + switch(argc) { + int *p; + default: { + p = &argc; + /*! assert \valid(p); */ + break; + } + } + return 0; +} diff --git a/src/plugins/e-acsl/known_bugs/let-alias.c b/src/plugins/e-acsl/known_bugs/let-alias.c new file mode 100644 index 0000000000000000000000000000000000000000..25af1ec3080abc2de0e9850d8d478a7617aa7488 --- /dev/null +++ b/src/plugins/e-acsl/known_bugs/let-alias.c @@ -0,0 +1,13 @@ +/* run.config_dev + DONTRUN: +*/ + +/* let binding on alias: only work with -e-acsl-full-mmodel; + should not be the case. */ + +int main(void) { + int t[4] = {1,2,3,4}; + /*@ assert \let u = t + 1; *(u + 2) == 4; */ ; + /*@ assert (\let u = t + 1; *(u + 2)) == 4; */ ; + return 0; +} diff --git a/src/plugins/e-acsl/lib/.gitkeep b/src/plugins/e-acsl/lib/.gitkeep new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/plugins/e-acsl/license/CEA_LGPL b/src/plugins/e-acsl/license/CEA_LGPL new file mode 100644 index 0000000000000000000000000000000000000000..f8ea6cb6fa29998f5f29262a96b6ed1e188fbc43 --- /dev/null +++ b/src/plugins/e-acsl/license/CEA_LGPL @@ -0,0 +1,19 @@ + +This file is part of the Frama-C's E-ACSL plug-in. + +Copyright (C) 2012-2018 + CEA (Commissariat à l'énergie atomique et aux énergies + alternatives) + +you can redistribute it and/or modify it under the terms of the GNU +Lesser General Public License as published by the Free Software +Foundation, version 2.1. + +It is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +See the GNU Lesser General Public License version 2.1 +for more details (enclosed in the file license/LGPLv2.1). + diff --git a/src/plugins/e-acsl/license/LGPLv2.1 b/src/plugins/e-acsl/license/LGPLv2.1 new file mode 100644 index 0000000000000000000000000000000000000000..8c177f8bedc4a734d40312bb165035be1b22fad4 --- /dev/null +++ b/src/plugins/e-acsl/license/LGPLv2.1 @@ -0,0 +1,458 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS diff --git a/src/plugins/e-acsl/license/SPARETIMELABS b/src/plugins/e-acsl/license/SPARETIMELABS new file mode 100644 index 0000000000000000000000000000000000000000..ac2f4f9164045b7759bb83ac4ae01c6a6e0d27c7 --- /dev/null +++ b/src/plugins/e-acsl/license/SPARETIMELABS @@ -0,0 +1,32 @@ + +Copyright (c) 2004,2012 Kustaa Nyholm / SpareTimeLabs + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +Neither the name of the Kustaa Nyholm or SpareTimeLabs nor the names +of its contributors may be used to endorse or promote products derived +from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + diff --git a/src/plugins/e-acsl/license/headache_config.txt b/src/plugins/e-acsl/license/headache_config.txt new file mode 100644 index 0000000000000000000000000000000000000000..9bb003875b043426b796ecc87f2378b392f3f60d --- /dev/null +++ b/src/plugins/e-acsl/license/headache_config.txt @@ -0,0 +1,136 @@ +################## +# Objective Caml # +################## +| ".*\.mly" -> frame open:"/*" line:"*" close:"*/" +| ".*\.ml[il4]?.*" -> frame open:"(*" line:"*" close:"*)" + +############ +# C source # +############ +| ".*\.h" -> frame open:"/*" line:"*" close:"*/" +| ".*\.i" -> frame open:"/*" line:"*" close:"*/" +| ".*\.c" -> frame open:"/*" line:"*" close:"*/" +| ".*\.ast" -> frame open:"//" line:" " close:" " +| ".*\.cc" -> frame open:"/*" line:"*" close:"*/" + +####### +# Asm # +####### +| ".*\.S" -> frame open:"/*" line:"*" close:"*/" + +############# +# Configure # +############# +| ".*config\.h\.in" -> frame open:"/*" line:"*" close:"*/" +| ".*configure\..*" -> frame open:"#" line:"#" close:"#" + +############ +# Makefile # +############ +| ".*Make.*" -> frame open:"#" line:"#" close:"#" +| ".*\.mk" -> frame open:"#" line:"#" close:"#" + +################# +# Shell scripts # +################# +#note: the skip directive requires a filename starting by ".*" ??? +| "autocomplete_frama-c" -> frame open: "#" line: "#" close: "#" +| "_frama-c" -> frame open: "#" line: "#" close: "#" +| ".*_frama-c" -> skip match:"#compdef.*" +| ".*\.sh" -> frame open:"#" line:"#" close:"#" +| ".*\.sh" -> skip match:"#!.*" +| "frama-c" -> frame open:"#" line:"#" close:"#" +| ".*frama-c" -> skip match:"#!.*" +| "frama-c-config" -> frame open:"#" line:"#" close:"#" +| ".*frama-c-config" -> skip match:"#!.*" +| "frama-c-script" -> frame open:"#" line:"#" close:"#" +| ".*frama-c-script" -> skip match:"#!.*" +| "frama-c-gui" -> frame open:"#" line:"#" close:"#" +| ".*frama-c-gui" -> skip match:"#!.*" +| "frama-c-gui.byte" -> frame open:"#" line:"#" close:"#" +| ".*frama-c-gui.byte" -> skip match:"#!.*" +| "frama-c.byte" -> frame open:"#" line:"#" close:"#" +| ".*frama-c.byte" -> skip match:"#!.*" +| "frama-c.top" -> frame open:"#" line:"#" close:"#" +| ".*frama-c.top" -> skip match:"#!.*" + +################ +# Perl scripts # +################ +| ".*\.perl" -> frame open:"#" line:"#" close:"#" +| "flamegraph.pl" -> frame open:"#" line:"#" close:"#" +| ".*flamegraph.pl" -> skip match:"#!.*" + +######################### +# MS-Windows Resources # +######################### +| ".*\.rc" -> frame open:"#" line:"#" close:"#" + +############# +# man pages # +############# +| ".*\.[1-9]" -> frame open:".\\\"" line: "-" close:"" + +############# +# Why files # +############# +| ".*\.why" -> frame open: "(*" line: "*" close: "*)" +| ".*\.why\.src" -> frame open: "(*" line: "*" close: "*)" + +############# +# Alt-Ergo files # +############# +| ".*\.mlw" -> frame open: "(*" line: "*" close: "*)" + +############# +# Coq files # +############# +| ".*\.v" -> frame open: "(*" line: "*" close: "*)" + +############# +# WP files # +############# +| ".*\.driver" -> frame open: "/*" line: "*" close: "*/" + +##################### +# Why3 driver files # +##################### +| ".*\.drv" -> frame open: "(*" line: "*" close: "*)" + +######## +# HTML # +######## +| ".*\.htm.*" -> frame open: "<!--" line: "-" close: "-->" + +####### +# DTD # +####### +| ".*\.dtd" -> frame open: "<!--" line: " " close: "-->" + +####### +# XSL # +####### +| ".*\.xsl" -> frame open: "<!--" line: " " close: "-->" + +####### +# CSS # +####### +| ".*\.css" -> frame open: "/*" line: "*" close: "*/" +# plug-in's ocamldoc introductions +| "intro_.*\.txt" -> frame open: "#*" line: "*" close: "#" + +########## +# PROLOG # +########## +| ".*\.pl" -> frame open: "%" line: "%" close: "%" + +############## +# Emacs Lisp # +############## +| ".*\.el" -> frame open: ";" line: ";" close:";" + +############## +# Misc files # +############## +| "make_release" -> frame open:"#" line:"#" close:"#" +| "FAQ" -> frame open:"#" line:"#" close:"#" diff --git a/src/plugins/e-acsl/man/e-acsl-gcc.sh.1 b/src/plugins/e-acsl/man/e-acsl-gcc.sh.1 new file mode 100644 index 0000000000000000000000000000000000000000..601728e0c01a4c18161f8e28d7583cc8b5f7e464 --- /dev/null +++ b/src/plugins/e-acsl/man/e-acsl-gcc.sh.1 @@ -0,0 +1,240 @@ +.\"------------------------------------------------------------------------ +.\" +.\" This file is part of the Frama-C's E-ACSL plug-in. +.\" +.\" Copyright (C) 2012-2018 +.\" CEA (Commissariat à l'énergie atomique et aux énergies +.\" alternatives) +.\" +.\" you can redistribute it and/or modify it under the terms of the GNU +.\" Lesser General Public License as published by the Free Software +.\" Foundation, version 2.1. +.\" +.\" It is distributed in the hope that it will be useful, +.\" but WITHOUT ANY WARRANTY; without even the implied warranty of +.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +.\" GNU Lesser General Public License for more details. +.\" +.\" See the GNU Lesser General Public License version 2.1 +.\" for more details (enclosed in the file licenses/LGPLv2.1). +.\" +.\"------------------------------------------------------------------------ + +.TH E-ACSL-GCC.SH 1 2016-02-02 + +.SH NAME +.B e-acsl-gcc.sh +\- instrument and compile C files with E-ACSL +.SH SYNOPSIS +.B e-acsl-gcc.sh +[ +.I options +] +.I files +.SH DESCRIPTION +.B e-acsl-gcc.sh +is a convenience wrapper for instrumentation of C programs using the +\fBE-ACSL\fP \fBFrama-C\fP plugin and their subsequent compilation using +the GNU compiler collection (\fBGCC\fP). +.SH OPTIONS +.TP +.B -h, --help +show a help page. +.TP +.B -c, --compile +compile the generated and the original (supplied) sources. +By default no compilation is performed. +.TP +.B -D, --rt-debug +Enable runtime debug features, i.e., compile unoptimized executable +with assertions and extra checks. +.TP +.B --no-trace +Disable stack trace reporting in debug mode +.TP +.B -V, --rt-verbose +Output extra messages when executing generated code +.TP +.B -X, --instrumented-only +Do not compile original code. Has effect only in the presence of the \fI-c\fP +flag. +.TP +.B -C, --compile-only +compile the input files as if they were generated by \fBE-ACSL\fP. +.TP +.B -d, --debug=\fI<N> +pass a value to the \fBFrama-C\fP -\fIdebug\fP option. +By default the -\fIdebug\fP flag is unused. +.TP +.B -v, --verbose=\fI<N> +pass a value to the \fBFrama-C\fP -\fIverbose\fP option. +By default the -\fIverbose\fP flag is unused. +.TP +.B -V, --check +check integrity of the generated AST (mostly useful for developers). +.TP +.B -o, --ocode=\fI<FILE> +output the \fBE-ACSL\fP instrumented code to \fI<FILE>\fP. +Defaults to \fIa.out.frama.c\fP. +.TP +.B -O, --oexec=\fI<FILE> +output the code compiled from the uninstrumented sources to \fI<FILE>\fP. +The executable compiled from the files generated by \fBE-ACSL\fP is +appended the \fI.e.acsl\fP suffix. +Unless specified, the +names of the executables generated from the original +and the modified programs are +\fIa.out\fP and \fIa.out.e-acsl\fP respectively. +.TP +.B --oexec-e-acsl=\fI<FILE> +name of the executable file generated from the \fBE-ACSL\fP-instrumented file. +Unless specified, the executable is named as inidicated by the \fB--oexec\fP option. +.TP +.B -f, --frama-c-only +run input source files through \fBFrama-C\fP without \fBE-ACSL\fP instrumentations. +.TP +.B -E, --extra-cpp-args=\fI<FLAGS> +pass additional arguments to the \fBFrama-C\fP pre-processor. +.TP +.B -L, --frama-c-stdlib +use the \fBFrama-C\fP standard library instead of a system-wide one. +.TP +.B -M, --full-mmodel +maximize memory-related instrumentation. +.TP +.B --temporal +enable checking for temporal memory errors in \\\fBvalid\fP and \\\fBvalid_read\fP predicates. +.TP +.B --weak-validity +enable notion of weak validity. By default expression \fB(p+i)\fP, where \fBp\fP +is a pointer and \fBi\fP is an integer offset is deemed valid if both addresses +\fBp\fP and \fB(p+i)\fP belong to the same allocated block. With weak validity +\fB(p+i)\fP is valid if the memory location which address is given by +expression \fB(p+i)\fP is allocated. +.TP +.B --validate-format-strings +enable built-in detection of format-string vulnerabilities. +.TP +.B --libc-replacements +replace some of the unsafe LIBC functions (e.g., strcpy, memcpy) with RTL +alternatives that include internal runtime error checking. +.TP +.B -g, --gmp +always use GMP integers instead of C integral types. +By default the GMP integers are used on as-needed basis. +.TP +.B -l, --ld-flags=\fI<FLAGS> +pass the specified flags to the linker. +.TP +.B -e, --cpp-flags=\fI<FLAGS> +pass the specified flags to the pre-processor at compile-time. +For instrumentation-time pre-processor flags see \fB--extra-cpp-args\fP option. +.TP +.B -q, --quiet +suppress any output except for errors and warnings. +.TP +.B -s, --logfile=\fI<FILE> +redirect all output to a given file. +.TP +.B -F, --frama-c-extra=\fI<FLAGS> +pass an extra option to a \fBFrama-C\fP invocation. +.TP +.B -a, --rte=\fI<OPTSTRING> +annotate a source program with assertions using a run of an RTE plugin prior to +E-ACSL. \fIOPTSTRING\fP is a comma-separated string that specifies the types of +generated assertions. +Valid arguments are: + + \fIsigned-overflow\fP \- signed integer overflows. + \fIunsigned-overflow\fP \- unsigned integer overflows. + \fIsigned-downcast\fP \- signed downcast exceeding destination range. + \fIunsigned-downcast\fP \- unsigned downcast exceeding destination range. + \fImem\fP \- pointer or array accesses. + \fIfloat-to-int\fP \- casts from floating-point to integer. + \fIdiv\fP \- division by zero. + \fIshift\fP \- left and right shifts by a value out of bounds. + \fpointer-call\fP \- annotate functions calls through pointers. + \fIall\fP \- all of the above. +.TP +.B -A, --rte-select=\fI<OPTSTRING> +Restrict annotations to a given list of functions. +\fIOPTSTRING\fP is a comma-separated string comprising function names. +.TP +.B --stack-size=\fI<NUMBER> +Set the size (in MB) of the stack shadow space +.TP +.B --heap-size=\fI<NUMBER> +Set the size (in MB) of the heap shadow space +.TP +.B -k, --keep-going +Continue execution after an assertion failure +.TP +.B --free-valid-address +Trigger failure if a NULL-pointer is used as an input to free function +.TP +.B --fail-with-code=\fI<NUMBER> +On assertion failure exit with the given integer code intead of raising an abort +signal +.TP +.B -m, --memory-model=\fI<model> +memory model (i.e., a runtime library for checking memory related annotations) +to be linked against the instrumented file. + +Valid arguments are: + \fIbittree\fP \- memory modelling using a Patricia trie. + \fIsegment\fP \- shadow based segment model. + +By default the Patricia trie memory model is used. +.TP +.B --print-models +Print the names of the supported memory models +.TP +.B -I, --frama-c=\fI<FILE> +the name of the \fBFrama-C\fP executable. By default the +first \fIframa-c\fP executable found in the system path is used. +.TP +.B -G, --gcc=\fI<FILE> +the name of the \fBGCC\fP executable. By default the first \fIgcc\fP +executable found in the system path is used. +.TP +.B --then +Separate with a \fB-then\fP the first \fBFrama-C\fP options from the actual +launch of the \fBE-ACSL\fP plugin. Prepends \fB-e-acsl-prepare\fP to the list +of options passed to \fBFrama-C\fP. +.TP +.B --e-acsl-extra=\fI<OPTS> +Adds \fI<OPTS>\fP to the list of options that will be given to the \fBE-ACSL\fP +analysis. Only useful when \fB--then\fP is in use, in which case \fI<OPTS>\fP +will be placed after the \fB-then\fP on \fBFrama-C\fP's command-line. Otherwise, +equivalent to \fB--frama-c-extra\fP +.SH EXIT STATUS +.TP +.B 0 +Successful execution +.TP +.B 1 +Invalid user input +.TP +.B \fBFrama-C\fP or \fBGCC\fP error code +Instrumentation- or compile-time error + +.SH EXAMPLES + +.B e-acsl-gcc.sh foo.c + +Instrument foo.c and output the instrumented code to \fIa.out.frama.c\fP. + +.B e-acsl-gcc.sh -P -c -ogen_foo.c -Ofoo foo.c + +Instrument \fIfoo.c\fP, output the instrumented code to \fIgen_foo.c\fP and +compile \fIfoo.c\fP into \fIfoo\fP and \fIgen_foo.c\fP into \fIfoo.e-acsl\fP. +The \fB-P\fP option specifies that the instrumentation should omit debug +functionality. + +.B e-acsl-gcc.sh --memory-model=bittree -C gen_foo.c + +Assume \fIgen_foo.c\fP has been instrumented by \fBE-ACSL\fP and compile it into +\fIa.out.e-acsl\fP using \fBbittree\fP memory model. + +.SH SEE ALSO +\fBgcc\fP(1), \fBcpp\fP(1), \fBld\fP(1), \fBframa-c\fP(1) diff --git a/src/plugins/e-acsl/nix/default.nix b/src/plugins/e-acsl/nix/default.nix new file mode 100644 index 0000000000000000000000000000000000000000..6c41960f846c6e6ed7cc5b386ba6ae683cb0189c --- /dev/null +++ b/src/plugins/e-acsl/nix/default.nix @@ -0,0 +1,11 @@ +# paramaterised derivation with dependencies injected (callPackage style) +{ pkgs, stdenv, src ? ../., opam2nix, ocaml_version ? "ocamlPackages_latest.ocaml", plugins ? { } }: + +plugins.helpers.simple_plugin + { inherit pkgs stdenv src opam2nix ocaml_version plugins; + deps = [ pkgs.getopt pkgs.which ]; + name = "e-acsl"; + preBuild = '' + echo IN_FRAMA_CI=yes > in_frama_ci + ''; + } diff --git a/src/plugins/e-acsl/nix/frama-ci.nix b/src/plugins/e-acsl/nix/frama-ci.nix new file mode 100644 index 0000000000000000000000000000000000000000..112683c48489cb7773fd1c6fa8575ad00a83bd70 --- /dev/null +++ b/src/plugins/e-acsl/nix/frama-ci.nix @@ -0,0 +1,15 @@ +#To copy in other repository +{ pkgs ? import <nixpkgs> {}, password}: + +let + src = builtins.fetchGit { + "url" = "https://bobot:${password}@git.frama-c.com/frama-c/Frama-CI.git"; + "name" = "Frama-CI"; + "rev" = "cea0f2d2872e59fd3e6fe4634891a3765c7036e8"; + "ref" = "master"; + }; + in + { + src = src; + compiled = pkgs.callPackage "${src}/compile.nix" { inherit pkgs; }; + } diff --git a/src/plugins/e-acsl/nix/frama-ci.sh b/src/plugins/e-acsl/nix/frama-ci.sh new file mode 100755 index 0000000000000000000000000000000000000000..b331b057a8e8ec372a541e94d2af935a95b94f2a --- /dev/null +++ b/src/plugins/e-acsl/nix/frama-ci.sh @@ -0,0 +1,12 @@ +#!/bin/sh -eu + +DIR=$(dirname $0) + +export FRAMA_CI_NIX=$DIR/frama-ci.nix + +export FRAMA_CI=$(nix-instantiate --eval -E "((import <nixos-19.03> {}).callPackage $FRAMA_CI_NIX { password = \"$TOKEN_FOR_API\";}).src.outPath") + +FRAMA_CI=${FRAMA_CI#\"} +FRAMA_CI=${FRAMA_CI%\"} + +$FRAMA_CI/compile.sh $@ diff --git a/src/plugins/e-acsl/scripts/e-acsl-gcc.comp b/src/plugins/e-acsl/scripts/e-acsl-gcc.comp new file mode 100644 index 0000000000000000000000000000000000000000..56f49d1a9d46970efcf0c5ef39c179969c342fd9 --- /dev/null +++ b/src/plugins/e-acsl/scripts/e-acsl-gcc.comp @@ -0,0 +1,57 @@ +########################################################################## +# # +# This file is part of the Frama-C's E-ACSL plug-in. # +# # +# Copyright (C) 2012-2018 # +# CEA (Commissariat à l'énergie atomique et aux énergies # +# alternatives) # +# # +# you can redistribute it and/or modify it under the terms of the GNU # +# Lesser General Public License as published by the Free Software # +# Foundation, version 2.1. # +# # +# It is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU Lesser General Public License for more details. # +# # +# See the GNU Lesser General Public License version 2.1 # +# for more details (enclosed in the file license/LGPLv2.1). # +# # +########################################################################## + +# Bash completion for e-acsl-gcc.sh + +_eacsl_gcc() { + local cur prev opts base + COMPREPLY=() + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + + opts=" + -i -C -p -d -o -O -v -f -E -L -M -l -e -g -q -s -F -P -N -D -I -G -X -a + -h -c -msegment -mbittree + --verbose= --debug= --debug-log= --logfile= --quiet --rt-debug --help + --ocode= --oexec= --oexec-e-acsl= + --ld-flags= --cpp-flags= --extra-cpp-args= + --frama-c-extra= --frama-c= --gcc= --e-acsl-share= --memory-model= + --compile --compile-only --print --frama-c-only --instrumented-only + --gmp --full-mmodel --rte --no-int-overflow --no-stdlib --frama-c-stdlib" + + case ${prev} in + -*) + COMPREPLY=($(compgen -W "${opts}" -- ${cur})) + return 0 + ;; + *) + COMPREPLY=($(compgen -W "${opts}" -- ${cur})) + [[ $COMPREPLY == *= ]] && compopt -o nospace + return 0 + ;; + esac + + return 0 +} +complete -F _eacsl_gcc e-acsl-gcc.sh + + diff --git a/src/plugins/e-acsl/scripts/e-acsl-gcc.sh b/src/plugins/e-acsl/scripts/e-acsl-gcc.sh new file mode 100755 index 0000000000000000000000000000000000000000..92da93f8982e0872316d273c2ddf1a4ac9ac9bf0 --- /dev/null +++ b/src/plugins/e-acsl/scripts/e-acsl-gcc.sh @@ -0,0 +1,847 @@ +#!/bin/sh -e +########################################################################## +# # +# This file is part of the Frama-C's E-ACSL plug-in. # +# # +# Copyright (C) 2012-2018 # +# CEA (Commissariat à l'énergie atomique et aux énergies # +# alternatives) # +# # +# you can redistribute it and/or modify it under the terms of the GNU # +# Lesser General Public License as published by the Free Software # +# Foundation, version 2.1. # +# # +# It is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU Lesser General Public License for more details. # +# # +# See the GNU Lesser General Public License version 2.1 # +# for more details (enclosed in the file licenses/LGPLv2.1). # +# # +########################################################################## + +# Convenience wrapper for small runs of E-ACSL Frama-C plugin + +# Print a message to STDERR and exit. If the second argument (exit code) +# is provided and it is '0' then do nothing. +error () { + if [ -z "$2" ] || ! [ "$2" = 0 ]; then + echo "e-acsl-gcc: fatal error: $1" 1>&2 + exit 1; + fi +} + +# Check if a given executable name can be found by in the PATH +has_tool() { + which "$@" >/dev/null 2>&1 && return 0 || return 1 +} + +# Check if a given executable name is indeed an executable or can be found +# in the $PATH. Abort the execution if not. +check_tool() { + { has_tool "$1" || test -e "$1"; } || error "No executable $1 found"; +} + +# Check whether getopt utility supports long options +check_getopt() { + local out="$(getopt -l "ab:,cd" -o "x:,y" -- --ab 1 -x 1 --cd -y \ + | sed "s/[ \']//g")" + error "system getopt has no support for long option processing" $? + if ! [ "$out" = "--ab1-x1--cd-y--" ]; then + error "unexpected output of system getopt" 1 + fi +} + +# Check if $1 is positive integer and whether $1 is greater than $2 +# Returns $1 is the above holds, otherwise return +# '-' if $1 is not a positive integer +# '<' if $1 is a positive integer but it is less than $2 +# NB: No checking is done for $2 +is_number() { + local n="$1" + local lim="$2" + + if [ "$n" -eq "$n" ] 2>/dev/null; then + if [ "$n" -lt "$lim" ]; then + echo '<' + else + echo $n + fi + else + echo '-' + fi +} + +# Portable realpath using pwd +realpath() { + if [ -e "$1" ]; then + if [ -d "$1" ]; then + (cd "$1" && pwd) + else + local name=$(basename "$1") + local dir=$(cd $(dirname "$1") && pwd) + echo $dir/$name + fi + return 0 + else + echo "realpath: no such file or directory: '$1'" 1>&2 + return 1 + fi +} + +# Split a comma-separated string into a space-separated string, remove +# all duplicates and trailing, leading or multiple spaces +tokenize() { + echo -n "$@" \ + | sed -e 's/\s//g' -e 's/,/ /g' -e 's/\s\+/\n/g' \ + | sort -u \ + | tr '\n' ' ' \ + | sed 's/\s*$//' +} + +# Given a token (first argument) and a list (remaining arguments) +# evaluate to true if the token is in the list, and to false otherwise +has_token() { + local token="$1" + local opt + shift + for opt in $@; do + [ "$opt" = "$token" ] && return 0 + done + return 1 +} + +# Filter out a token given by the first argument from the list of tokens +# given by the remaining arguments +shift_token() { + local token="$1" + shift + for opt in $@; do + [ "$opt" = "$token" ] && true || echo $opt + done +} + +# Generate option string for RTE plugin based on the value given via --rte +# and --rte-select flags +rte_options() { + # Frama-C assertions + local fc_options="signed-overflow unsigned-overflow \ + signed-downcast unsigned-downcast" + # RTE assertions + local rte_options="div float-to-int mem pointer-call shift \ + trivial-annotations" + # RTE assertions which are negated in all cases except when + # explicitly specified + # Option supported by RTE but unsupported in E-ACSL, should + # always be negated + local rte_options_unsupported="" + local rte_options_explicit="trivial-annotations" + local generated="-rte" # Generated Frama-C options + + # Clean-up option strings + local full_options="$fc_options $rte_options" + local input_asserts="$(tokenize "$1")" + local fselect="$2" + + # If there is 'all' keyword found enable all assertions + if has_token all $input_asserts; then + asserts="$full_options" + for opt in $rte_options_explicit; do + if ! has_token $opt $input_asserts; then + asserts="$(shift_token $opt $asserts)" + fi + done + else + asserts="$input_asserts" + fi + + if [ -n "$asserts" ]; then + # Check input options + local opt + for opt in $asserts; do + # Check whether a given input option exists, i.e., found in $full_options + if ! has_token $opt $full_options; then + echo "$opt" + return 1 + fi + done + + local prefix + # Generate assertion options for Frama-C (i.e., -warn-* or -no-warn-*) + for opt in $fc_options; do + has_token $opt $asserts && prefix="-warn" || prefix="-no-warn" + generated="$generated $prefix-$opt" + done + + # Generate assertion options for RTE (i.e., -rte-* or -rte-no-*) + for opt in $rte_options $rte_options_unsupported; do + has_token $opt $asserts && prefix="-rte" || prefix="-rte-no" + generated="$generated $prefix-$opt" + done + + # Pass -rte-select option of RTE + if [ -n "$fselect" ]; then + fselect="$(echo $fselect | sed 's/\s//g')" + generated="$generated -rte-select=$fselect" + fi + + echo $generated -then + fi + return 0 +} + +# Output -D flags enabling a given E_ACSL memory model +mmodel_features() { + local model="$1" + + # Memory model + case $model in + bittree) flags="-DE_ACSL_BITTREE_MMODEL" ;; + segment) flags="-DE_ACSL_SEGMENT_MMODEL" ;; + *) error "Memory model '$model' is not available in this distribution" ;; + esac + + # Temporal analysis + if [ -n "$OPTION_TEMPORAL" ]; then + flags="$flags -DE_ACSL_TEMPORAL" + fi + + # Trigger failures in assertions + if [ -n "$OPTION_KEEP_GOING" ]; then + flags="$flags -DE_ACSL_NO_ASSERT_FAIL" + fi + + # Enable debug mode + if [ -n "$OPTION_RT_DEBUG" ]; then + flags="$flags -DE_ACSL_DEBUG" + fi + + # Set stack shadow size + if [ -n "$OPTION_STACK_SIZE" ]; then + flags="$flags -DE_ACSL_STACK_SIZE=$OPTION_STACK_SIZE" + fi + + # Set heap shadow size + if [ -n "$OPTION_HEAP_SIZE" ]; then + flags="$flags -DE_ACSL_HEAP_SIZE=$OPTION_HEAP_SIZE" + fi + + # Set runtime verosity flags + if [ -n "$OPTION_RT_VERBOSE" ]; then + flags="$flags -DE_ACSL_VERBOSE -DE_ACSL_DEBUG_VERBOSE" + fi + + if [ -n "$OPTION_FAIL_WITH_CODE" ]; then + flags="$flags -DE_ACSL_FAIL_EXITCODE=$OPTION_FAIL_WITH_CODE " + fi + + if [ -n "$OPTION_WEAK_VALIDITY" ]; then + flags="$flags -DE_ACSL_WEAK_VALIDITY" + fi + + if [ -n "$OPTION_FREE_VALID_ADDRESS" ]; then + flags="$flags -DE_ACSL_FREE_VALID_ADDRESS" + fi + + if [ -n "$OPTION_EXTERNAL_ASSERT" ]; then + flags="$flags -DE_ACSL_EXTERNAL_ASSERT" + fi + + if [ -n "$OPTION_NO_TRACE" ]; then + flags="$flags -DE_ACSL_NO_TRACE" + fi + + if [ -n "$OPTION_VALIDATE_FORMAT_STRINGS" ]; then + flags="$flags -DE_ACSL_VALIDATE_FORMAT_STRINGS" + fi + + echo $flags +} + +# Check if system getopt supports long option processing +check_getopt; + +# Getopt options +LONGOPTIONS="help,compile,compile-only,debug:,ocode:,oexec:,verbose:, + frama-c-only,extra-cpp-args:,frama-c-stdlib,full-mmodel,gmp,quiet,logfile:, + ld-flags:,cpp-flags:,frama-c-extra:,memory-model:,keep-going, + frama-c:,gcc:,e-acsl-share:,instrumented-only,rte:,oexec-e-acsl:, + print-mmodels,rt-debug,rte-select:,then,e-acsl-extra:,check,fail-with-code:, + temporal,weak-validity,stack-size:,heap-size:,rt-verbose,free-valid-address, + external-assert:,validate-format-strings,no-trace,libc-replacements" +SHORTOPTIONS="h,c,C,d:,D,o:,O:,v:,f,E:,L,M,l:,e:,g,q,s:,F:,m:,I:,G:,X,a:,T,k,V" +# Prefix for an error message due to wrong arguments +ERROR="ERROR parsing arguments:" + +# Variables holding getopt options +OPTION_CFLAGS= # Compiler flags +OPTION_CPPFLAGS= # Preprocessor flags +OPTION_LDFLAGS= # Linker flags +OPTION_FRAMAC="frama-c" # Frama-C executable name +OPTION_CC="gcc" # GCC executable name +OPTION_ECHO="set -x" # Echo executed commands to STDOUT +OPTION_INSTRUMENT=1 # Perform E-ACSL instrumentation +OPTION_DEBUG= # Set Frama-C debug flag +OPTION_VERBOSE= # Set Frama-C verbose flag +OPTION_COMPILE= # Compile instrumented program +OPTION_RT_DEBUG= # Enable runtime debug features +OPTION_RT_VERBOSE= # Set runtime verbosity level +OPTION_OUTPUT_CODE="a.out.frama.c" # Name of the translated file +OPTION_OUTPUT_EXEC="a.out" # Generated executable name +OPTION_EACSL_OUTPUT_EXEC="" # Name of E-ACSL executable +OPTION_EACSL="-e-acsl" # Specifies E-ACSL run +OPTION_FRAMA_STDLIB="-no-frama-c-stdlib" # Use Frama-C stdlib +OPTION_FULL_MMODEL= # Instrument as much as possible +OPTION_GMP= # Use GMP integers everywhere +OPTION_EACSL_MMODELS="segment" # Memory model used +OPTION_EACSL_SHARE= # Custom E-ACSL share directory +OPTION_INSTRUMENTED_ONLY= # Do not compile original code +OPTION_TEMPORAL= # Enable temporal analysis +OPTION_WEAK_VALIDITY= # Use notion of weak validity +OPTION_RTE= # Enable assertion generation +OPTION_FAIL_WITH_CODE= # Exit status code for failures +OPTION_CHECK= # Check AST integrity +OPTION_NO_TRACE= # Disable trace in debug mode +OPTION_FRAMAC_CPP_EXTRA= # Extra CPP flags for Frama-C +OPTION_FREE_VALID_ADDRESS= # Fail if NULL is used as input to free +OPTION_VALIDATE_FORMAT_STRINGS= # Runtime format string validation +OPTION_LIBC_REPLACEMENTS= # Replace libc functions with RTL definitions +OPTION_RTE_SELECT= # Generate assertions for these functions only +OPTION_THEN= # Adds -then in front of -e-acsl in FC command. +OPTION_STACK_SIZE=32 # Size of a heap shadow space (in MB) +OPTION_HEAP_SIZE=128 # Size of a stack shadow space (in MB) +OPTION_KEEP_GOING= # Report failing assertions but do not abort execution +OPTION_EXTERNAL_ASSERT="" # Use custom definition of assert function + +SUPPORTED_MMODELS="bittree,segment" # Supported memory model names +MIN_STACK=16 # Minimal size of a tracked program stack +MIN_HEAP=64 # Minimal size of a tracked program heap + +manpage() { + printf "e-acsl-gcc.sh - instrument and compile C files with E-ACSL +Usage: e-acsl-gcc.sh [options] files +Options: + -h show this help page + -c compile instrumented code + -l pass additional options to the linker + -e pass additional options to the prepreprocessor + -E pass additional arguments to the Frama-C preprocessor + -p output the generated code to STDOUT + -o <file> output the generated code to <file> [a.out.frama.c] + -O <file> output the generated executables to <file> [a.out, a.out.e-acsl] + -M maximize memory-related instrumentation + -g always use GMP integers instead of C integral types + -q suppress any output except for errors and warnings + -s <file> redirect all output to <file> + -I <file> specify Frama-C executable [frama-c] + -G <file> specify C compiler executable [gcc] + +Notes: + This help page shows only basic options. + See man (1) e-acsl-gcc.sh for full up-to-date documentation.\n" + exit 1 +} + +# Base dir of this script +BASEDIR="$(realpath `dirname $0`)" +# Directory with contrib libraries of E-ACSL +LIBDIR="$BASEDIR/../lib" + +# Run getopt +ARGS=`getopt -n "$ERROR" -l "$LONGOPTIONS" -o "$SHORTOPTIONS" -- "$@"` + +# Print and exit if getopt fails +if [ $? != 0 ]; then + exit 1; +fi + +# Set all options in $@ before -- and other after +eval set -- "$ARGS" + +# Switch statements for other options +for i in $@ +do + case "$i" in + # Do compile instrumented code + --help|-h) + shift; + manpage; + ;; + # Do not echo commands to STDOUT + # Set log and debug flags to minimal verbosity levels + --quiet|-q) + shift; + OPTION_ECHO= + OPTION_DEBUG="-e-acsl-debug 0" + OPTION_VERBOSE="-e-acsl-verbose 0" + ;; + # Redirect all output to a given file + --logfile|-s) + shift; + exec > $1 + exec 2> $1 + shift; + ;; + # Enable runtime debug features, i.e., compile unoptimized executable + # with assertions, extra checks and other debug features + --rt-debug|-D) + shift + OPTION_RT_DEBUG=1 + OPTION_CHECK=1 + ;; + --rt-verbose|-V) + shift; + OPTION_RT_VERBOSE=1 + ;; + # Pass an option to a Frama-C invocation + --frama-c-extra|-F) + shift; + FRAMAC_FLAGS="$FRAMAC_FLAGS $1" + shift; + ;; + # Do compile instrumented code + --compile|-c) + shift; + OPTION_COMPILE=1 + ;; + # Set Frama-C debug flag + --debug|-d) + shift; + if [ "$1" -eq "$1" ] 2>/dev/null; then + OPTION_DEBUG="-e-acsl-debug $1" + else + error "-d|--debug option requires integer argument" + fi + shift; + ;; + # Set Frama-C verbose flag + --verbose|-v) + shift; + if [ "$1" -eq "$1" ] 2>/dev/null; then + OPTION_VERBOSE="-e-acsl-verbose $1" + else + error "-v|--verbose option requires integer argument" + fi + shift; + ;; + # Specify the name of the default source file where instrumented + # code is to be written + --ocode|-o) + shift; + OPTION_OUTPUT_CODE="$1" + shift + ;; + # Specify the base name of the executable generated from the + # instrumented and non-instrumented sources. + --oexec|-O) + shift; + OPTION_OUTPUT_EXEC="$1" + shift + ;; + # Specify the output name of the E-ACSL generated executable + --oexec-e-acsl) + shift; + OPTION_EACSL_OUTPUT_EXEC="$1" + shift; + ;; + # Additional CPP arguments + --extra-cpp-args|-E) + shift; + OPTION_FRAMAC_CPP_EXTRA="$OPTION_FRAMAC_CPP_EXTRA $1" + shift; + ;; + # Additional flags passed to the linker + --ld-flags|-l) + shift; + OPTION_LDFLAGS="$OPTION_LDFLAGS $1" + shift; + ;; + # Additional flags passed to the pre-processor (compile-time) + --cpp-flags|-e) + shift; + OPTION_CPPFLAGS="$OPTION_CPPFLAGS $1" + shift; + ;; + # Do not perform the instrumentation, only compile the provided sources + # This option assumes that the source files provided at input have + # already been instrumented + --compile-only|-C) + shift; + OPTION_INSTRUMENT= + OPTION_COMPILE="1" + ;; + # Run only Frama-C related instrumentation + --frama-c-only|-f) + shift; + OPTION_EACSL= + ;; + # Do not compile original source file + --instrumented-only|-X) + shift; + OPTION_INSTRUMENTED_ONLY=1 + ;; + # Do use Frama-C stdlib, which is the default behaviour of Frama-C + --frama-c-stdlib|-L) + shift; + OPTION_FRAMA_STDLIB="-frama-c-stdlib" + ;; + # Use as much memory-related instrumentation as possible + -M|--full-mmodel) + shift; + OPTION_FULL_MMODEL="-e-acsl-full-mmodel" + ;; + # Use GMP everywhere + -g|--gmp) + shift; + OPTION_GMP="-e-acsl-gmp-only" + ;; + # Supply Frama-C executable name + -I|--frama-c) + shift; + OPTION_FRAMAC="$(which $1)" + shift; + ;; + # Supply GCC executable name + -G|--gcc) + shift; + OPTION_CC="$(which $1)" + shift; + ;; + # Specify EACSL_SHARE directory (where C runtime library lives) by hand + # rather than compute it + --e-acsl-share) + shift; + OPTION_EACSL_SHARE="$1" + shift; + ;; + # Runtime assertion generation + --rte|-a) + shift; + OPTION_RTE="$1" + shift; + ;; + # Runtime assertion generation for given functions only + --rte-select|-A) + shift; + OPTION_RTE_SELECT="$1" + shift; + ;; + # Check AST integrity (mostly for developers of E-ACSL) + --check) + OPTION_CHECK=1 + FRAMAC_FLAGS="-check $FRAMAC_FLAGS" + shift; + ;; + # Enable instrumentations of temporal validity analysis + -T|--temporal) + shift; + OPTION_TEMPORAL=-e-acsl-temporal-validity + ;; + # A memory model (or models) to link against + -m|--memory-model) + shift; + # Convert comma-separated string into white-space separated string + OPTION_EACSL_MMODELS="`echo $1 | sed -s 's/,/ /g'`" + shift; + ;; + # Print names of the supported memody models. + --print-mmodels) + shift; + echo $SUPPORTED_MMODELS + exit 0 + ;; + # Separate extra Frama-C flags from e-acsl launch with -then. + --then) + shift; + OPTION_THEN=-then + FRAMAC_FLAGS="-e-acsl-prepare $FRAMAC_FLAGS" + ;; + # Extra E-ACSL options + --e-acsl-extra) + shift; + OPTION_EACSL="$1 $OPTION_EACSL" + shift; + ;; + # Report failing assertions but do not abort execution + -k|--keep-going) + shift; + OPTION_KEEP_GOING=1 + ;; + # Exit with a given code on assertion failure instead of raising abort + --fail-with-code) + shift; + if [ "$1" -eq "$1" ] 2>/dev/null; then + OPTION_FAIL_WITH_CODE="$1" + else + error "--fail-with-code option requires integer argument" + fi + shift; + ;; + # Use notion of weak validity + --free-valid-address) + shift; + OPTION_FREE_VALID_ADDRESS=1 + ;; + # Use notion of weak validity + --weak-validity) + shift; + OPTION_WEAK_VALIDITY=1 + ;; + # Set heap shadow size + --heap-size) + shift; + zone_size="$(is_number "$1" $MIN_HEAP)" + case $zone_size in + '-') error "invalid number: '$1'" ;; + '<') error "heap limit less than minimal size [$MIN_HEAP"] + ;; + *) OPTION_HEAP_SIZE=$zone_size ;; + esac; + shift; + ;; + # Set stack shadow size + --stack-size) + shift; + zone_size="$(is_number "$1" $MIN_STACK)" + case $zone_size in + '-') error "invalid number: '$1'" ;; + '<') error "stack limit less than minimal size [$MIN_STACK"] ;; + *) OPTION_STACK_SIZE=$zone_size ;; + esac; + shift; + ;; + # Custom runtime assert function + --external-assert) + shift; + OPTION_EXTERNAL_ASSERT="$1" + shift; + ;; + # Check output format functions + --validate-format-strings) + shift; + OPTION_VALIDATE_FORMAT_STRINGS="-e-acsl-validate-format-strings" + ;; + # Replace some unsafe libc functions (such as strcpy, strcat) with + # RTL definitions and internal error checking + --libc-replacements) + shift; + OPTION_LIBC_REPLACEMENTS="-e-acsl-replace-libc-functions" + ;; + # Disable trace in debug mode + --no-trace) + shift + OPTION_NO_TRACE=1 + ;; + esac +done +shift; + +# Bail if no files to translate are given +if [ -z "$1" ]; then + error "no input files"; +fi + +# Check Frama-C and GCC executable names +check_tool "$OPTION_FRAMAC" +check_tool "$OPTION_CC" + +# Frama-C directories +FRAMAC="$OPTION_FRAMAC" +: ${FRAMAC_SHARE:="`$FRAMAC -print-share-path`"} +: ${FRAMAC_PLUGIN:="`$FRAMAC -print-plugin-path`"} + +# Check if this is a development or an installed version +if [ -f "$BASEDIR/../E_ACSL.mli" ]; then + # Development version + DEVELOPMENT="$(realpath "$BASEDIR/..")" + # Check if the project has been built, as if this is a non-installed + # version that has not been built Frama-C will fallback to an installed one + # for instrumentation but still use local RTL + error "Plugin in $DEVELOPMENT not compiled" \ + `test -f "$DEVELOPMENT/META.frama-c-e_acsl" -o \ + -f "$FRAMAC_PLUGIN/META.frama-c-e_acsl"; echo $?` + EACSL_SHARE="$DEVELOPMENT/share/e-acsl" + # Add the project directory to FRAMAC_PLUGINS, + # otherwise Frama-C uses an installed version + if test -f "$DEVELOPMENT/META.frama-c-e_acsl"; then + FRAMAC_FLAGS="-add-path=$DEVELOPMENT/top -add-path=$DEVELOPMENT $FRAMAC_FLAGS"; + fi +else + # Installed version. FRAMAC_SHARE should not be used here as Frama-C + # and E-ACSL may not be installed to the same location + EACSL_SHARE="$BASEDIR/../share/frama-c/e-acsl/" +fi + +# Architecture-dependent flags. Since by default Frama-C uses 32-bit +# architecture we need to make sure that same architecture is used for +# instrumentation and for compilation. +MACHDEPFLAGS="`getconf LONG_BIT`" +# Check if getconf gives out the value accepted by Frama-C/GCC +echo "$MACHDEPFLAGS" | grep '16\|32\|64' 2>&1 >/dev/null \ + || error "$MACHDEPFLAGS-bit architecture not supported" +# -machdep option sent to Frama-C +MACHDEP="-machdep gcc_x86_$MACHDEPFLAGS" +# Macro for correct preprocessing of Frama-C generated code +CPPMACHDEP="-D__FC_MACHDEP_X86_$MACHDEPFLAGS" +# GCC machine option +GCCMACHDEP="-m$MACHDEPFLAGS" + +# RTE flags +RTE_FLAGS="$(rte_options "$OPTION_RTE" "$OPTION_RTE_SELECT")" +error "Invalid argument $1 to --rte|-a option" $? + +# Frama-C and related flags +# Additional flags passed to Frama-C preprocessor via `-cpp-extra-args` +# -std=c99 -D_DEFAULT_SOURCE: use C99 + default features. This is important +# in OSX which by default enables `blocks` unsupported by Frama-C +# -D__NO_CTYPE: prevent `isupper` (and similar functions) from being used as +# macros, otherwise E-ACSL cannot track them at runtime +FRAMAC_CPP_EXTRA="\ + -std=c99 -D_DEFAULT_SOURCE -D__NO_CTYPE $CPPMACHDEP\ + $OPTION_FRAMAC_CPP_EXTRA" +EACSL_MMODEL="$OPTION_EACSL_MMODEL" + +# Re-set EACSL_SHARE directory is it has been given by the user +if [ -n "$OPTION_EACSL_SHARE" ]; then + EACSL_SHARE="$OPTION_EACSL_SHARE" +fi + +if [ -n "$OPTION_THEN" ]; then + FRAMAC_FLAGS="-e-acsl-share=$EACSL_SHARE $FRAMAC_FLAGS"; +fi + +# Select optimization flags for both instrumented and noon-instrumented code +# compilation +if [ -n "$OPTION_RT_DEBUG" ]; then + OPT_CFLAGS="-g3 -O0 -fno-omit-frame-pointer" +else + OPT_CFLAGS="-g -O2" +fi + +# Gcc and related flags +CC="$OPTION_CC" +CFLAGS="$OPTION_CFLAGS + -std=c99 $GCCMACHDEP $OPT_CFLAGS + -fno-builtin -fno-merge-constants + -Wall \ + -Wno-long-long \ + -Wno-attributes \ + -Wno-nonnull \ + -Wno-undef \ + -Wno-unused \ + -Wno-unused-function \ + -Wno-unused-result \ + -Wno-unused-value \ + -Wno-unused-function \ + -Wno-unused-variable \ + -Wno-unused-but-set-variable \ + -Wno-implicit-function-declaration \ + -Wno-empty-body" + +# Disable extra warning for clang +if [ "`basename $CC`" = 'clang' ]; then + CFLAGS="-Wno-unknown-warning-option \ + -Wno-extra-semi \ + -Wno-tautological-compare \ + -Wno-gnu-empty-struct \ + -Wno-incompatible-pointer-types-discards-qualifiers" +fi + +CPPFLAGS="$OPTION_CPPFLAGS" +LDFLAGS="$OPTION_LDFLAGS" + +# Extra Frama-C Flags E-ACSL needs +FRAMAC_FLAGS="$FRAMAC_FLAGS -variadic-no-translation" + +# C, CPP and LD flags for compilation of E-ACSL-generated sources +EACSL_CFLAGS="$OPTION_EXTERNAL_ASSERT" +EACSL_CPPFLAGS="-I$EACSL_SHARE" +EACSL_LDFLAGS="$LIBDIR/libeacsl-dlmalloc.a -lgmp -lm" + +# Output file names +OUTPUT_CODE="$OPTION_OUTPUT_CODE" # E-ACSL instrumented source +OUTPUT_EXEC="$OPTION_OUTPUT_EXEC" # Output name of the original executable + +# Output name of E-ACSL-modified executable +if [ -z "$OPTION_EACSL_OUTPUT_EXEC" ]; then + EACSL_OUTPUT_EXEC="$OPTION_OUTPUT_EXEC.e-acsl" +else + EACSL_OUTPUT_EXEC="$OPTION_EACSL_OUTPUT_EXEC" +fi + +# Build E-ACSL plugin argument string +if [ -n "$OPTION_EACSL" ]; then + EACSL_FLAGS=" + $OPTION_THEN + $OPTION_EACSL + $OPTION_GMP + $OPTION_LIBC_REPLACEMENTS + $OPTION_FULL_MMODEL + $OPTION_TEMPORAL + $OPTION_VERBOSE + $OPTION_DEBUG + $OPTION_VALIDATE_FORMAT_STRINGS + -e-acsl-share="$EACSL_SHARE" + -then-last" +fi + +# Instrument +if [ -n "$OPTION_INSTRUMENT" ]; then + ($OPTION_ECHO; \ + $FRAMAC \ + $FRAMAC_FLAGS \ + $MACHDEP \ + -cpp-extra-args="$FRAMAC_CPP_EXTRA" \ + $OPTION_FRAMA_STDLIB \ + "$@" \ + $RTE_FLAGS \ + $EACSL_FLAGS \ + -print -ocode "$OPTION_OUTPUT_CODE"); + error "aborted by Frama-C" $?; +fi + +# Compile +if [ -n "$OPTION_COMPILE" ]; then + # Compile original source code + # $OPTION_INSTRUMENT is set -- both, instrumented and original, sources are + # available. Do compile the original program unless instructed to not do so + # by a user + if [ -n "$OPTION_INSTRUMENT" ]; then + if [ -z "$OPTION_INSTRUMENTED_ONLY" ]; then + ($OPTION_ECHO; $CC $CPPFLAGS $CFLAGS "$@" -o "$OUTPUT_EXEC" $LDFLAGS); + error "fail to compile/link un-instrumented code" $?; + fi + # If $OPTION_INSTRUMENT is unset then the sources are assumed to be already + # instrumented, so skip compilation of the original files + else + OUTPUT_CODE="$@" + fi + + # Compile and link E-ACSL-instrumented file with all models specified + for model in $OPTION_EACSL_MMODELS; do + # If multiple models are specified then the generated executable + # is appended a '-MODEL' suffix, where MODEL is the name of the memory + # model used + if ! [ "`echo $OPTION_EACSL_MMODELS | wc -w`" = 1 ]; then + OUTPUT_EXEC="$EACSL_OUTPUT_EXEC-$model" + else + OUTPUT_EXEC="$EACSL_OUTPUT_EXEC" + fi + # RTL sources + EACSL_RTL="$EACSL_SHARE/e_acsl_rtl.c" + EACSL_MMODEL_FEATURES="$(mmodel_features $model)" + ($OPTION_ECHO; + $CC \ + $EACSL_MMODEL_FEATURES \ + $CFLAGS $CPPFLAGS \ + $EACSL_CFLAGS $EACSL_CPPFLAGS \ + -o "$OUTPUT_EXEC" \ + $OUTPUT_CODE \ + $EACSL_RTL \ + $LDFLAGS \ + $EACSL_LDFLAGS) + error "fail to compile/link instrumented code" $? + done +fi +exit 0; diff --git a/src/plugins/e-acsl/share/e-acsl/bittree_model/e_acsl_bittree.h b/src/plugins/e-acsl/share/e-acsl/bittree_model/e_acsl_bittree.h new file mode 100644 index 0000000000000000000000000000000000000000..d581f762e9d7614755c9a05369eb2bfa614a5f19 --- /dev/null +++ b/src/plugins/e-acsl/share/e-acsl/bittree_model/e_acsl_bittree.h @@ -0,0 +1,469 @@ +/**************************************************************************/ +/* */ +/* This file is part of the Frama-C's E-ACSL plug-in. */ +/* */ +/* Copyright (C) 2012-2018 */ +/* CEA (Commissariat à l'énergie atomique et aux énergies */ +/* alternatives) */ +/* */ +/* you can redistribute it and/or modify it under the terms of the GNU */ +/* Lesser General Public License as published by the Free Software */ +/* Foundation, version 2.1. */ +/* */ +/* It is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Lesser General Public License for more details. */ +/* */ +/* See the GNU Lesser General Public License version 2.1 */ +/* for more details (enclosed in the file licenses/LGPLv2.1). */ +/* */ +/**************************************************************************/ + +/*! *********************************************************************** + * \file e_acsl_bittree.h + * \brief Patricia Trie API Implementation +***************************************************************************/ + +#ifndef E_ACSL_BITTREE +#define E_ACSL_BITTREE + +#define WORDBITS __WORDSIZE + +static size_t mask(size_t, size_t); + +#if WORDBITS == 16 + +static const size_t Tmasks[] = { +0x0,0x8000,0xc000,0xe000,0xf000,0xf800,0xfc00,0xfe00,0xff00,0xff80,0xffc0, +0xffe0,0xfff0,0xfff8,0xfffc,0xfffe,0xffff}; + +static const int Teq[] = {0,-1,3,-3,6,-5,7,-7,12,-9,11,-11,14,-13,15,16,-16}; +static const int Tneq[] = {0,0,1,-2,2,-4,5,-6,4,-8,9,-10,10,-12,13,-14,-15}; + +#elif WORDBITS == 32 + +static const size_t Tmasks[] = { +0x0,0x80000000,0xc0000000,0xe0000000,0xf0000000,0xf8000000,0xfc000000, +0xfe000000,0xff000000,0xff800000,0xffc00000,0xffe00000,0xfff00000,0xfff80000, +0xfffc0000,0xfffe0000,0xffff0000,0xffff8000,0xffffc000,0xffffe000,0xfffff000, +0xfffff800,0xfffffc00,0xfffffe00,0xffffff00,0xffffff80,0xffffffc0,0xffffffe0, +0xfffffff0,0xfffffff8,0xfffffffc,0xfffffffe,0xffffffff}; + +static const int Teq[] = + { 0,-1,3,-3,6,-5,7,-7,12,-9,11,-11,14,-13,15,-15,24,-17,19,-19,22, + -21,23,-23,28,-25,27,-27,30,-29,31,32,-32 }; + +static const int Tneq[] = + { 0,0,1,-2,2,-4,5,-6,4,-8,9,-10,10,-12,13,-14,8,-16,17,-18,18,-20,21,-22,20, + -24,25,-26,26,-28,29,-30,-31 }; + +#else /* WORDBITS == 64 */ + +static const size_t Tmasks[] = { +0x0,0x8000000000000000,0xc000000000000000,0xe000000000000000,0xf000000000000000, +0xf800000000000000,0xfc00000000000000,0xfe00000000000000,0xff00000000000000, +0xff80000000000000,0xffc0000000000000,0xffe0000000000000,0xfff0000000000000, +0xfff8000000000000,0xfffc000000000000,0xfffe000000000000,0xffff000000000000, +0xffff800000000000,0xffffc00000000000,0xffffe00000000000,0xfffff00000000000, +0xfffff80000000000,0xfffffc0000000000,0xfffffe0000000000,0xffffff0000000000, +0xffffff8000000000,0xffffffc000000000,0xffffffe000000000,0xfffffff000000000, +0xfffffff800000000,0xfffffffc00000000,0xfffffffe00000000,0xffffffff00000000, +0xffffffff80000000,0xffffffffc0000000,0xffffffffe0000000,0xfffffffff0000000, +0xfffffffff8000000,0xfffffffffc000000,0xfffffffffe000000,0xffffffffff000000, +0xffffffffff800000,0xffffffffffc00000,0xffffffffffe00000,0xfffffffffff00000, +0xfffffffffff80000,0xfffffffffffc0000,0xfffffffffffe0000,0xffffffffffff0000, +0xffffffffffff8000,0xffffffffffffc000,0xffffffffffffe000,0xfffffffffffff000, +0xfffffffffffff800,0xfffffffffffffc00,0xfffffffffffffe00,0xffffffffffffff00, +0xffffffffffffff80,0xffffffffffffffc0,0xffffffffffffffe0,0xfffffffffffffff0, +0xfffffffffffffff8,0xfffffffffffffffc,0xfffffffffffffffe,0xffffffffffffffff}; + +static const int Teq[] = + { 0,-1,3,-3,6,-5,7,-7,12,-9,11,-11,14,-13,15,-15,24,-17,19,-19,22,-21,23,-23, + 28,-25,27,-27,30,-29,31,-31,48,-33,35,-35,38,-37,39,-39,44,-41,43,-43,46, + -45,47,-47,56,-49,51,-51,54,-53,55,-55,60,-57,59,-59,62,-61,63,64,-64 }; + +static const int Tneq[] = + { 0,0,1,-2,2,-4,5,-6,4,-8,9,-10,10,-12,13,-14,8,-16,17,-18,18,-20,21,-22,20, + -24,25,-26,26,-28,29,-30,16,-32,33,-34,34,-36,37,-38,36,-40,41,-42,42,-44, + 45,-46,40,-48,49,-50,50,-52,53,-54,52,-56,57,-58,58,-60,61,-62,-63 }; + +#endif + +/*! \brief Root node of the bitree */ +static bt_node * bt_root = NULL; + +/* common prefix of two addresses */ +/*@ assigns \nothing; + @ ensures \forall int i; + 0 <= i <= WORDBITS + ==> (Tmasks[i] & a) == (Tmasks[i] & b) + ==> \result >= Tmasks[i]; + @ ensures (a & \result) == (b & \result); + @ ensures \exists int i; 0 <= i <= WORDBITS && \result == Tmasks[i]; + @*/ +static size_t mask(size_t a, size_t b) { + size_t nxor = ~(a ^ b), ret; + int i = WORDBITS/2; /* dichotomic search, starting in the middle */ + /*cpt_mask++;*/ + + /* if the current mask matches we use transition from Teq, else from Tneq + we stop as soon as i is negative, meaning that we found the mask + a negative element i from Teq or Tneq means stop and return Tmasks[-i] */ + /*@ loop invariant -WORDBITS <= i <= WORDBITS; + @ loop assigns i; + @*/ + while(i > 0) { + //@ assert 0 < i <= WORDBITS; + //@ assert \valid(Tmasks+i); + if (nxor >= Tmasks[i]) + //@ assert \valid(Teq+i); + i = Teq[i]; + else + //@ assert \valid(Tneq+i); + i = Tneq[i]; + } + + //@ assert -WORDBITS <= i <= 0; + ret = Tmasks[-i]; + DASSERT ((a & ret) == (b & ret)); + return ret; +} + + +/* called from bt_remove */ +/* the block we are looking for has to be in the tree */ +/*@ requires \valid(ptr); + @ requires \valid(bt_root); + @ assigns \nothing; + @ ensures \valid(\result); + @ ensures \result->leaf == ptr; + @*/ +static bt_node * bt_get_leaf_from_block (bt_block * ptr) { + bt_node * curr = bt_root; + DASSERT(bt_root != NULL); + DASSERT(ptr != NULL); + + /*@ loop assigns curr; + @*/ + while(!curr->is_leaf) { + // the prefix is consistent + DASSERT((curr->addr & curr->mask) == (ptr->ptr & curr->mask)); + // two children + DASSERT(curr->left != NULL && curr->right != NULL); + // the prefix of one child is consistent + if((curr->right->addr & curr->right->mask) + == (ptr->ptr & curr->right->mask)) + curr = curr->right; + else if((curr->left->addr & curr->left->mask) + == (ptr->ptr & curr->left->mask)) + curr = curr->left; + else + vassert(0, "Unreachable", NULL); + } + DASSERT(curr->is_leaf); + DASSERT(curr->leaf == ptr); + return curr; +} + + +/* remove the block from the structure */ +/* the block we are looking for has to be in the tree */ +/*@ requires \valid(ptr); + @*/ +static void bt_remove (bt_block * ptr) { + bt_node * leaf_to_delete = bt_get_leaf_from_block (ptr); + DASSERT(leaf_to_delete->leaf == ptr); + + if(leaf_to_delete->parent == NULL) + // the leaf is the root + bt_root = NULL; + else { + bt_node * sibling, * parent; + parent = leaf_to_delete->parent; + sibling = (leaf_to_delete == parent->left) ? parent->right : parent->left; + DASSERT(sibling != NULL); + // copying all sibling's fields into the parent's + parent->is_leaf = sibling->is_leaf; + parent->addr = sibling->addr; + parent->mask = sibling->mask; + parent->left = sibling->left; + parent->right = sibling->right; + parent->leaf = sibling->leaf; + if(!sibling->is_leaf) { + sibling->left->parent = parent; + sibling->right->parent = parent; + } + private_free(sibling); + /* necessary ? -- begin */ + if(parent->parent != NULL) { + parent->parent->mask = mask(parent->parent->left->addr + & parent->parent->left->mask, + parent->parent->right->addr + & parent->parent->right->mask); + } + /* necessary ? -- end */ + } + private_free(leaf_to_delete); +} + + +/* called from bt_insert */ +/* the returned node will be the sibling of the soon to be added node */ +/*@ requires \valid(ptr); + @ requires \valid(bt_root); + @ assigns \nothing; + @ ensures \valid(\result); + @*/ +static bt_node * bt_most_similar_node (bt_block * ptr) { + bt_node * curr = bt_root; + size_t left_prefix, right_prefix; + DASSERT(ptr != NULL); + DASSERT(bt_root != NULL); + + while(1) { + if(curr->is_leaf) + return curr; + DASSERT(curr->left != NULL && curr->right != NULL); + left_prefix = mask(curr->left->addr & curr->left->mask, ptr->ptr); + right_prefix = mask(curr->right->addr & curr->right->mask, ptr->ptr); + if(left_prefix > right_prefix) + curr = curr->left; + else if(right_prefix > left_prefix) + curr = curr->right; + else + return curr; + } +} + +/* add a block in the structure */ +/*@ requires \valid(ptr); + @*/ +static void bt_insert (bt_block * ptr) { + bt_node * new_leaf; + DASSERT(ptr != NULL); + + new_leaf = private_malloc(sizeof(bt_node)); + DASSERT(new_leaf != NULL); + new_leaf->is_leaf = 1; + new_leaf->addr = ptr->ptr; + new_leaf->mask = Tmasks[WORDBITS]; /* ~0ul */ + new_leaf->left = NULL; + new_leaf->right = NULL; + new_leaf->parent = NULL; + new_leaf->leaf = ptr; + + if(bt_root == NULL) + bt_root = new_leaf; + else { + bt_node * sibling = bt_most_similar_node (ptr), * parent, * aux; + + DASSERT(sibling != NULL); + parent = private_malloc(sizeof(bt_node)); + DASSERT(parent != NULL); + parent->is_leaf = 0; + parent->addr = sibling->addr & new_leaf->addr; + /*parent->mask = mask(sibling->addr & sibling->mask, ptr->ptr);*/ + parent->leaf = NULL; + if(new_leaf->addr <= sibling->addr) { + parent->left = new_leaf; + parent->right = sibling; + } else { + parent->left = sibling; + parent->right = new_leaf; + } + new_leaf->parent = parent; + + if(sibling == bt_root) { + parent->parent = NULL; + parent->mask = mask(sibling->addr & sibling->mask, ptr->ptr); + bt_root = parent; + } else { + if (sibling->parent->left == sibling) + sibling->parent->left = parent; + else + sibling->parent->right = parent; + parent->parent = sibling->parent; + + /* necessary ? -- begin */ + aux = parent; + aux->mask = mask(aux->left->addr & aux->left->mask, + aux->right->addr & aux->right->mask); + /* necessary ? -- end */ + } + sibling->parent = parent; + if(!sibling->is_leaf) + sibling->mask = mask(sibling->left->addr & sibling->left->mask, + sibling->right->addr & sibling->right->mask); + + DASSERT((parent->left == sibling && parent->right == new_leaf) + || (parent->left == new_leaf && parent->right == sibling)); + } +} + +/* return the block B such as: begin addr of B == ptr if such a block exists, + return NULL otherwise */ +/*@ assigns \nothing; + @ ensures \valid(\result); + @ ensures \result == \null || \result->ptr == (size_t)ptr; + @*/ +static bt_block * bt_lookup (void * ptr) { + bt_node * tmp = bt_root; + DASSERT(bt_root != NULL); + DASSERT(ptr != NULL); + + /*@ loop assigns tmp; + @*/ + while(!tmp->is_leaf) { + // if the ptr we are looking for does not share the prefix of tmp + if((tmp->addr & tmp->mask) != ((size_t)ptr & tmp->mask)) + return NULL; + + // two children + DASSERT(tmp->left != NULL && tmp->right != NULL); + // the prefix of one child is consistent + if((tmp->right->addr & tmp->right->mask) + == ((size_t)ptr & tmp->right->mask)) + tmp = tmp->right; + else if((tmp->left->addr & tmp->left->mask) + == ((size_t)ptr & tmp->left->mask)) + tmp = tmp->left; + else + return NULL; + } + + if(tmp->leaf->ptr != (size_t)ptr) + return NULL; + return tmp->leaf; +} + +/* return the block B containing ptr, such as : + begin addr of B <= ptr < (begin addr + size) of B + or NULL if such a block does not exist */ +static bt_block * bt_find (void * ptr) { + bt_node * tmp = bt_root; + if(bt_root == NULL || ptr == NULL) + return NULL; + + bt_node * other_choice = NULL; + + while(1) { + if(tmp->is_leaf) { + /* tmp cannot contain ptr because its begin addr is higher */ + if(tmp->addr > (size_t)ptr) + return NULL; + + /* tmp->addr <= ptr, tmp may contain ptr + ptr is contained if tmp is large enough (begin addr + size) */ + else if((size_t)ptr < tmp->leaf->size + tmp->addr + || (tmp->leaf->size == 0 && (size_t)ptr == tmp->leaf->ptr)) + return tmp->leaf; + /* tmp->addr <= ptr, but tmp->addr is not large enough */ + else + return NULL; + } + + DASSERT(tmp->left != NULL && tmp->right != NULL); + + /* the right child has the highest address, so we test it first */ + if(((size_t)tmp->right->addr & tmp->right->mask) + <= ((size_t)ptr & tmp->right->mask)) { + other_choice = tmp->left; + tmp = tmp->right; + } + else if(((size_t)tmp->left->addr & tmp->left->mask) + <= ((size_t)ptr & tmp->left->mask)) + tmp = tmp->left; + else { + if(other_choice == NULL) + return NULL; + else { + tmp = other_choice; + other_choice = NULL; + } + } + } +} + +/*******************/ +/* CLEAN */ +/*******************/ +/* erase information about initialization of a block */ +static void bt_clean_block_init (bt_block * ptr) { + if(ptr->init_ptr != NULL) { + private_free(ptr->init_ptr); + ptr->init_ptr = NULL; + } + ptr->init_bytes = 0; +} + +/* erase all information about a block */ +static void bt_clean_block (bt_block * ptr) { + if(ptr) { + bt_clean_block_init(ptr); + private_free(ptr); + } +} + +/* called from bt_clean */ +/* recursively erase the content of the structure */ +static void bt_clean_rec (bt_node * ptr) { + if(ptr == NULL) return; + else if(ptr->is_leaf) { + bt_clean_block(ptr->leaf); + ptr->leaf = NULL; + } + else { + bt_clean_rec(ptr->left); + bt_clean_rec(ptr->right); + ptr->left = ptr->right = NULL; + } + private_free(ptr); +} + +/* erase the content of the structure */ +static void bt_clean () { + bt_clean_rec(bt_root); + bt_root = NULL; +} + +/*********************/ +/* DEBUG */ +/*********************/ +#ifdef E_ACSL_DEBUG +static void bt_print_block(bt_block * ptr) { + if (ptr != NULL) { + DLOG("%a; %lu Bytes; %slitteral; [init] : %d ", + (char*)ptr->ptr, ptr->size, + ptr->is_readonly ? "" : "not ", ptr->init_bytes); + if(ptr->init_ptr != NULL) { + unsigned i; + for(i = 0; i < ptr->size/8; i++) + DLOG("%b ", ptr->init_ptr[i]); + } + DLOG("\n"); + } +} + +static void bt_print_node(bt_node * ptr, int depth) { + int i; + if(ptr == NULL) + return; + for(i = 0; i < depth; i++) + DLOG(" "); + if(ptr->is_leaf) + bt_print_block(ptr->leaf); + else { + DLOG("%p -- %p\n", (void*)ptr->mask, (void*)ptr->addr); + bt_print_node(ptr->left, depth+1); + bt_print_node(ptr->right, depth+1); + } +} + +static void bt_print_tree() { + DLOG("------------DEBUG\n"); + bt_print_node(bt_root, 0); + DLOG("-----------------\n"); +} +#endif +#endif diff --git a/src/plugins/e-acsl/share/e-acsl/bittree_model/e_acsl_bittree_api.h b/src/plugins/e-acsl/share/e-acsl/bittree_model/e_acsl_bittree_api.h new file mode 100644 index 0000000000000000000000000000000000000000..ae566998e006910950415c72be7e6506449b4f72 --- /dev/null +++ b/src/plugins/e-acsl/share/e-acsl/bittree_model/e_acsl_bittree_api.h @@ -0,0 +1,101 @@ +/**************************************************************************/ +/* */ +/* This file is part of the Frama-C's E-ACSL plug-in. */ +/* */ +/* Copyright (C) 2012-2018 */ +/* CEA (Commissariat à l'énergie atomique et aux énergies */ +/* alternatives) */ +/* */ +/* you can redistribute it and/or modify it under the terms of the GNU */ +/* Lesser General Public License as published by the Free Software */ +/* Foundation, version 2.1. */ +/* */ +/* It is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Lesser General Public License for more details. */ +/* */ +/* See the GNU Lesser General Public License version 2.1 */ +/* for more details (enclosed in the file licenses/LGPLv2.1). */ +/* */ +/**************************************************************************/ + +/*! *********************************************************************** + * \file e_acsl_bittree_api.h + * \brief Patricia Trie API +***************************************************************************/ + +#ifndef E_ACSL_BITTREE_API +#define E_ACSL_BITTREE_API + +/*! \brief Structure representing an allocated memory block */ +struct bt_block { + size_t ptr; //!< Base address + size_t size; //!< Block length (in bytes) + unsigned char * init_ptr; //!< Per-bit initialization + size_t init_bytes; //!< Number of initialized bytes within a block + int is_readonly; //!< True if a block is marked read-only + int is_freeable; //!< True if a block can be de-allocated using `free` +#ifdef E_ACSL_DEBUG + size_t line; //!< Line number where this block was recorded + char* file; //!< File name where this block was recorded +#endif +#ifdef E_ACSL_TEMPORAL + uint32_t timestamp; //!< Temporal timestamp of a block's creation + void *temporal_shadow; //!< Temporal shadow for storing referent numbers +#endif +}; + +typedef struct bt_block bt_block; + +/*! \brief Structure representing a bittree node */ +struct bt_node { + int is_leaf; + size_t addr, mask; + struct bt_node * left, * right, * parent; + bt_block * leaf; +}; + +typedef struct bt_node bt_node; + +/*! \brief Remove a block from the structure */ +static void bt_remove(bt_block *b); + +/*! \brief Add a block to the structure */ +static void bt_insert(bt_block *b); + +/*! \brief Look-up a memory block by its base address + NB: The function assumes that such a block exists. */ +static bt_block * bt_lookup(void *ptr); + +/*! \brief Find a memory block containing a given memory address + * + * Return block B such that: + * `\base_addr(B->ptr) <= ptr < (\base_addr(B->ptr) + size)` + * or NULL if such a block does not exist. */ +static bt_block * bt_find(void *ptr); + +/*! \brief Erase the contents of the structure */ +static void bt_clean(void); + +/*! \brief Erase information about a block's initialization */ +static void bt_clean_block_init(bt_block *b); + +/*! \brief Erase all information about a given block */ +static void bt_clean_block(bt_block *b); + +#ifdef E_ACSL_DEBUG +/*! \brief Print information about a given block */ +static void bt_print_block(bt_block *b); + +/*! \brief Recursively print the contents of the bittree starting from a + * given node */ +/*@ assigns \nothing; */ +static void bt_print_node(bt_node * ptr, int depth); + +/*! \brief Print the contents of the entire bittree */ +/*@ assigns \nothing; */ +static void bt_print(); +#endif + +#endif diff --git a/src/plugins/e-acsl/share/e-acsl/bittree_model/e_acsl_bittree_mmodel.c b/src/plugins/e-acsl/share/e-acsl/bittree_model/e_acsl_bittree_mmodel.c new file mode 100644 index 0000000000000000000000000000000000000000..eafd0b80772ba11cbc38559fbe2a34258ae325c0 --- /dev/null +++ b/src/plugins/e-acsl/share/e-acsl/bittree_model/e_acsl_bittree_mmodel.c @@ -0,0 +1,710 @@ +/**************************************************************************/ +/* */ +/* This file is part of the Frama-C's E-ACSL plug-in. */ +/* */ +/* Copyright (C) 2012-2018 */ +/* CEA (Commissariat à l'énergie atomique et aux énergies */ +/* alternatives) */ +/* */ +/* you can redistribute it and/or modify it under the terms of the GNU */ +/* Lesser General Public License as published by the Free Software */ +/* Foundation, version 2.1. */ +/* */ +/* It is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Lesser General Public License for more details. */ +/* */ +/* See the GNU Lesser General Public License version 2.1 */ +/* for more details (enclosed in the file licenses/LGPLv2.1). */ +/* */ +/**************************************************************************/ + +/*! *********************************************************************** + * \file e_acsl_bittree_mmodel.c + * \brief Implementation of E-ACSL public API using a memory model based + * on Patricia Trie. See e_acsl.h for details. +***************************************************************************/ + +# include "e_acsl_bittree_api.h" +# include "e_acsl_bittree.h" + +static inline int allocated(uintptr_t addr, long size, uintptr_t base_ptr); +static inline int writeable(uintptr_t addr, long size, uintptr_t base_ptr); + +/* Public API {{{ */ +/* Debug */ +#ifdef E_ACSL_DEBUG +# define bt_print_block export_alias(bt_print_block) +# define bt_print_tree export_alias(bt_print_tree) +# define block_info export_alias(block_info) +# define store_block_debug export_alias(store_block_debug) +# define delete_block_debug export_alias(delete_block_debug) +#endif +/* }}} */ + +#define E_ACSL_MMODEL_DESC "patricia trie" + +/* Assertions in debug mode */ +#ifdef E_ACSL_DEBUG +/* Assert that memory block [_addr, _addr + _size] is allocated */ +# define DVALIDATE_ALLOCATED(_addr, _size, _base) \ + vassert(allocated((uintptr_t)_addr, _size, (uintptr_t)_base), \ + "Operation on unallocated block [%a + %lu] with base %a\n", \ + _addr, _size, _base); + +/* Assert that memory block [_addr, _addr + _size] is allocated + * and can be written to */ +# define DVALIDATE_WRITEABLE(_addr, _size, _base) \ + vassert(writeable((uintptr_t)_addr, _size, (uintptr_t)_base), \ + "Operation on unallocated block [%a + %lu] with base %a\n", \ + _addr, _size, _base); +#else +#define DVALIDATE_ALLOCATED(_ptr, _size, _base) +#define DVALIDATE_WRITEABLE(_ptr, _size, _base) +#endif + +/**************************/ +/* SUPPORT {{{ */ +/**************************/ +static const int nbr_bits_to_1[256] = { + 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,1,2,2,3,2,3, + 3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,1,2,2,3,2,3,3,4,2,3,3,4, + 3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4, + 4,5,4,5,5,6,4,5,5,6,5,6,6,7,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5, + 3,4,4,5,4,5,5,6,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6, + 6,7,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,3,4,4,5, + 4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8 +}; + +/* given the size of the memory block (_size) return (or rather evaluate to) + * size in bytes required to represent its partial initialization */ +#define needed_bytes(_size) \ + ((_size % 8) == 0 ? (_size/8) : (_size/8 + 1)) +/* }}} */ + +/**************************/ +/* LOCATION (DEBUG MODE) {{{ */ +/**************************/ +#ifdef E_ACSL_DEBUG +/* Notion of current location for debugging purposes */ +static struct current_location { + int line; + char *file; +} cloc = { 0, "undefined" }; + +#define update_cloc(_file, _line) { cloc.line = _line; cloc.file = _file; } +#endif +/* }}} */ + +/**************************/ +/* INITIALIZATION {{{ */ +/**************************/ + +/* mark the size bytes of ptr as initialized */ +void initialize (void * ptr, size_t size) { + bt_block * tmp; + if(!ptr) + return; + + tmp = bt_find(ptr); + if(tmp == NULL) + return; + + /* already fully initialized, do nothing */ + if(tmp->init_bytes == tmp->size) + return; + + /* fully uninitialized */ + if(tmp->init_bytes == 0) { + int nb = needed_bytes(tmp->size); + tmp->init_ptr = private_malloc(nb); + memset(tmp->init_ptr, 0, nb); + } + + /* partial initialization is kept via a character array accessible via the + * tmp->init_ptr. This is such that a N-th bit of tmp->init_ptr tracks + * initialization of the N-th byte of the memory block tracked by tmp. + * + * The following sets individual bits in tmp->init_ptr that track + * initialization of `size' bytes starting from `ptr'. */ + unsigned i; + for(i = 0; i < size; i++) { + /* byte-offset within the block, i.e., mark `offset' byte as initialized */ + size_t offset = (uintptr_t)ptr - tmp->ptr + i; + /* byte offset within tmp->init_ptr, i.e., a byte containing the bit to + be toggled */ + int byte = offset/8; + /* bit-offset within the above byte, i.e., bit to be toggled */ + int bit = offset%8; + + if (!checkbit(bit, tmp->init_ptr[byte])) { /* if bit is unset ... */ + setbit(bit, tmp->init_ptr[byte]); /* ... set the bit ... */ + tmp->init_bytes++; /* ... and increment initialized bytes count */ + } + } + + /* now fully initialized */ + if(tmp->init_bytes == tmp->size) { + private_free(tmp->init_ptr); + tmp->init_ptr = NULL; + } +} + +/* mark all bytes of ptr as initialized */ +void full_init (void * ptr) { + bt_block * tmp; + if (ptr == NULL) + return; + + tmp = bt_lookup(ptr); + if (tmp == NULL) + return; + + if (tmp->init_ptr != NULL) { + private_free(tmp->init_ptr); + tmp->init_ptr = NULL; + } + tmp->init_bytes = tmp->size; +} + +/* mark a block as read-only */ +void mark_readonly(void * ptr) { + bt_block * tmp; + if (ptr == NULL) + return; + tmp = bt_lookup(ptr); + if (tmp == NULL) + return; + tmp->is_readonly = 1; +} +/* }}} */ + +/**************************/ +/* PREDICATES {{{ */ +/**************************/ + +int freeable(void* ptr) { + bt_block * tmp; + if(ptr == NULL) + return 0; + tmp = bt_lookup(ptr); + if(tmp == NULL) + return 0; + return tmp->is_freeable; +} + +/* return whether the size bytes of ptr are initialized */ +int initialized(void * ptr, size_t size) { + unsigned i; + bt_block * tmp = bt_find(ptr); + if(tmp == NULL) + return 0; + + /* fully uninitialized */ + if(tmp->init_bytes == 0) + return 0; + /* fully initialized */ + if(tmp->init_bytes == tmp->size) + return 1; + + /* see implementation of function `initialize` for details */ + for(i = 0; i < size; i++) { + size_t offset = (uintptr_t)ptr - tmp->ptr + i; + int byte = offset/8; + int bit = offset%8; + if (!checkbit(bit, tmp->init_ptr[byte])) + return 0; + } + return 1; +} + +/** \brief \return the length (in bytes) of the block containing ptr */ +size_t block_length(void* ptr) { + bt_block * blk = bt_find(ptr); + /* Hard failure when un-allocated memory is used */ + vassert(blk != NULL, "\\block_length of unallocated memory", NULL); + return blk->size; +} + +/** \brief check whether a memory block containing address given via `ptr` + of length `size` and with base address `ptr_base` belongs to tracked + allocation and return corresponding `bt_block` if so. Return NULL + otherwise. */ +static bt_block* lookup_allocated(void* ptr, size_t size, void *ptr_base) { + bt_block * blk = bt_find(ptr); + if (blk == NULL) + return NULL; +#ifndef E_ACSL_WEAK_VALIDITY + bt_block * blk_base = bt_find(ptr_base); + if (blk_base == NULL || blk->ptr != blk_base->ptr) + return NULL; +#endif + return (blk->size - ((size_t)ptr - blk->ptr) >= size) ? blk : NULL; +} + +/** \brief same as ::lookup_allocated but return either `1` or `0` depending + on whether the memory block described by this function's arguments is + allocated or not. + NOTE: Should have same signature in all models. */ +static inline int allocated(uintptr_t addr, long size, uintptr_t base) { + return lookup_allocated((void*)addr, size, (void*)base) == NULL ? 0 : 1; +} + +/** \brief Return 1 if a given memory location is read-only and 0 otherwise */ +static int readonly (void *ptr) { + bt_block * blk = bt_find(ptr); + vassert(blk != NULL, "Readonly on unallocated memory", NULL); + return blk->is_readonly; +} + +/** \brief same as ::allocated but returns `0` if the memory block described + by the arguments cannot be written to */ +static inline int writeable(uintptr_t addr, long size, uintptr_t base_ptr) { + return allocated(addr, size, base_ptr) && !readonly((void*)addr); +} + +/* return whether the size bytes of ptr are readable/writable */ +int valid(void* ptr, size_t size, void *ptr_base, void *addrof_base) { + bt_block * blk = lookup_allocated(ptr, size, ptr_base); + return blk != NULL && !blk->is_readonly +#ifdef E_ACSL_TEMPORAL + && temporal_valid(ptr_base, addrof_base) +#endif + ; +} + +/* return whether the size bytes of ptr are readable */ +int valid_read(void* ptr, size_t size, void *ptr_base, void *addrof_base) { + bt_block * blk = lookup_allocated(ptr, size, ptr_base); + return blk != NULL +#ifdef E_ACSL_TEMPORAL + && temporal_valid(ptr_base, addrof_base) +#endif + ; +} + +/* return the base address of the block containing ptr */ +void* base_addr(void* ptr) { + bt_block * tmp = bt_find(ptr); + vassert(tmp != NULL, "\\base_addr of unallocated memory", NULL); + return (void*)tmp->ptr; +} + +/* return the offset of `ptr` within its block */ +size_t offset(void* ptr) { + bt_block * tmp = bt_find(ptr); + vassert(tmp != NULL, "\\offset of unallocated memory", NULL); + return ((uintptr_t)ptr - tmp->ptr); +} +/* }}} */ + +/**************************/ +/* ALLOCATION {{{ */ +/**************************/ + +/* STACK ALLOCATION {{{ */ +/* store the block of size bytes starting at ptr, the new block is returned. + * Warning: the return type is implicitly (bt_block*). */ +void* store_block(void *ptr, size_t size) { +#ifdef E_ACSL_DEBUG + if (ptr == NULL) + vabort("Attempt to record NULL block"); + else { + char *check = (char*)ptr; + bt_block *exitsing_block = bt_find(ptr); + if (exitsing_block) { + vabort("\nRecording %a [%lu] at %s:%d failed." + " Overlapping block %a [%lu] found at %s:%d\n", + ptr, size, cloc.file, cloc.line, base_addr(check), + block_length(check), exitsing_block->file, exitsing_block->line); + } + check += size - 1; + exitsing_block = bt_find(check); + if (exitsing_block) { + vabort("\nRecording %a [%lu] at %d failed." + " Overlapping block %a [%lu] found at %s:%d\n", + ptr, size, cloc.file, cloc.line, base_addr(check), + block_length(check), exitsing_block->file, exitsing_block->line); + } + } +#endif + bt_block *tmp = NULL; + if (ptr) { + tmp = private_malloc(sizeof(bt_block)); + tmp->ptr = (uintptr_t)ptr; + tmp->size = size; + tmp->init_ptr = NULL; + tmp->init_bytes = 0; + tmp->is_readonly = 0; + tmp->is_freeable = 0; + bt_insert(tmp); +#ifdef E_ACSL_DEBUG + tmp->line = 0; + tmp->file = "undefined"; +#endif +#ifdef E_ACSL_TEMPORAL + tmp->timestamp = NEW_TEMPORAL_TIMESTAMP(); + tmp->temporal_shadow = (size >= sizeof(void*)) ? + private_malloc(size) : NULL; +#endif + } + return tmp; +} + +/* Track a heap block. This is a wrapper for all memory allocation functions + that create new bittree nodes. It applies to all memory allocating functions + but realloc that modifies nodes rather than create them */ +static void *store_freeable_block(void *ptr, size_t size, int init_bytes) { + bt_block *blk = NULL; + if (ptr) { + blk = store_block(ptr, size); + blk->is_freeable = 1; + update_heap_allocation(size); + if (init_bytes) + blk->init_bytes = size; + } + return blk; +} + +/* remove the block starting at ptr */ +void delete_block(void *ptr) { +#ifdef E_ACSL_DEBUG + /* Make sure the recorded block is not NULL */ + if (!ptr) + vabort("Attempt to delete NULL block"); +#endif + if (ptr != NULL) { + bt_block *tmp = bt_lookup(ptr); +#ifdef E_ACSL_DEBUG + /* Make sure the removed block exists in the tracked allocation */ + if (!tmp) + vabort("Attempt to delete untracked block"); +#endif + if (tmp) { + bt_clean_block_init(tmp); +#ifdef E_ACSL_TEMPORAL + private_free(tmp->temporal_shadow); +#endif + bt_remove(tmp); + private_free(tmp); + } + } +} + +void* store_block_duplicate(void* ptr, size_t size) { + bt_block * tmp = NULL; + if (ptr != NULL) { + bt_block * tmp = bt_lookup(ptr); + if (tmp) { +#ifdef E_ACSL_DEBUG + /* Make sure that duplicate block, if so is of the same length */ + if (tmp->size != size) + vabort("Attempt to store duplicate block of different length"); +#endif + delete_block(ptr); + } + store_block(ptr, size); + } + return tmp; +} + +/* }}} */ + +/* HEAP ALLOCATION {{{ */ +/*! \brief Replacement for `malloc` with memory tracking */ +void* malloc(size_t size) { + if (size == 0) + return NULL; + + void *res = public_malloc(size); + store_freeable_block(res, size, 0); + return res; +} + +/*! \brief Replacement for `calloc` with memory tracking */ +void* calloc(size_t nbr_block, size_t size_block) { + /* FIXME: Need an integer overflow check here */ + size_t size = nbr_block * size_block; + if (size == 0) + return NULL; + + void *res = public_calloc(nbr_block, size_block); + store_freeable_block(res, size, 1); + return res; +} + +/*! \brief Replacement for `aligned_alloc` with memory tracking */ +void *aligned_alloc(size_t alignment, size_t size) { + /* Check if: + - size and alignment are greater than zero + - alignment is a power of 2 + - size is a multiple of alignment */ + if (!size || !alignment || !powof2(alignment) || (size%alignment)) + return NULL; + + void *res = public_aligned_alloc(alignment, size); + store_freeable_block(res, size, 0); + return res; +} + +/*! \brief Replacement for `posix_memalign` with memory tracking */ +int posix_memalign(void **memptr, size_t alignment, size_t size) { + /* Check if: + * - size and alignment are greater than zero + * - alignment is a power of 2 and a multiple of sizeof(void*) */ + if (!size || !alignment || !powof2(alignment) || alignment%sizeof(void*)) + return -1; + + /* Make sure that the first argument to posix memalign is indeed allocated */ + DVALIDATE_WRITEABLE(memptr, sizeof(void*), memptr); + + int res = public_posix_memalign(memptr, alignment, size); + if (!res) + store_freeable_block(*memptr, size, 0); + return res; +} + +/*! \brief Replacement for `realloc` with memory tracking */ +void* realloc(void *ptr, size_t size) { + bt_block * tmp; + void * new_ptr; + /* ptr is NULL - malloc */ + if(ptr == NULL) + return malloc(size); + /* size is zero - free */ + if(size == 0) { + free(ptr); + return NULL; + } + tmp = bt_lookup(ptr); + DASSERT(tmp != NULL); + new_ptr = public_realloc((void*)tmp->ptr, size); + if (new_ptr == NULL) + return NULL; + + /* update the heap allocation size to `size - tmp->size` while keeping + constant the number of allocated blocks */ + update_heap_allocation(size); + update_heap_allocation(-tmp->size); + /* realloc changes start address -- re-enter the element */ + if (tmp->ptr != (uintptr_t)new_ptr) { + bt_remove(tmp); + tmp->ptr = (uintptr_t)new_ptr; + bt_insert(tmp); + } + /* uninitialized, do nothing */ + if(tmp->init_bytes == 0) ; + /* already fully initialized block */ + else if (tmp->init_bytes == tmp->size) { + /* realloc smaller block */ + if (size <= tmp->size) { + /* adjust new size, allocation not necessary */ + tmp->init_bytes = size; + /* realloc larger block */ + } else { + /* size of tmp->init_ptr in the new block */ + int nb = needed_bytes(size); + /* number of bits that need to be set in tmp->init_ptr */ + int nb_old = needed_bytes(tmp->size); + /* allocate memory to store partial initialization */ + tmp->init_ptr = private_calloc(1, nb); + /* carry out initialization of the old block */ + setbits(tmp->size, tmp->init_ptr); + } + } else { /* contains initialized and uninitialized parts */ + int nb = needed_bytes(size); + int nb_old = needed_bytes(tmp->size); + int i; + /* increase container with init data */ + tmp->init_ptr = private_realloc(tmp->init_ptr, nb); + for (i = nb_old; i < nb; i++) + tmp->init_ptr[i] = 0; + tmp->init_bytes = 0; + for (i = 0; i < nb; i++) + tmp->init_bytes += nbr_bits_to_1[tmp->init_ptr[i]]; + if (tmp->init_bytes == size || tmp->init_bytes == 0) { + private_free(tmp->init_ptr); + tmp->init_ptr = NULL; + } + } + tmp->size = size; + tmp->is_freeable = 1; + return (void*)tmp->ptr; +} + +/*! \brief Replacement for `free` with memory tracking */ +void free(void *ptr) { + if (ptr == NULL) { +/* Fail if instructed to treat NULL input to free as invalid. */ +#ifdef E_ACSL_FREE_VALID_ADDRESS + vabort("NULL pointer in free\n"); +#endif + return; + } + bt_block *res = bt_lookup(ptr); + if (!res) { + vabort("Not a start of block (%a) in free\n", ptr); + } else { + update_heap_allocation(-res->size); + public_free(ptr); + bt_clean_block_init(res); + bt_remove(res); + } +} +/* }}} */ +/* }}} */ + +/******************************/ +/* PROGRAM INITIALIZATION {{{ */ +/******************************/ + +/* erase the content of the abstract structure */ +void memory_clean() { + bt_clean(); + report_heap_leaks(); +} + +/* POSIX-compliant array of character pointers to the environment strings. */ +extern char **environ; + +/* add `argv` to the memory model */ +static void argv_alloca(int *argc_ref, char *** argv_ref) { + /* Track a top-level containers */ + store_block((void*)argc_ref, sizeof(int)); + store_block((void*)argv_ref, sizeof(char**)); + int argc = *argc_ref; + char** argv = *argv_ref; + /* Track argv */ + + size_t argvlen = (argc + 1)*sizeof(char*); + store_block(argv, argvlen); + initialize(argv, (argc + 1)*sizeof(char*)); + + while (*argv) { + size_t arglen = strlen(*argv) + 1; + store_block(*argv, arglen); + initialize(*argv, arglen); + argv++; + } + +#ifdef E_ACSL_TEMPORAL /* Fill temporal shadow */ + int i; + argv = *argv_ref; + temporal_store_nblock(argv_ref, *argv_ref); + for (i = 0; i < argc; i++) + temporal_store_nblock(argv + i, *(argv+i)); +#endif + + while (*environ) { + size_t envlen = strlen(*environ) + 1; + store_block(*environ, envlen); + initialize(*environ, envlen); + environ++; + } +} + +void memory_init(int *argc_ref, char ***argv_ref, size_t ptr_size) { + describe_run(); + /* Mspace sizes here are not that relevant as there is no shadowing and + mspaces will grow automatically */ + make_memory_spaces(MB_SZ(64), MB_SZ(64)); + arch_assert(ptr_size); + initialize_report_file(argc_ref, argv_ref); + /* Tracking program arguments */ + if (argc_ref) + argv_alloca(argc_ref, argv_ref); + /* Tracking safe locations */ + collect_safe_locations(); + int i; + for (i = 0; i < safe_location_counter; i++) { + void *addr = (void*)safe_locations[i].address; + uintptr_t len = safe_locations[i].length; + store_block(addr, len); + if (safe_locations[i].is_initialized) + initialize(addr, len); + } + init_infinity_values(); +} +/* }}} */ + +/******************************/ +/* DEBUG PRINT {{{ */ +/******************************/ + +#ifdef E_ACSL_DEBUG +/* Debug version of store block with location tracking. This function is aimed + * at manual debugging. While there is no easy way of traking file/line numbers + * recorded memory blocks with the use of the following macros placed after the + * declaration of __e_acsl_store_block: + * + * #define __e_acsl_store_block(...) \ + * __e_acsl_store_block_debug(__FILE__, __LINE__, __VA_ARGS__) + * + * The above macros with rewrite of instances of __e_acsl_store_block generating + * origin information of tracked memory blocks. +*/ +void* store_block_debug(char *file, int line, void* ptr, size_t size) { + update_cloc(file, line); + bt_block * res = store_block(ptr, size); + if (res) { + res->line = line; + res->file = file; + } + return res; +} + +void delete_block_debug(char *file, int line, void* ptr) { + update_cloc(file, line); + bt_block * tmp = bt_lookup(ptr); + if (!tmp) { + vabort("Block with base address %a not found in the memory model at %s:%d", + ptr, file, line); + } + delete_block(ptr); +} + +/* Debug print of block information */ +void block_info(char *p) { + bt_block * res = bt_find(p); + if (res) { + DLOG(" << %a >> %a [%lu] => %lu \n", + p, base_addr(p), offset(p), block_length(p)); + } else { + DLOG(" << %a >> not allocated\n", p); + } +} +#endif +/* }}} */ + +/* Local operations on temporal timestamps {{{ */ +/* Remaining functionality (shared between all models) is located in e_acsl_temporal.h */ +#ifdef E_ACSL_TEMPORAL +static uint32_t origin_timestamp(void *ptr) { + bt_block * blk = bt_find(ptr); + return blk != NULL ? blk->timestamp : INVALID_TEMPORAL_TIMESTAMP; +} + +static uintptr_t temporal_referent_shadow(void *ptr) { + bt_block *blk = bt_find(ptr); + vassert(blk != NULL, + "referent timestamp on unallocated memory address %a", (uintptr_t)ptr); + vassert(blk->temporal_shadow != NULL, + "no temporal shadow of block with base address", (uintptr_t)blk->ptr); + return (uintptr_t)blk->temporal_shadow + offset(ptr); +} + +static uint32_t referent_timestamp(void *ptr) { + bt_block * blk = bt_find(ptr); + if (blk != NULL) + return *((uint32_t*)temporal_referent_shadow(ptr)); + else + return INVALID_TEMPORAL_TIMESTAMP; +} + +static void store_temporal_referent(void *ptr, uint32_t ref) { + uint32_t *shadow = (uint32_t*)temporal_referent_shadow(ptr); + *shadow = ref; +} +#endif +/* }}} */ diff --git a/src/plugins/e-acsl/share/e-acsl/e_acsl.h b/src/plugins/e-acsl/share/e-acsl/e_acsl.h new file mode 100644 index 0000000000000000000000000000000000000000..a9378dc8c3481c5c6808e3fd9c269a4a4caf2e13 --- /dev/null +++ b/src/plugins/e-acsl/share/e-acsl/e_acsl.h @@ -0,0 +1,568 @@ +/**************************************************************************/ +/* */ +/* This file is part of the Frama-C's E-ACSL plug-in. */ +/* */ +/* Copyright (C) 2012-2018 */ +/* CEA (Commissariat à l'énergie atomique et aux énergies */ +/* alternatives) */ +/* */ +/* you can redistribute it and/or modify it under the terms of the GNU */ +/* Lesser General Public License as published by the Free Software */ +/* Foundation, version 2.1. */ +/* */ +/* It is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Lesser General Public License for more details. */ +/* */ +/* See the GNU Lesser General Public License version 2.1 */ +/* for more details (enclosed in the file licenses/LGPLv2.1). */ +/* */ +/**************************************************************************/ + +/*! *********************************************************************** + * \file e_acsl.h + * \brief Public C API of E-ACSL Runtime Library + * + * Functions and variables with non-static linkage used for instrumentation. +***************************************************************************/ + +#ifndef E_ACSL_MMODEL_H +#define E_ACSL_MMODEL_H + +#include <stddef.h> +#include <stdio.h> +#include "e_acsl_alias.h" + +/************************************************************************/ +/*** API Prefixes {{{ ***/ +/************************************************************************/ + +/* Assert */ +#define sound_verdict export_alias(sound_verdict) +#define assert export_alias(assert) + +/* Tracking */ +#define delete_block export_alias(delete_block) +#define store_block export_alias(store_block) +#define store_block_duplicate export_alias(store_block_duplicate) + +/* Predicates */ +#define offset export_alias(offset) +#define base_addr export_alias(base_addr) +#define block_length export_alias(block_length) +#define valid_read export_alias(valid_read) +#define valid export_alias(valid) +#define initialized export_alias(initialized) +#define freeable export_alias(freeable) + +/* Block initialization */ +#define mark_readonly export_alias(mark_readonly) +#define initialize export_alias(initialize) +#define full_init export_alias(full_init) + +/* Libc drop-in replacements */ +#define builtin_strlen export_alias(builtin_strlen) +#define builtin_strcpy export_alias(builtin_strcpy) +#define builtin_strncpy export_alias(builtin_strncpy) +#define builtin_strcat export_alias(builtin_strcat) +#define builtin_strncat export_alias(builtin_strncat) +#define builtin_strncat export_alias(builtin_strncat) +#define builtin_strcmp export_alias(builtin_strcmp) +#define builtin_strncmp export_alias(builtin_strncmp) +#define builtin_memcpy export_alias(builtin_memcpy) +#define builtin_memset export_alias(builtin_memset) +#define builtin_memcmp export_alias(builtin_memcmp) +#define builtin_memmove export_alias(builtin_memmove) + +/* stdio.h replacement functions */ +#define builtin_printf export_alias(builtin_printf) +#define builtin_fprintf export_alias(builtin_fprintf) +#define builtin_dprintf export_alias(builtin_dprintf) +#define builtin_sprintf export_alias(builtin_sprintf) +#define builtin_snprintf export_alias(builtin_snprintf) +#define builtin_syslog export_alias(builtin_syslog) + +/* Memory state initialization */ +#define memory_clean export_alias(memory_clean) +#define mspaces_init export_alias(mspaces_init) +#define memory_init export_alias(memory_init) + +/* Heap size */ +#define heap_allocation_size export_alias(heap_allocation_size) +#define get_heap_allocation_size export_alias(get_heap_allocation_size) + +/* Temporal analysis */ +/* No need to encapsulate via ifdef: using these extra definitions does + not hurt, otherwise need to pass additional parameters to frama-c */ +#define temporal_store_nblock export_alias(temporal_store_nblock) +#define temporal_store_nreferent export_alias(temporal_store_nreferent) +#define temporal_save_nblock_parameter export_alias(temporal_save_nblock_parameter) +#define temporal_save_nreferent_parameter export_alias(temporal_save_nreferent_parameter) +#define temporal_save_copy_parameter export_alias(temporal_save_copy_parameter) +#define temporal_pull_parameter export_alias(temporal_pull_parameter) +#define temporal_save_return export_alias(temporal_save_return) +#define temporal_reset_parameters export_alias(temporal_reset_parameters) +#define temporal_pull_return export_alias(temporal_pull_return) +#define temporal_reset_return export_alias(temporal_reset_return) +#define temporal_memcpy export_alias(temporal_memcpy) +#define temporal_memset export_alias(temporal_memset) + +/* Infinity values for floating point types */ +#define math_HUGE_VAL export_alias(math_HUGE_VAL) +#define math_HUGE_VALF export_alias(math_HUGE_VALF) +#define math_INFINITY export_alias(math_INFINITY) +#define floating_point_exception export_alias(floating_point_exception) +/* }}} */ + +/************************************************************************/ +/*** Assertion {{{ ***/ +/************************************************************************/ + +/*! \brief Runtime assertion verifying a given predicate + * \param pred integer code of a predicate + * \param kind C string representing a kind an annotation (e.g., "Assertion") + * \param fct + * \param pred_txt stringified predicate + * \param line line of predicate placement in the un-instrumented file */ +/*@ requires pred != 0; + @ assigns \nothing; */ +void assert(int pred, char *kind, char *fct, char *pred_txt, int line) + __attribute__((FC_BUILTIN)); +/* }}} */ + +/************************************************************************/ +/*** Dynamic memory allocation {{{ ***/ +/************************************************************************/ + +/*! \brief Drop-in replacement for \p malloc with memory tracking enabled. + * For further information, see \p malloc(3). */ +void * malloc(size_t size) + __attribute__((FC_BUILTIN)); + +/*! \brief Drop-in replacement for \p calloc with memory tracking enabled. + * For further information, see \p calloc(3). */ +void * calloc(size_t nbr_elt, size_t size_elt) + __attribute__((FC_BUILTIN)); + +/*! \brief Drop-in replacement for \p realloc with memory tracking enabled. + * For further information, see realloc(3) */ +void * realloc(void * ptr, size_t size) + __attribute__((FC_BUILTIN)); + +/*! \brief Drop-in replacement for \p free with memory tracking enabled. + * For further information, see \p free(3). */ +void free(void * ptr) + __attribute__((FC_BUILTIN)); + +/*! \brief Allocate `size` bytes of memory such that the allocation's base + * address is an even multiple of alignment. + * + * \param alignment - should be the power of two + * \param size - should be the multiple of alignment + * \return - pointer to the allocated memory if the restrictions placed on size + * and alignment parameters hold. NULL is returned otherwise. */ +void *aligned_alloc(size_t alignment, size_t size) + __attribute__((FC_BUILTIN)); + +/*! \brief Allocate size bytes and place the address of the allocated memory in + * `*memptr`. The address of the allocated memory will be a multiple of + * `alignment`, which must be a power of two and a multiple of `sizeof(void*)`. + * If size is 0, then the value placed in *memptr is NULL. */ +int posix_memalign(void **memptr, size_t alignment, size_t size) + __attribute__((FC_BUILTIN)); +/* }}} */ + +/************************************************************************/ +/*** Memory tracking {{{ ***/ +/************************************************************************/ + +/*! \brief Initialize memory locations. */ +void mspaces_init() + __attribute__((FC_BUILTIN)); + +/*! \brief Initialize memory tracking state. + * Called before any other statement in \p main */ +/*@ assigns \nothing; */ +void memory_init(int *argc_ref, char ***argv, size_t ptr_size) + __attribute__((FC_BUILTIN)); + +/*! \brief Clean-up memory tracking state before a program's termination. */ +/*@ assigns \nothing; */ +void memory_clean(void) + __attribute__((FC_BUILTIN)); + +/*! \brief Store stack or globally-allocated memory block + * starting at an address given by \p ptr. + * + * \param ptr base address of the tracked memory block + * \param size size of the tracked block in bytes */ +/*@ ensures \result == ptr; + @ assigns \result \from *(((char*)ptr)+(0..size-1)), ptr, size; */ +void * store_block(void * ptr, size_t size) + __attribute__((FC_BUILTIN)); + +/*! \brief Same as `store_block`, but first check + * checks whether a block with a base address given by `ptr` exists in the + * tracked allocation and remove it before storing a new block. + * + * \param ptr base address of the tracked memory block + * \param size size of the tracked block in bytes */ +/*@ ensures \result == ptr; + @ assigns \result \from *(((char*)ptr)+(0..size-1)), ptr, size; */ +void * store_block_duplicate(void * ptr, size_t size) + __attribute__((FC_BUILTIN)); + +/*! \brief Remove a memory block which base address is \p ptr from tracking. */ +/*@ assigns \nothing; */ +void delete_block(void * ptr) + __attribute__((FC_BUILTIN)); + +/*! \brief Mark the \p size bytes starting at an address given by \p ptr as + * initialized. */ +/*@ assigns \nothing; */ +void initialize(void * ptr, size_t size) + __attribute__((FC_BUILTIN)); + +/*! \brief Mark all bytes belonging to a memory block which start address is + * given by \p ptr as initialized. */ +/*@ assigns \nothing; */ +void full_init(void * ptr) + __attribute__((FC_BUILTIN)); + +/*! \brief Mark a memory block which start address is given by \p ptr as + * read-only. */ +/*@ assigns \nothing; */ +void mark_readonly(void * ptr) + __attribute__((FC_BUILTIN)); + +/*! \brief A variable holding a byte size of tracked heap allocation. */ +extern size_t heap_allocation_size; + +/*@ predicate diffSize{L1,L2}(integer i) = + \at(heap_allocation_size, L1) + - \at(heap_allocation_size, L2) == i; */ + +/*! \brief Return the cumulative size (in bytes) of tracked heap allocation. */ +/*@ assigns \result \from heap_allocation_size; */ +size_t get_heap_allocation_size(void) + __attribute__((FC_BUILTIN)); + +/* }}} */ + +/************************************************************************/ +/*** E-ACSL predicates {{{ ***/ +/************************************************************************/ + +/*!\brief Implementation of the \b \\freeable predicate of E-ACSL. + * + * Evaluate to a non-zero value if \p ptr points to a start address of + * a block allocated via \p malloc, \p calloc or \p realloc. */ +/*@ assigns \result \from ptr; */ +int freeable(void * ptr) + __attribute__((FC_BUILTIN)); + +/*! \brief Implementation of the \b \\valid predicate of E-ACSL. + * + * \\valid evaluates an expression of the form `p+i`, where `p` is a pointer + * and `i` is an integer offset and returns `true` if both `p` and `p+i` belong + * to the same allocated memory block. + * + * @param ptr - memory address under question + * @param size - the byte-length (starting from `ptr`) of the memory area which + * needs to be valid + * @param base - if `ptr` can be represented by the expression `p+i` then + * `base` refers to `p` + * @param addrof_base - if `ptr` can be represented by the expression `p+i` + * then `addrof_base` refers to `&p`. For the cases when the address of `p` + * cannot be taken (e.g., address of a static array or a constant value + * casted to a pointer) then `addrof_base` is zero. + * + * @returns + * `true` if regions `[ptr, ptr + size]` and `[base, base + size]` are + * writable and lie within the same memory block and `false` otherwise. + * If `weak validity` is used (see macro `E_ACSL_WEAK_VALIDITY`) + * then only region `[ptr, ptr + size]` should lie within the same block + * and be writable. + */ +/*@ assigns \result \from *(((char*)ptr)+(0..size-1)), ptr, size; + @ behavior valid: + @ assumes \valid(((char *)ptr)+(0..size-1)); + @ assumes + @ size <= 0 || + @ ! \separated(((char *)ptr)+(0..size-1), + @ ((char *)\base_addr(base))+(0..\block_length(base)-1)); + @ ensures \result == 1; + @ behavior invalid_ptr: + @ assumes ! \valid(((char *)ptr)+(0..size-1)); + @ ensures \result == 0; + @ behavior separated_ptr: + @ assumes size > 0; + @ assumes \separated(((char *)ptr)+(0..size-1), + @ ((char *)\base_addr(base))+(0..\block_length(base)-1)); + @ ensures \result == 0; + @ complete behaviors; + @ disjoint behaviors; + @ */ +int valid(void * ptr, size_t size, void *base, void *addrof_base) + __attribute__((FC_BUILTIN)); + +/*! \brief Implementation of the \b \\valid_read predicate of E-ACSL. + * + * Same as ::valid except the checked memory locations are only + * required to be allocated. */ +/*@ assigns \result \from *(((char*)ptr)+(0..size-1)), ptr, size; + @ behavior valid: + @ assumes \valid_read(((char *)ptr)+(0..size-1)); + @ assumes + @ size <= 0 || + @ ! \separated(((char *)ptr)+(0..size-1), + @ ((char *)\base_addr(base))+(0..\block_length(base)-1)); + @ ensures \result == 1; + @ behavior invalid_ptr: + @ assumes ! \valid_read(((char *)ptr)+(0..size-1)); + @ ensures \result == 0; + @ behavior separated_ptr: + @ assumes size > 0; + @ assumes \separated(((char *)ptr)+(0..size-1), + @ ((char *)\base_addr(base))+(0..\block_length(base)-1)); + @ ensures \result == 0; + @ complete behaviors; + @ disjoint behaviors; + @ */ +int valid_read(void * ptr, size_t size, void *base, void *addrof_base) + __attribute__((FC_BUILTIN)); + +/*! \brief Implementation of the \b \\base_addr predicate of E-ACSL. + * Return the base address of the memory block containing an address given + * by \p ptr */ +/*@ ensures \result == \base_addr(ptr); + @ assigns \result \from ptr; */ +void * base_addr(void * ptr) + __attribute__((FC_BUILTIN)); + +/*! \brief Implementation of the \b \\block_length predicate of E-ACSL. + * Return the byte length of the memory block of the block containing a memory + * address given by \p ptr */ +/*@ ensures \result == \block_length(ptr); + @ assigns \result \from ptr; */ +size_t block_length(void * ptr) + __attribute__((FC_BUILTIN)); + +/*! \brief Implementation of the \b \\offset predicate of E-ACSL. + * Return the byte offset of address given by \p ptr within a memory blocks + * it belongs to */ +/*@ ensures \result == \offset(ptr); + @ assigns \result \from ptr; */ +size_t offset(void * ptr) + __attribute__((FC_BUILTIN)); + +/*! \brief Implementation of the \b \\initialized predicate of E-ACSL. + * Return a non-zero value if \p size bytes starting from an address given by + * \p ptr are initialized and zero otherwise. */ +/*@ assigns \result \from *(((char*)ptr)+(0..size-1)), ptr, size; + @ behavior initialized: + @ assumes \initialized(((char *)ptr)+(0..size-1)); + @ ensures \result == 1; + @ behavior uninitialized: + @ assumes ! \initialized(((char *)ptr)+(0..size-1)); + @ ensures \result == 0; + @ complete behaviors; + @ disjoint behaviors; + @ */ +int initialized(void * ptr, size_t size) + __attribute__((FC_BUILTIN)); +/* }}} */ + +/************************************************************************/ +/*** Drop-in replacement functions {{{ ***/ +/************************************************************************/ + +/*@ assigns dest[0..] \from src[0..]; + @ assigns \result \from dest; + @ ensures \result == dest; */ +char *builtin_strcpy(char *dest, const char *src) + __attribute__((FC_BUILTIN)); + +/*@ assigns dest[0..n - 1] \from src[0..n-1]; + @ assigns \result \from dest; + @ ensures \result == dest; */ +char *builtin_strncpy(char *dest, const char *src, size_t n) + __attribute__((FC_BUILTIN)); + +/*@ assigns \result \from s[0..]; */ +size_t builtin_strlen(const char *s) + __attribute__((FC_BUILTIN)); + +/*@ assigns dest[..] \from src[0..]; + @ assigns \result \from dest; + @ ensures \result == dest; */ +char *builtin_strcat(char *dest, const char *src) + __attribute__((FC_BUILTIN)); + +/*@ assigns dest[..] \from src[0..n]; + @ assigns \result \from dest; + @ ensures \result == dest; */ +char *builtin_strncat(char *dest, const char *src, size_t n) + __attribute__((FC_BUILTIN)); + +/*@ assigns \result \from s1[0..], s2[0..]; */ +int builtin_strcmp(const char *s1, const char *s2) + __attribute__((FC_BUILTIN)); + +/*@ assigns \result \from s1[0..n-1], s2[0..n-1]; */ +int builtin_strncmp(const char *s1, const char *s2, size_t n) + __attribute__((FC_BUILTIN)); + +/*@ assigns ((char*)dest)[0..n-1] \from ((char*)src)[0..n-1]; + @ assigns \result \from dest; + @ ensures \result == dest; */ +void *builtin_memcpy(void *dest, const void *src, size_t n) + __attribute__((FC_BUILTIN)); + +/*@ assigns ((char*)s)[0..n-1] \from c; + @ assigns \result \from s; + @ ensures \result == s; */ +void *builtin_memset(void *s, int c, size_t n) + __attribute__((FC_BUILTIN)); + +/*@ assigns ((char*)dest)[0..n-1] \from ((char*)src)[0..n-1]; + @ assigns \result \from dest; + @ ensures \result == dest; */ +void *builtin_memmove(void *dest, const void *src, size_t n) + __attribute__((FC_BUILTIN)); + +/*@ assigns \result \from ((char*)s1)[0..n-1], ((char*)s2)[0..n-1]; */ +int builtin_memcmp(const void *s1, const void *s2, size_t n) + __attribute__((FC_BUILTIN)); + +/* }}} */ + +/************************************************************************/ +/*** Format functions {{{ ***/ +/************************************************************************/ + +/** \brief `printf` with error checking. */ +int builtin_printf(const char *fmtdesc, const char *fmt, ...) + __attribute__((FC_BUILTIN)); + +/** \brief `fprintf` with error checking. */ +int builtin_fprintf(const char *fmtdesc, FILE *stream, const char *fmt, ...) + __attribute__((FC_BUILTIN)); + +/** \brief `dprintf` with error checking. */ +int builtin_dprintf(const char *fmtdesc, int fd, const char *fmt, ...) + __attribute__((FC_BUILTIN)); + +/** \brief `sprintf` with error checking. */ +int builtin_sprintf(const char *fmtdesc, char *str, const char *fmt, ...) + __attribute__((FC_BUILTIN)); + +/** \brief `snprintf` with error checking. */ +int builtin_snprintf + (const char *fmtdesc, char *str, size_t size, const char *fmt, ...) + __attribute__((FC_BUILTIN)); + +/** \brief `syslog` with error checking. */ +int builtin_syslog(const char *fmtdesc, int priority, const char *fmt, ...) + __attribute__((FC_BUILTIN)); +/* }}} */ + +/************************************************************************/ +/*** Machine-dependent infinity values for flating points {{{ ***/ +/************************************************************************/ + +/* Positive infinity for doubles: same as HUGE_VAL */ +extern double math_HUGE_VAL + __attribute__((FC_BUILTIN)); + +/* Positive infinity for floats: same as HUGE_VALF */ +extern float math_HUGE_VALF + __attribute__((FC_BUILTIN)); + +/* Representation of infinity value for doubles: same as INFINITY */ +extern double math_INFINITY + __attribute__((FC_BUILTIN)); + +/* Check for floating point exception at a given execution point */ +extern void floating_point_exception(const char *s) + __attribute__((FC_BUILTIN)); +/* }}} */ + +/************************************************************************/ +/*** Temporal analysis {{{ ***/ +/************************************************************************/ + +/*! \brief Take origin number of a memory block containing `block_addr` and + * store it as a referent number of a pointer given by `ptr_addr`. */ +/*@ assigns \nothing; */ +void temporal_store_nblock(void *ptr_addr, void *block_addr) + __attribute__((FC_BUILTIN)); + +/*! \brief Same as `temporal_store_nblock` but take a referent + * number of `block_addr` instead */ +/*@ assigns \nothing; */ +void temporal_store_nreferent(void *ptr_addr, void *block_addr) + __attribute__((FC_BUILTIN)); + +/*! \brief store struct { .ptr = ptr, .temporal_flow = TReferentN } + * in the global parameter array. */ +/*@ assigns \nothing; */ +void temporal_save_nreferent_parameter(void *ptr, unsigned int param) + __attribute__((FC_BUILTIN)); + +/*! \brief store struct { .ptr = ptr, .temporal_flow = TBlockN } + * in the global parameter array. */ +/*@ assigns \nothing; */ +void temporal_save_nblock_parameter(void *ptr, unsigned int param) + __attribute__((FC_BUILTIN)); + +/*! \brief store struct { .ptr = ptr, .temporal_flow = TCopy } in the global + * parameter array. */ +/*@ assigns \nothing; */ +void temporal_save_copy_parameter(void *ptr, unsigned int param) + __attribute__((FC_BUILTIN)); + +/*! \brief Assign a referent number of `ptr` based on the record in the global + * parameter array at index `param`. */ +/*@ assigns \nothing; */ +void temporal_pull_parameter(void *ptr, unsigned int param, size_t size) + __attribute__((FC_BUILTIN)); + +/*! \brief Nullify global parameter array */ +/*@ assigns \nothing; */ +void temporal_reset_parameters() + __attribute__((FC_BUILTIN)); + +/*! \brief Save temporal referent number of `ptr` in a placeholder variable + * tracking the referent number of a function's return. */ +/*@ assigns \nothing; */ +void temporal_save_return(void *ptr) + __attribute__((FC_BUILTIN)); + +/*! \brief Take a temporal referent stored in the placeholder tracking return + * values as a temporal referent number of `ptr`. */ +/*@ assigns \nothing; */ +void temporal_pull_return(void *ptr) + __attribute__((FC_BUILTIN)); + +/*! \brief Nullify a placeholder variable tracking the referent number of a + * function's return. */ +/*@ assigns \nothing; */ +void temporal_reset_return() + __attribute__((FC_BUILTIN)); + +/*! \brief Copy temporal shadow data from [src, src + size] to + * [dest, dest + size]. Counterpart of the memcpy function */ +/*@ assigns \nothing; */ +void temporal_memcpy(void *dest, void *src, size_t size) + __attribute__((FC_BUILTIN)); + +/*! \brief Set temporal shadow data from [src, src + size] to 0. + * Counterpart of memset the function */ +/*@ assigns \nothing; */ +void temporal_memset(void *dest, int n, size_t size) + __attribute__((FC_BUILTIN)); + +/* }}} */ +#endif diff --git a/src/plugins/e-acsl/share/e-acsl/e_acsl_alias.h b/src/plugins/e-acsl/share/e-acsl/e_acsl_alias.h new file mode 100644 index 0000000000000000000000000000000000000000..17518ac0333574bd6a084f5eede66c14899a642c --- /dev/null +++ b/src/plugins/e-acsl/share/e-acsl/e_acsl_alias.h @@ -0,0 +1,40 @@ +/**************************************************************************/ +/* */ +/* This file is part of the Frama-C's E-ACSL plug-in. */ +/* */ +/* Copyright (C) 2012-2018 */ +/* CEA (Commissariat à l'énergie atomique et aux énergies */ +/* alternatives) */ +/* */ +/* you can redistribute it and/or modify it under the terms of the GNU */ +/* Lesser General Public License as published by the Free Software */ +/* Foundation, version 2.1. */ +/* */ +/* It is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Lesser General Public License for more details. */ +/* */ +/* See the GNU Lesser General Public License version 2.1 */ +/* for more details (enclosed in the file licenses/LGPLv2.1). */ +/* */ +/**************************************************************************/ + +/*! *********************************************************************** + * \file e_acsl_alias.h + * + * \brief Function aliasing +***************************************************************************/ + +#ifndef E_ACSL_ALIAS_H +#define E_ACSL_ALIAS_H + +/* Concatenation of 2 tokens */ +# define preconcat(x,y) x ## y +# define concat(x,y) preconcat(x,y) +/** Prefix of public functions */ +# define export_prefix __e_acsl_ +/** Add public prefix to an identifier */ +# define export_alias(_n) concat(export_prefix, _n) + +#endif diff --git a/src/plugins/e-acsl/share/e-acsl/e_acsl_assert.h b/src/plugins/e-acsl/share/e-acsl/e_acsl_assert.h new file mode 100644 index 0000000000000000000000000000000000000000..9090e7c7e79f172a44376980a4f7667eec181132 --- /dev/null +++ b/src/plugins/e-acsl/share/e-acsl/e_acsl_assert.h @@ -0,0 +1,139 @@ +/**************************************************************************/ +/* */ +/* This file is part of the Frama-C's E-ACSL plug-in. */ +/* */ +/* Copyright (C) 2012-2018 */ +/* CEA (Commissariat à l'énergie atomique et aux énergies */ +/* alternatives) */ +/* */ +/* you can redistribute it and/or modify it under the terms of the GNU */ +/* Lesser General Public License as published by the Free Software */ +/* Foundation, version 2.1. */ +/* */ +/* It is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Lesser General Public License for more details. */ +/* */ +/* See the GNU Lesser General Public License version 2.1 */ +/* for more details (enclosed in the file licenses/LGPLv2.1). */ +/* */ +/**************************************************************************/ + +/*! *********************************************************************** + * \file e_acsl_assert.h + * \brief E-ACSL assertions and abort statements. +***************************************************************************/ + +#ifndef E_ACSL_ASSERT_H +#define E_ACSL_ASSERT_H + +#include <sys/types.h> +#include <signal.h> +#include <limits.h> +#include "e_acsl_alias.h" +#include "e_acsl_printf.h" +#include "e_acsl_string.h" +#include "e_acsl_trace.h" + +#define runtime_assert export_alias(assert) +#define runtime_sound_verdict export_alias(sound_verdict) + +/*! \brief Drop-in replacement for abort function */ +#define runtime_abort() exec_abort(__LINE__, __FILE__) + +/*! \brief Output a message to error stream using printf-like format string + * and abort the execution. + * + * This is a wrapper for \p eprintf combined with \p abort */ +static void vabort(char *fmt, ...); + +/*! \brief Assert with printf-like error message support */ +#define vassert(expr, fmt, ...) \ + vassert_fail(expr, __LINE__, __FILE__, fmt, __VA_ARGS__) + +/* This ::exec_abort replaces `abort` via a macro at the top of this file */ +static void exec_abort(int line, const char *file) { +#ifdef E_ACSL_DEBUG +#ifndef E_ACSL_NO_TRACE + trace(); +#endif +#endif + raise(SIGABRT); +} + +/*! \brief Print a message to stderr and abort the execution */ +static void vabort(char *fmt, ...) { + va_list va; + sigset_t defer_abrt; + sigemptyset(&defer_abrt); + sigaddset(&defer_abrt,SIGABRT); + sigprocmask(SIG_BLOCK,&defer_abrt,NULL); + va_start(va,fmt); + _format(NULL,_charc_stderr,fmt,va); + va_end(va); + sigprocmask(SIG_UNBLOCK,&defer_abrt,NULL); + runtime_abort(); +} + +static void vassert_fail(int expr, int line, char *file, char *fmt, ...) { + if (!expr) { + char *afmt = "%s at %s:%d\n"; + char buf [strlen(fmt) + strlen(afmt) + PATH_MAX + 11]; + rtl_sprintf(buf, afmt, fmt, file, line); + fmt = buf; + + va_list va; + va_start(va,fmt); + _format(NULL,_charc_stderr,fmt,va); + va_end(va); + runtime_abort(); + } +} + +#ifdef E_ACSL_NO_ASSERT_FAIL +# define E_ACSL_ASSERT_NO_FAIL_DESC "pass through" +#else +# define E_ACSL_ASSERT_NO_FAIL_DESC "abort" +#endif + +/*! E-ACSL instrumentation automatically sets this global to 0 if its verdict + becomes unsound. + TODO: may only happen for annotations containing memory-related properties. + For arithmetic properties, the verdict is always sound (?). */ +int runtime_sound_verdict = 1; + +#ifndef E_ACSL_EXTERNAL_ASSERT +/*! \brief Default implementation of E-ACSL runtime assertions */ +void runtime_assert(int predicate, char *kind, char *fct, char *pred_txt, int line) { + if (runtime_sound_verdict) { + if (! predicate) { + STDERR("%s failed at line %d (function %s).\n" + "The failing predicate is:\n%s.\n", kind, line, fct, pred_txt); +#ifndef E_ACSL_NO_ASSERT_FAIL /* Do fail on assertions */ +#ifdef E_ACSL_FAIL_EXITCODE /* Fail by exit with a given code */ + exit(E_ACSL_FAIL_EXITCODE); +#else + runtime_abort(); /* Raise abort signal */ +#endif +#endif + } + } else + STDERR("warning: no sound verdict (guess: %s) at line %d " + "(function %s).\nThe considered predicate is:\n%s.\n", + predicate ? "ok" : "FAIL", + line, fct, pred_txt); +} +#endif + +/* Instances of assertions shared accross different memory models */ + +/*! \brief Abort the execution if the size of the pointer computed during + * instrumentation (\p _ptr_sz) does not match the size of the pointer used + * by a compiler (\p void*) */ +#define arch_assert(_ptr_sz) \ + vassert(_ptr_sz == sizeof(void*), \ + "Mismatch of instrumentation- and compile-time pointer sizes: " \ + "%lu vs %lu\n", _ptr_sz, sizeof(void*)) + +#endif diff --git a/src/plugins/e-acsl/share/e-acsl/e_acsl_bits.h b/src/plugins/e-acsl/share/e-acsl/e_acsl_bits.h new file mode 100644 index 0000000000000000000000000000000000000000..f13e46264b7b6d3641142422e3d88870ac973f9d --- /dev/null +++ b/src/plugins/e-acsl/share/e-acsl/e_acsl_bits.h @@ -0,0 +1,191 @@ +/**************************************************************************/ +/* */ +/* This file is part of the Frama-C's E-ACSL plug-in. */ +/* */ +/* Copyright (C) 2012-2018 */ +/* CEA (Commissariat à l'énergie atomique et aux énergies */ +/* alternatives) */ +/* */ +/* you can redistribute it and/or modify it under the terms of the GNU */ +/* Lesser General Public License as published by the Free Software */ +/* Foundation, version 2.1. */ +/* */ +/* It is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Lesser General Public License for more details. */ +/* */ +/* See the GNU Lesser General Public License version 2.1 */ +/* for more details (enclosed in the file licenses/LGPLv2.1). */ +/* */ +/**************************************************************************/ + +/*! *********************************************************************** + * \file e_acsl_bits.h + * \brief Bit-level manipulations and endianness checks. + * + * Should be included after e_acsl_printf.h and e_acsl_string.h headers. + * + * FIXME: Present implementation is built for little-endian byte order. That + * is, the implementation assumes that least significant bytes are stored at + * the highest memory addresses. In future support for big-endian/PDP byte + * orders should also be provided. + * + * CAUTION: As per above FIXME notice, all examples, macros and functions + * assume little-endian byte order. +***************************************************************************/ + +#ifndef E_ACSL_BITS_H +#define E_ACSL_BITS_H + +#include <stdint.h> +#include <stddef.h> + +/* Check if we have little-endian and abort the execution otherwise. */ +#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +# error "Big-endian byte order is unsupported" +#elif __BYTE_ORDER__ == __ORDER_PDP_ENDIAN__ +# error "PDP-endian byte order is unsupported" +#elif __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__ +# error "Unknown byte order" +#endif + +/* Bit-level manipulations {{{ */ + +/* 64-bit type with all bits set to ones */ +#define ONE UINT64_MAX + +/* 64-bit type with all bits set to zeroes */ +#define ZERO (~ONE) + +/* Set a given bit in a number to '1' (least-significant bit is at index zero). + * Example: + * int x = 0; // x => 0000 0000 ... + * bitset(0, x) // x => 1000 0000 ... + * bitset(7, x) // x => 1000 0001 ... */ +#define setbit(_bit,_number) (_number |= 1 << _bit) + +/* Same as bitset but the `_bit` bit is cleared (i.e., set of zero) */ +#define clearbit(_bit, _number) (_number &= ~(1 << _bit)) + +/* Evaluate to a non-zero value if a given bit in a number is set to 1. + * int x = 1; // x => 1000 0000 ... + * checkbit(0, x) // 1 + * checkbit(1, x) // 0 */ +#define checkbit(_bit, _number) ((_number >> _bit) & 1) + +/* Toggle a given bit. + * Example: + * int x = 4; // x => 0010 0000 ... + * togglebit(3, x); // x => 0000 0000 ... + * togglebit(3, x); // x => 0010 0000 ... */ +#define togglebit(_bit, _number) (_number ^= 1 << _bit) + +/* Set a given bit to a specified value (e.g., 0 or 1). */ +#define changebit(_bit, _val, _number) \ + (_number ^= (-_val ^ _number) & (1 << _bit)) + +/* Set up to 64 bits from left to right to ones. + * Example: + * int x = 0; // x => 00000000 00000000 ... + * setbits64(11, x) // => 11111111 11100000 ... + * setbits64(64, x) // => behaviour undefined */ +#define setbits64(_bits, _number) (_number |= ~(ONE << _bits)) + +/* Set up to 64 bits from left to right to ones skiping `_skip` leftmost bits + * Example: + * int x = 0; // x => 00000000 00000000 ... + * setbits64(11, x, 2) // => 00111111 11111000 ... + * setbits64(64, x, 2) // => behaviour undefined */ +#define setbits64_skip(_bits, _number, _skip) \ + (_number |= ~(ONE << _bits) << _skip) + +/* Evaluate to 1 if up to 64 bits from left to right in `_number` are set: + * Example: + * int x = 31; // x => 11111000 00000000 ... + * checkbits64(4, x) // => 1 + * checkbits64(5, x) // => 1 + * checkbits64(6, x) // => 0 + * checkbits64(64, x) // => behaviour undefined */ +#define checkbits64(_bits, _number) \ + ((_number & ~(ONE << _bits)) == (~(ONE << _bits))) + +/* Same as checkbits64 but with skipping `_skip` leftmost bits + * Example: + * int x = 124; // x => 00111100 00000000 ... + * checkbits64_skip(3, x, 2) // => 1 + * checkbits64_skip(4, x, 2) // => 1 + * checkbits64_skip(5, x, 2) // => 0 + * checkbits64_skip(3, x, 1) // => 0 + * checkbits64_skip(64, x, 0) // => behaviour undefined */ +#define checkbits64_skip(_bits, _number, _skip) \ + ((_number & ~(ONE << _bits) << _skip) == (~(ONE << _bits) << _skip)) + +/* Same as `setbits64' but clear the bits (set to zeroes). */ +#define clearbits64(_bits, _number) (_number &= ONE << _bits) + +/* Set `_bits' bits from right to the left starting from a 64-bit boundary. + * Example: + * long x = 0; // x => ... 00000000 00000000 00000000 00000000 + * setbits64_right(10, x) // x => ... 00000000 00000000 00000011 11111111 */ +#define setbits64_right(_bits, _number) (_number |= ~(ONE >> _bits)) + +/* Same as setbits64_right but clears bits (sets to zeroes) */ +#define clearbits64_right(_bits, _number) (_number &= ONE >> _bits) + +/* Set `size' bits starting from an address given by `ptr' to ones. + * Example: + * char a[4]; + * memset(a,0,4); // => 00000000 00000000 00000000 00000000 + * setbits(&a, 11); // => 11111111 11100000 00000000 00000000 */ +static inline void setbits(size_t size, void *ptr) { + size_t i; + int64_t *lp = (int64_t*)ptr; + for (i = 0; i < size/64; i++) + *(lp+i) |= ONE; + setbits64(size%64, *(lp+i)); +} + +/* Same as `setbits' but clear the bits (set to zeroes). */ +static inline void clearbits(size_t size, void *ptr) { + size_t i; + int64_t *lp = (int64_t*)ptr; + for (i = 0; i < size/64; i++) + *(lp+i) &= ZERO; + clearbits64(size%64, *(lp+i)); +} + +/* Same as `setbits' but clear the bits (set to zeroes). */ +static inline int checkbits(size_t size, void *ptr) { + size_t i; + int64_t *lp = (int64_t*)ptr; + for (i = 0; i < size/64; i++) { + if (*(lp+i) != ONE) + return 0; + } + return checkbits64(size%64, *(lp+i)); +} + +/* Same as `setbits' but set the bits from right to left + * Example: + * char a[4]; + * memset(a,0,4); // => 00000000 00000000 00000000 00000000 + * setbits_right(&a, 11); // => 00000000 00000000 00000111 11111111 */ +static inline void setbits_right(size_t size, void *ptr) { + size_t i = 0; + int64_t *lp = (int64_t*)ptr - 1; + for (i = 0; i < size/64; i++) + *(lp-i) |= ONE; + setbits64_right(size%64, *(lp-i)); +} + +/* Same as `setbits_right' but clear the bits (set to zeroes). */ +static inline void clearbits_right(size_t size, void *ptr) { + size_t i = 0; + int64_t *lp = (int64_t*)ptr - 1; + for (i = 0; i < size/64; i++) + *(lp-i) &= ZERO; + clearbits64_right(size%64, *(lp-i)); +} +/* }}} */ +#endif diff --git a/src/plugins/e-acsl/share/e-acsl/e_acsl_debug.h b/src/plugins/e-acsl/share/e-acsl/e_acsl_debug.h new file mode 100644 index 0000000000000000000000000000000000000000..2073a9aa1f32003748176887f29d355c24f23828 --- /dev/null +++ b/src/plugins/e-acsl/share/e-acsl/e_acsl_debug.h @@ -0,0 +1,115 @@ +/**************************************************************************/ +/* */ +/* This file is part of the Frama-C's E-ACSL plug-in. */ +/* */ +/* Copyright (C) 2012-2018 */ +/* CEA (Commissariat à l'énergie atomique et aux énergies */ +/* alternatives) */ +/* */ +/* you can redistribute it and/or modify it under the terms of the GNU */ +/* Lesser General Public License as published by the Free Software */ +/* Foundation, version 2.1. */ +/* */ +/* It is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Lesser General Public License for more details. */ +/* */ +/* See the GNU Lesser General Public License version 2.1 */ +/* for more details (enclosed in the file licenses/LGPLv2.1). */ +/* */ +/**************************************************************************/ + +/*! *********************************************************************** + * \file e_acsl_debug.h + * \brief Debug-level functions and macros +***************************************************************************/ +#ifndef E_ACSL_DEBUG_H +#define E_ACSL_DEBUG_H + +static void vabort(char *fmt, ...); + +/* Stringification macros {{{ */ +#ifndef E_ACSL_STRINGIFICATION +#define E_ACSL_STRINGIFICATION +# define STRINGIFY(x) #x +# define TOSTRING(x) STRINGIFY(x) +# define __AT__ __FILE__ ":" TOSTRING(__LINE__) +#endif +/* }}} */ + +/** Debugging support {{{ + * Enabled in the presence of the E_ACSL_DEBUG macro */ +#ifdef E_ACSL_DEBUG + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include "e_acsl_printf.h" +#include "e_acsl_string.h" +#include "e_acsl_trace.h" +#include "e_acsl_assert.h" + +#define E_ACSL_DEBUG_DESC "debug" + +/* Default location of the E_ACSL log file */ +#ifndef E_ACSL_DEBUG_LOG +# define E_ACSL_DEBUG_LOG - +#endif + +/*! \brief Name of the debug log file */ +static const char *dlog_name = TOSTRING(E_ACSL_DEBUG_LOG); + +/*! \brief File descriptor associated with the debug log file */ +static int dlog_fd = -1; + +/*! \brief Output a message to a log file */ +#define DLOG(...) rtl_dprintf(dlog_fd, __VA_ARGS__) + +#ifdef E_ACSL_DEBUG_VERBOSE +# define DVLOG(...) rtl_dprintf(dlog_fd, __VA_ARGS__) +#else +# define DVLOG(...) +#endif + +/*! \brief Debug-time assertion based on assert (see e_acsl_assert.h) */ +#define DASSERT(_e) vassert(_e,"",NULL) + +/*! \brief Debug-time assertion based on vassert (see e_acsl_assert.h) */ +#define DVASSERT(_expr, _fmt, ...) vassert(_expr, _fmt, __VA_ARGS__) + +/*! \brief Initialize debug report file: + * - open file descriptor + * - add program arguments to the log */ +static void initialize_report_file(int *argc, char ***argv) { + /* Redirect the log to stderr is just set to be defined or set to '-' */ + if (!strcmp(dlog_name, "-") || !strcmp(dlog_name, "1")) { + dlog_fd = 2; + } else { + dlog_fd = open(dlog_name, O_WRONLY | O_CREAT | O_TRUNC |O_NONBLOCK + | O_NOCTTY, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); + } + if (dlog_fd == -1) + vabort("Cannot open file descriptor for %s\n", dlog_name); +} + +static int debug_stop_number = 0; +int getchar(void); + +#define DSTOP { \ + DLOG(" << ***** " "Debug Stop %d in '%s' at %s:%d" " ***** >> ", \ + ++debug_stop_number, __func__, __FILE__, __LINE__); \ + getchar(); \ +} + +#else +# define E_ACSL_DEBUG_DESC "production" +# define DSTOP +# define initialize_report_file(...) +# define DLOG(...) +# define DVLOG(...) +# define DASSERT(_e) +# define DVASSERT(_expr, _fmt, ...) +#endif +#endif +// }}} diff --git a/src/plugins/e-acsl/share/e-acsl/e_acsl_floating_point.h b/src/plugins/e-acsl/share/e-acsl/e_acsl_floating_point.h new file mode 100644 index 0000000000000000000000000000000000000000..8c6a654616130dd1d821301afb567da0a63b4a7c --- /dev/null +++ b/src/plugins/e-acsl/share/e-acsl/e_acsl_floating_point.h @@ -0,0 +1,94 @@ +/**************************************************************************/ +/* */ +/* This file is part of the Frama-C's E-ACSL plug-in. */ +/* */ +/* Copyright (C) 2012-2018 */ +/* CEA (Commissariat à l'énergie atomique et aux énergies */ +/* alternatives) */ +/* */ +/* you can redistribute it and/or modify it under the terms of the GNU */ +/* Lesser General Public License as published by the Free Software */ +/* Foundation, version 2.1. */ +/* */ +/* It is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Lesser General Public License for more details. */ +/* */ +/* See the GNU Lesser General Public License version 2.1 */ +/* for more details (enclosed in the file licenses/LGPLv2.1). */ +/* */ +/**************************************************************************/ + +/*! *********************************************************************** + * \file e_acsl_floating_point.h + * \brief Functionality related to processing of floating point values +***************************************************************************/ + +#ifndef E_ACSL_FLOATING_POINT_H +#define E_ACSL_FLOATING_POINT_H + +#include "e_acsl.h" +#include <math.h> +#include <float.h> +#include <fenv.h> + +/* Below variables hold infinity values for floating points defined in math.h. + Most of them are defined as macros that expand to built-in function calls. + As such, they cannot be used in E-ACSL specifications directly. To solve + the issue this header provides alternative definitions prefixed + __e_acsl_math_. For instance, if a call to `pow` overflows it + returns `HUGE_VAL`. To make sure that the result of pow does not overflow + one can use the following contract: + + extern double __e_acsl_math_HUGE_VAL; + + //@ ensures \result != __e_acsl_math_HUGE_VAL; + double pow(double, double); +*/ + +/** \brief Positive infinity for doubles: same as HUGE_VAL */ +double math_HUGE_VAL = 0.0; +/** \brief Positive infinity for floats: same as HUGE_VALF */ +float math_HUGE_VALF = 0.0; +/** \brief Representation of infinity value for doubles: same as INFINITY */ +double math_INFINITY = 0.0; + +/* FIXME: An additional variable that should be added to this list is + long double math_HUGE_VALL; + That represents positive infinity for long doubles. However, long doubles + are unsupported Value plug-in analysis who start throwing errors once + test suite is ran. */ + +static void init_infinity_values() { + /* Initialize E-ACSL infinity values */ + math_HUGE_VAL = HUGE_VAL; + math_HUGE_VALF = HUGE_VALF; + math_INFINITY = INFINITY; + /* Clear exceptions buffers */ + feclearexcept(FE_ALL_EXCEPT); +} + +void floating_point_exception(const char *exp) { + int except = fetestexcept(FE_ALL_EXCEPT); + char *resp = NULL; + if (except) { + if (fetestexcept(FE_DIVBYZERO)) + resp = "Division by zero"; + else if (fetestexcept(FE_INEXACT)) + resp = "Rounded result of an operation is not equal to the infinite precision result"; + else if (fetestexcept(FE_INVALID)) + resp = "Result of a floating-point operation is not well-defined"; + else if (fetestexcept(FE_OVERFLOW)) + resp = "Floating-point overflow"; + else if (fetestexcept(FE_UNDERFLOW)) + resp = "Floating-point underflow"; + } + if (resp) { + rtl_printf("Execution of the statement `%s` leads to a floating point exception\n", exp); + rtl_printf("Exception: %s\n", resp); + } + feclearexcept(FE_ALL_EXCEPT); +} + +#endif diff --git a/src/plugins/e-acsl/share/e-acsl/e_acsl_format.h b/src/plugins/e-acsl/share/e-acsl/e_acsl_format.h new file mode 100644 index 0000000000000000000000000000000000000000..fa78e400828db3547a83888f89e58e5e8eee447c --- /dev/null +++ b/src/plugins/e-acsl/share/e-acsl/e_acsl_format.h @@ -0,0 +1,1024 @@ +/**************************************************************************/ +/* */ +/* This file is part of the Frama-C's E-ACSL plug-in. */ +/* */ +/* Copyright (C) 2012-2018 */ +/* CEA (Commissariat à l'énergie atomique et aux énergies */ +/* alternatives) */ +/* */ +/* you can redistribute it and/or modify it under the terms of the GNU */ +/* Lesser General Public License as published by the Free Software */ +/* Foundation, version 2.1. */ +/* */ +/* It is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Lesser General Public License for more details. */ +/* */ +/* See the GNU Lesser General Public License version 2.1 */ +/* for more details (enclosed in the file licenses/LGPLv2.1). */ +/* */ +/**************************************************************************/ + +/*! *********************************************************************** + * \file e_acsl_format.h + * \brief Validating format strings with respect to arguments and their types + * + * Detection of format string vulnerabilities and other violations + * related to improper use of formats in printf-like functions are addressed + * as follows. Each call to a format function `f` (e.g. printf) + * is replaced by a call to an analysis function `f'`. The signature of `f'` is + * similar to that of `f'` except it has an additional argument. This argument + * is a literal string where each character describes the type of a variadic + * argument in the original call to `f`. + * + * For instance: + * `printf("Str=%s, Int=%d ", str, num);` + * is replaced by + * `__e_acsl_builtin_printf("sd", "Str=%s, Int=%d", str, num);` + * Note the first argument "sd". It indicates that `printf` was invoked + * with two variadic arguments of types `char*` (specified via 's') + * and `int` (`d`). Such single-character types are further called + * |abbreviated| types. See ::abbr2str function for details. + * + * Execution of __e_acsl_builtin_printf checks that + * - format string is a NUL-terminated C string + * - all directives in the format string are well-formed (as per C99 standard) + * - each formatting directive has a corresponding variadic argument. + * Excessive arguments (for which there are no directives) are allowed + * but otherwise ignored. + * - the types of variadic arguments provided via a call match the types + * expected by the respective format directives. This check includes checking + * for signedness. For instance, + * __e_acsl_builtin_printf("d", "%u", n); + * will abort because the formatting directive expects its argument to be an + * unsigned integer, whereas `n` is a signed integer (indicated by "d") in + * the first argument to `__e_acsl_builtin_printf`. Bear in mind though that + * char, short, and float types are the subjects to default promotions. That + * is, `char` and `short` are promoted to `int` and `float` is promoted to + * double. Frama-C enforces such promotions by adding explicit casts. + * - variadic arguments corresponding to `%s` conversion specifiers describe + * valid C strings (NUL-terminated arrays of characters belonging to program + * allocation) + * - variadic arguments corresponding to `%n` conversion specifiers describe + * valid integer pointers + * Execution of __e_acsl_builtin_dprintf additionally checks that + * - the file descriptor designated for writing is open + * Execution of __e_acsl_builtin_fprintf additionally checks that + * - the stream designated for writing is valid + * Execution of __e_acsl_builtin_sprintf and __e_acsl_builtin_sprintf + * additionally check that + * - memory buffers designated for writing are allocated, writable and provide + * sufficient space for storing the results +***************************************************************************/ + +#ifndef E_ACSL_FORMAT_H +#define E_ACSL_FORMAT_H + +#ifndef E_ACSL_VALIDATE_FORMAT_STRINGS +# define E_ACSL_FORMAT_VALIDITY_DESC "disabled" +#else +# define E_ACSL_FORMAT_VALIDITY_DESC "enabled" + +#include <stdlib.h> +#include <features.h> +#include <stdint.h> +#include <stdio.h> +#include <wctype.h> +#include <fcntl.h> + +#define FMT_ERROR "Format error: " +#define INT_ERROR "Internal error: " + +/* Check whether a value is unsigned or not. + Watch out for integer promotions. */ +#define UNSIGNED(n) (n >= 0 && ~n >= 0) + +/* Abbreviated types {{{ */ + +/* An abbreviated type is a character that describes a given primitive or a + pointer type that may be expected by a formatting directive of a + function such as `printf`. Correspondance between abbreviated and actual + types is given via macro ::abbreviated_types. + + Abbreviated type values are ad-hoc with one convention: + any given signed integral (or integral pointer type) is given by a lower-case + letter, whereas an unsigned type is given by the same but upper-case letter. + For instance, 'd' corresponds to `int` and 'D' corresponds to `unsigned int`. + Similarly, 'i' corresponds to `int*` and `I` corresponds to `unsigned int*`. + + NOTE: Abbreviated types are generated by the instrumentation engine + (see definition of the `get_printf_argument_str` in `functions.ml`). + It is therefore important that the types as they are used by this file + and by `functions.ml` are in sync */ + +#define abbreviated_types \ + typedef_abbreviated('c', char, IChar) \ + typedef_abbreviated('C', unsigned char, IUChar) \ + typedef_abbreviated('h', short, IShort) \ + typedef_abbreviated('H', unsigned short, IUShort) \ + typedef_abbreviated('d', int, IInt) \ + typedef_abbreviated('D', unsigned int, IUInt) \ + typedef_abbreviated('l', long, ILong) \ + typedef_abbreviated('L', unsigned long, IULong) \ + typedef_abbreviated('r', long long, ILongLong) \ + typedef_abbreviated('R', unsigned long long, IULongLong) \ + typedef_abbreviated('f', float, FFloat) \ + typedef_abbreviated('e', double, FDouble) \ + typedef_abbreviated('E', long double, FLongDouble) \ + typedef_abbreviated('s', char*, PChar) \ + typedef_abbreviated('S', unsigned char*, PUChar) \ + typedef_abbreviated('q', short*, PShort) \ + typedef_abbreviated('Q', unsigned short*, PUShort) \ + typedef_abbreviated('i', int*, PInt) \ + typedef_abbreviated('I', unsigned int*, PUInt) \ + typedef_abbreviated('z', long*, PLong) \ + typedef_abbreviated('Z', unsigned long*, PULong) \ + typedef_abbreviated('w', long long*, PLongLong) \ + typedef_abbreviated('W', unsigned long long*, PULongLong) \ + typedef_abbreviated('p', void*, PVoid) + +/* Define abbreviated types as enum so they can be referred to as aliases */ +typedef enum { +#define typedef_abbreviated(type,val,alias) alias = type, + abbreviated_types +#undef typedef_abbreviated +} abbrev_t; + +/** \brief Return a C-string representation of a given abbreviated type */ +static const char* abbr2str(abbrev_t type) { + switch(type) { +#define typedef_abbreviated(type,val,alias) case type: return #val; + abbreviated_types +#undef typedef_abbreviated + } + return '\0'; +} + +/** \brief Return a byte-size of a given abbreviated type */ +static int abbr2size(abbrev_t type) { + switch(type) { +#define typedef_abbreviated(type,val,alias) case type: return sizeof(val); + abbreviated_types +#undef typedef_abbreviated + } + return 0; +} + +/** \brief Some format directives expect typedefs rather than actual types. + For instance '%jd' expects `intmax_t`. The instrumentation engine "unrolls" + types, that is, we will be given an actual primitive type instead (say + long). While we cannot reason about typedefs dynamically we infer types + corresponding to typedefs based on their size and sign. The following + function establishes some loose correspondence between sizes and signs and + abbreviated integer types corresponding to these sizes and signs */ +static abbrev_t size2abbri(int size, int sign) { + if (size <= sizeof(int)) + return sign ? IInt : IUInt; + else if (size == sizeof(long int)) + return sign ? ILong : IULong; + else if (size == sizeof(long long int)) + return sign ? ILongLong : IULongLong; + vabort(INT_ERROR "integral type corresponding to size %d unknown", size); + return '\0'; +} + +/** \brief Same as above but for floating point types */ +static abbrev_t size2abbrf(int size) { + if (size == sizeof(float)) + return FFloat; + else if (size == sizeof(double)) + return FDouble; + else if (size == sizeof(long double)) + return FLongDouble; + vabort + (INT_ERROR "floating point type corresponding to size %d unknown", size); + return '\0'; +} + +/* Partial mapping of primitive abreviated type to a pointer of the same type, + e.g., 'd' (int) -> 's' (*) */ +static char abbr2ptr(char c) { + switch(c) { + case IInt: return PInt; + case IUInt: return PUInt; + case ILong: return PLong; + case IULong: return PULong; + case ILongLong: return PLongLong; + case IULongLong: return PULongLong; + default: + vabort(INT_ERROR "Unexpected abbreviated type %c\n", c); + } + return '\0'; +} +/* }}} */ + +/* Format string character classes {{{ */ + +/* Length modifier characters */ +const char *length_chars = "hljztL"; + +/* Flag characters */ +const char *flag_chars = "-+ #0'"; + +/* Conversion specifier characters. '%' is treated specially */ +const char *specifier_chars = "diouxXfFeEgGaAcspn"; + +/* Period character */ +const char *period_chars = "."; + +/* Character map allowing to quickly identify the class of a character (above). + Do not use this map directly, use one of the below macros. */ +char format_char_map[256]; + +#define specifier_id 's' +#define length_id 'l' +#define flag_id 'f' +#define period_id 'r' + +#define is_specifier_char(_c) (format_char_map[(int)_c] == specifier_id) +#define is_flag_char(_c) (format_char_map[(int)_c] == flag_id) +#define is_length_char(_c) (format_char_map[(int)_c] == length_id) +#define is_period_char(_c) (format_char_map[(int)_c] == period_id) + +static void set_format_char_map() { + int init_idx = (int)'\0'; + int init_char = 'i'; + if (format_char_map[init_idx] != init_char) { + memset(format_char_map, 0, 256); + int i; + for(i = 0; i < strlen(specifier_chars); i++) + format_char_map[(int)specifier_chars[i]] = specifier_id; + for(i = 0; i < strlen(length_chars); i++) + format_char_map[(int)length_chars[i]] = length_id; + for(i = 0; i < strlen(flag_chars); i++) + format_char_map[(int)flag_chars[i]] = flag_id; + for(i = 0; i < strlen(period_chars); i++) + format_char_map[(int)period_chars[i]] = period_id; + format_char_map[init_idx] = init_char; + } +} +/* }}} */ + +/* Argument specification {{{ */ +typedef struct { + char *format; /* Pointer to the complete format string */ + char directive [16]; /* Directive string */ + struct arg { + int index; /* Argument index this specification refers to */ + _Bool expl; /* Set to 1 if the argument has been numbered via $ */ + } arg; + struct flags { /* Flags */ + _Bool specified; /* set if any of the below flags are set */ + _Bool minus; /* - */ + _Bool plus; /* + */ + _Bool space; /* ' ' */ + _Bool hash; /* # */ + _Bool zero; /* 0 */ + _Bool apostroph; /* ' */ + } flags; + int field_width; /* Field width, INT_MIN if not given, -1 if '*' */ + int precision; /* Format precision, INT_MIN if not given, -1 if '*' */ + struct length { /* Length Modifier */ + int bytes; /* Number of bytes inferred from length modifier */ + char mod; /* Modifier character (such as 'l' or 'h') */ + _Bool extended; /* Set if modifier is repeated (e.g., 'll' or 'hh') */ + } length; + char specifier; /* Format specifier character */ +} format_directive; +/* }}} */ + +/* Debug print {{{ */ +static void print_directive(format_directive *dir, char *rem) { + rtl_printf(" Format: %s\n", dir->format); + rtl_printf(" Specifier: %c\n", dir->specifier); + rtl_printf(" Arg: \n"); + rtl_printf(" Index: $d\n", dir->arg.index); + rtl_printf(" Explicit: $d\n", dir->arg.expl); + rtl_printf(" Precision: .%d\n", dir->precision); + rtl_printf(" Field width: %d\n", dir->field_width); + rtl_printf(" Length: \n"); + rtl_printf(" Modifier: %c \n", dir->length.mod); + rtl_printf(" Bytes: %d \n", dir->length.bytes); + rtl_printf(" Extended: %d \n", dir->length.extended); + rtl_printf(" Flags: <"); +#define print_format_flag(_f,_s) if (dir->flags._f) rtl_printf(_s) + print_format_flag(plus,"+"); + print_format_flag(minus, "-"); + print_format_flag(space, " "); + print_format_flag(hash,"#"); + print_format_flag(apostroph,"'"); + print_format_flag(zero,"0"); +#undef print_format_flag + rtl_printf(">\n"); + rtl_printf(" Remainder: \"%s\"\n", rem); +} +/* }}} */ + +/* Fetch format argument number {{{ + Most format specifications allow for argument numbers to be specified. E.g., + printf("%2$*1$d", width, num); + The above will first print num and then width. Even though this is not in + C99, we allow that as many `printf` implementations have this extension. + The feature comes from the Single UNIX Specification. + + This function assumes that *(fmt-1) is '%' */ +static char *fetch_format_argno(char *fmt, format_directive *dir, + format_directive *prev, int ind) { + int argno = 0; + char *ret = fmt; + + /* If *fmt is a non-zero digit then it is either an argument number + (if followed by '$') or a field width. */ + if (*ret != '0') { + while (isdigit(*ret)) { + argno = argno * 10 + (*ret - '0'); + ret++; + } + } else { + /* The only case when zero is found is when it is a flag, just return. */ + return ret; + } + + /* If '$' is found then it was an argument number, save its index */ + if (*ret == '$') { + dir->arg.index = argno - 1; + dir->arg.expl = 1; + ret++; + /* ... do nothing otherwise but revert back to original format as some + characters may have been fetched */ + } else { + dir->arg.index = ind; + dir->arg.expl = 0; + ret = fmt; + } + + /* make sure that numbered and non-numbered directives are not mixed */ + if (prev && prev->arg.expl != dir->arg.expl) + vabort(FMT_ERROR + "\"%s\": numbered and non-numbered directives cannot be mixed\n", + dir->format); + + return ret; +} +/* }}} */ + +/* Fetch format flags {{{ */ +/* Assumes that `fmt` is a format string returned by ::fetch_format_argno */ +static char *fetch_format_flags(char *fmt, format_directive *dir) { +#define set_format_flag(_f) \ + if (!dir->flags._f) \ + { dir->flags._f = 1; } \ + else \ + { vabort(FMT_ERROR "flag %s has already been set", #_f); } + + while (is_flag_char(*fmt)) { + dir->flags.specified = 1; + switch(*fmt) { + case '#': + set_format_flag(hash); + break; + case '-': + set_format_flag(minus); + break; + case '+': + set_format_flag(plus); + break; + case ' ': + set_format_flag(space); + break; + case '\'': + set_format_flag(apostroph); + break; + case '0': + set_format_flag(zero); + break; + } + fmt++; + } +#undef set_format_flag + return fmt; +} +/* }}} */ + +/* Fetch field width {{{ */ +/* Assumes that `fmt` is a format string returned by ::fetch_format_flags */ +static char *fetch_format_field_width(char *fmt, format_directive *dir) { + dir->field_width = INT_MIN; + /* Field width is either an asterisk ... */ + int len = 0; + if (*fmt == '*') { + dir->field_width = -1; + fmt++; + } else { /* ... or a positive decimal integer */ + if (isdigit(*fmt)) { + if (*fmt == '0') { + vabort(FMT_ERROR + "field width in format cannot start with zero (%s)\n", dir->format); + }; + while (isdigit(*fmt)) { + len = len * 10 + (*fmt - '0'); + fmt++; + } + dir->field_width = len; + } + } + return fmt; +} /* }}} */ + +/* Fetch format precision {{{ */ +/* Assumes that `fmt` is a format string returned by + ::fetch_format_field_width */ +static char *fetch_format_precision(char *fmt, format_directive *dir) { + /* Precision is given in the form '.' optionally followed by either + '*' or a digit string. */ + dir->precision = INT_MIN; + if (is_period_char(*fmt)) { + fmt++; + if (*fmt == '*') { + dir->precision = -1; + fmt++; + } else { + dir->precision = 0; + while (isdigit(*fmt)) { + dir->precision = dir->precision * 10 + (*fmt - '0'); + fmt++; + } + } + } + return fmt; +} /* }}} */ + +/* Fetch format length modifier and format specifier {{{ */ +/* Assumes that `fmt` is a format string returned by ::fetch_format_precision */ +static char *fetch_format_length(char *fmt, format_directive *dir) { + dir->length.bytes = 0; + dir->length.mod = '\0'; + dir->length.extended = 0; + + switch(*fmt) { + case 'h': { + if (*(fmt + 1) == 'h') { + dir->length.bytes = sizeof(char); + dir->length.extended = 1; + fmt++; + } else + dir->length.bytes = sizeof(short); + break; + } + case 'l': { + if (*(fmt + 1) == 'l') { + dir->length.bytes = sizeof(long long); + dir->length.extended = 1; + fmt++; + } else + dir->length.bytes = sizeof(long); + break; + } + case 'j': + dir->length.bytes = sizeof(intmax_t); + break; + case 'z': + dir->length.bytes = sizeof(size_t); + break; + case 't': + dir->length.bytes = sizeof(ptrdiff_t); + break; + case 'L': + dir->length.bytes = sizeof(long double); + break; + } + + /* Make sure that the length modifier (if there is one) belongs + to a right character class */ + vassert(dir->length.mod == '\0' || is_length_char(dir->length.mod), + INT_ERROR "Bad length modifier: '%c'\n", dir->length.mod); + + if (dir->length.bytes) { + dir->length.mod = *fmt; + fmt++; + } + + /* fmt now points to a conversion specifier, get it. */ + dir->specifier = *fmt; + + /* Detect specifying length modifiers twice. This is purely for better error + reporting. Even if there is no this check, the one below detects it, + but with a different error message. */ + if ( dir->specifier ) + + /* which has been fetched at the start matches the one we have arrived at */ + if (!is_specifier_char(dir->specifier)) { + if (dir->specifier == '%') + vabort(FMT_ERROR "in directive '%s'." + "the complete conversion specification for '%%' is '%%%%'\n", + dir->format); + else + vabort(FMT_ERROR "illegal format specifier '%c'\n", dir->specifier); + } + return ++fmt; +} /* }}} */ + +/* Parse format string {{{ */ +/* Parse format string into a NULL-terminated array of directives */ +static format_directive ** get_format_directives(char *fmt) { + /* Count the number of formatting directives in the format string + by counting '%' occurrences. Yes, it may give more specifications than + needed (e.g., "%%") but allocating space for a few extra pointers does not + hurt considering that in order to do that properly we need to parse format + string twice. */ + + int sz = charcount(fmt, '%') + 1; + format_directive ** directives = + private_malloc(sizeof(format_directive *) * sz); + char *format_string = fmt; + + /* Nullify all pointers to make sure there is no leftover rubbish */ + int i; + for (i = 0; i < sz; i++) + directives[i] = NULL; + + /* Set character map so format characters can be recognized */ + set_format_char_map(); + char ch; + i = 0; + format_directive *prev = NULL; + while ((ch = *fmt++) != '\0') { + if (ch == '%') { + /* Do not take into account '%%' specification. It has no corresponding + arguments, flags or any other attributes. */ + if (*fmt == '%') { + ++fmt; + continue; + } + /* Allocate space for `format_directive` to hold the result of parsing */ + format_directive *dir = private_calloc(1, sizeof(format_directive)); + /* Parse format string */ + dir->format = format_string; + char *fmt_start = fmt - 1; + fmt = fetch_format_argno(fmt, dir, prev, i); + fmt = fetch_format_flags(fmt, dir); + fmt = fetch_format_field_width(fmt, dir); + fmt = fetch_format_precision(fmt, dir); + fmt = fetch_format_length(fmt, dir); + /* Save format string in the dir struct. Rather ugly but the RTL + printf library has no `snprintf` or extensions allowing to print + `N` characters. */ + ptrdiff_t fmt_len = fmt - fmt_start; + ptrdiff_t max_len = sizeof(dir->directive) - 1; + int len = max_len > fmt_len ? fmt_len : max_len; + strncpy(dir->directive, fmt_start, len); + dir->directive[len+1] = '\0'; + /* Save the directive */ + directives[i++] = dir; + prev = dir; + /* print_directive(dir, fmt); */ + } + } + return directives; +} + +static void release_directives(const char *fmt, format_directive ** dirs) { + int formats = charcount(fmt, '%') + 1; + int i; + for (i = 0; i < formats; i++) + private_free(dirs[i]); + private_free(dirs); +} +/* }}} */ + +/* Format string validation (well-formedness) {{{ */ +static inline void validate_application(format_directive *dir, char *allowed, + char* kind, char *desc) { + vassert(strchr(allowed, dir->specifier) != '\0', FMT_ERROR + "wrong application of %s [%s] to format specifier [%c]\n", + desc, kind, dir->specifier); +} + +/** \brief Check that a given format specifier are used with right flags, + precision, field width, and length modifier. */ +static void validate_applications(format_directive *dir) { + /* ==== Flags ==== */ + char *desc = "flag"; + + /* ' flag separates thousands by commas. It is applicable only to + i, d, u, f, F, g, or G conversion specifiers. For other specifiers + its behaviour is undefined. */ + if (dir->flags.apostroph) + validate_application(dir, "idufFgG", "\\", desc); + + /* # flag converts a value to an alternative form. It is applicable only to + x, X, a, A, e, E, f, F, g, and G conversion specifiers. */ + if (dir->flags.hash) + validate_application(dir, "oxXaAeEfFgG", "#", desc); + + /* 0 flag pads values with zeroes. It is applicable only to + d, i, o, u, x, X, a, A, e, E, f, F, g, and G conversion specifiers */ + if (dir->flags.zero) + validate_application(dir, "diouxXaAeEfFgG", "0", desc); + + /* No flags should be used if 'n' specifier is given */ + if (dir->flags.specified && dir->specifier == 'n') + vabort(FMT_ERROR "one of more flags with [n] specifier", NULL); + + /* ==== Precision ==== */ + desc = "precision"; + + /* Precision gives the minimum number of digits to appear for the + d, i, o, u, x, and X conversion specifiers; the number of digits + to appear after the period character for the a, A, e, E, f, and F + conversion specifiers; the maximum number of significant digits for the + g and G conversion specifiers; or the maximum number of bytes to be + printed from a string in the s and S conversion specifiers. */ + if (dir->precision != INT_MIN) + validate_application(dir, "diouxXaAeEfFgGs", ".", desc); + + /* ==== Field width ==== */ + desc = "field width"; + + if (dir->specifier == 'n' && dir->field_width != INT_MIN) + vabort(FMT_ERROR "field width used with [n] specifier", NULL); + + /* ==== Length modifiers ==== */ + desc = "length modifier"; + + /* Most length modifiers (all except 'L') apply to d, i, o, u, x, or X + conversion specifiers. 'L' applies to a, A, e, E, f, F, g, or G. */ + if (dir->length.mod != '\0') { + /* Make sure the length specifier is one of the allowed ones */ + vassert(is_length_char(dir->length.mod), + FMT_ERROR "bad length specifier [%c]\n", dir->length.mod); + + /* Conver length modifier to a string */ + char lm_kind[3]; + int i = 0; + lm_kind[i++] = dir->length.mod; + if (dir->length.extended) + lm_kind[i++] = dir->length.mod; + lm_kind[i++] = '\0'; + + switch (dir->length.mod) { + case 'l': + if (!dir->length.extended) { + validate_application(dir, "diouxXncsfFeEgGaA", lm_kind, desc); + break; + } + /* No need to look whether 'h' is extended, both 'h' and 'hh' are only + applicable to [diouxXn] */ + case 'h': + case 'j': + case 'z': + case 't': + validate_application(dir, "diouxXn", lm_kind, desc); + break; + case 'L': + validate_application(dir, "aAeEfFgG", lm_kind, desc); + break; + default: + vabort(INT_ERROR "unexpected length modifier %c\n", lm_kind); + } + } +} +/* }}} */ + +/* Format validation (arguments) {{{ */ + +/** \brief d, i, o, u, x and X format specifiers expect either `int` or + `unsigned int`. This, however, can be changed using length modifiers. For + instance, "%d" expects `int`, "%ld" expects `long`. The following function + computes an integer type that a format expects using length modifiers and + format specifiers. */ +static abbrev_t infer_integral_abbr(format_directive *dir, int sgn) { + switch(dir->length.mod) { + case 'l': /* expects long long or long */ + return (dir->length.extended) ? + (sgn ? ILongLong : IULongLong) : (sgn ? ILong : IULong); + case 'h': /* short/char: promoted to int */ + return IInt; + case 'j': /* intmax_t */ + return size2abbri(sizeof(intmax_t), sgn); + case 'z': /* size_t */ + return size2abbri(sizeof(size_t), sgn); + case 't': /* ptrdiff_t */ + return size2abbri(sizeof(ptrdiff_t), sgn); + case '\0': + return (sgn ? IInt : IUInt); + } + vabort(INT_ERROR "unexpected length modifier: '%c'\n", dir->length.mod); + return '\0'; +} + +/** \brief Same as above but for 'n' conversion specifier. */ +static abbrev_t infer_n_abbr(format_directive *dir) { + char c; + switch(dir->length.mod) { + case 'h': + return dir->length.extended ? PChar : PShort; + case 'l': + return dir->length.extended ? PLongLong : PLong; + case 'j': /* intmax_t: signed type */ + c = size2abbri(sizeof(intmax_t), 1); + return abbr2ptr(c); + case 'z': /* size_t: unsigned type */ + c = size2abbri(sizeof(size_t), 0); + return abbr2ptr(c); + case 't': /* ptrdiff_t: signed type */ + c = size2abbri(sizeof(ptrdiff_t), 1); + return abbr2ptr(c); + case '\0': + return PInt; + default: + vabort(INT_ERROR "unexpected length modifier '%c'\n", dir->length.mod); + } + return '\0'; +} + +/** \brief Check that a given abbreviated type (`expected_t`) matches the + abbreviated type in the format description (`fmtdesc`) and abort the + execution if it is not so. + + This function expects that the index given via the format directive + `dir` is less than or equal to the length of `fmtdesc`, i.e., there is an + actual argument that corresponds to `dir`. */ +static void validate_format_type + (abbrev_t expected_t, const char *fmtdesc, + format_directive *dir, const char *func) +{ + abbrev_t actual_t = fmtdesc[dir->arg.index]; + if (actual_t != expected_t) { + vabort("%s: directive %d ('%s') expects argument of type '%s'" + " but the corresponding argument has type '%s'\n", + func, dir->arg.index + 1, dir->directive, + abbr2str(expected_t), abbr2str(actual_t)); + } +} + +/** \brief Validate that a C string used with 's' modifier belongs to allocation + and has a NUL-terminator. Takes precision into account. + + @param s - address of the string + @param dir - formatting directive + @param func - name of the function (e.g., printf) + @param wide - if set to a true value then the string should be treated as + a wide string (wchar_t*) */ +static long validate_format_string_argument + (char *s, format_directive *dir, const char *func, int wide) +{ + int limit = (dir->precision >= 0) ? dir->precision : -1; + long size = + (wide) ? valid_nwstring((wchar_t*)s, limit, 0) : valid_nstring(s, limit, 0); + switch(size) { + case -1: + vabort + ("%s: attempt to access unallocated memory via directive %d ('%s')\n", + func, dir->arg.index + 1, dir->directive); + case -2: + vabort(INT_ERROR + "%s: writeable check unexpectedly failed in directive %d ('%s')\n", + func, dir->arg.index + 1, dir->directive); + case -3: + vabort("%s: attempt to access partially unallocated memory " + "via directive %d ('%s')\n", + func, dir->arg.index + 1, dir->directive); + case -4: + vabort("%s: unterminated string in directive %d ('%s')\n", + func, dir->arg.index + 1, dir->directive); + } + return size; +} + +/** \brief Check that a buffer of a given length overlaps with the memory space + of a formatting directive argument. */ +static void validate_overlapping_buffer(char *buffer, size_t buf_sz, void *arg, + size_t arg_sz, const char *func, format_directive *dir) { + if (buffer) { + if (!disjoint_spaces((uintptr_t)buffer, buf_sz, (uintptr_t)arg, arg_sz)) + vabort("%s: output buffer overlaps with argument %d (%s)\n", + func, dir->arg.index + 1, dir->directive); + } +} + +/** \brief Main format validation function that parses the format string and + validates each format directive against the provided format description. + If any of the requirements are violated the the program is aborted. + + @param fmtdesc - format description, a C string of abbreviated types + that describes the types of actual argument a call to a formatting function + has been made with + @param fmt - format string + @param ap - va_list of arguments to a formatting function + @param func - symbolic name of a formatting function used + @param buffer - buffer to write (in case of sprintf/snprintf, NULL otherwise) + @param buffer - buffer limit */ +static void validate_format + (const char *fmtdesc, const char *fmt, + va_list ap, const char *func, char *buffer, size_t buf_size) +{ + + /* Check that format string is valid first */ + if (valid_string((char*)fmt, 0) < 0) + vabort("%s: invalid format string (unallocated or unterminated)\n", func); + + /* Parse format string and generate format directives */ + format_directive ** dirs = get_format_directives((char*)fmt); + format_directive ** dirs_c = dirs; /* extra alias for passing it to `free` */ + + /* Track addresses of variadic arguments */ + int arglen = strlen(fmtdesc); /* number of variadic arguments */ + void *args[arglen]; + int i; + for (int i = 0; i < arglen; i++) + args[i] = va_arg(ap, void*); + va_end(ap); + + /* Validate each generated directive */ + while (*dirs) { + format_directive *dir = *dirs; + validate_applications(dir); /* Check that the directive is well formed */ + int argno = dir->arg.index; + + /* Make sure there is a sufficient number of arguments provided: for each + format directive in the format string there should be a corresponding + argument except for literal directive `%%` */ + if (argno >= arglen) + vabort("%s: directive %d (%s) in format \"%s\" has no argument\n", + func, dir->arg.index + 1, dir->directive, dir->format); + +/* Shortcut for `validate_format_type` function */ +#define validate_type(_t) validate_format_type(_t, fmtdesc, dir, func) + + uintptr_t addr = (uintptr_t)args[argno]; /* Address of the argument */ + char expected_t; /* Placeholder for the type expected by the directive */ + + switch(dir->specifier) { + case 'd': /* signed integer */ + case 'i': + expected_t = infer_integral_abbr(dir, 1); + validate_type(expected_t); + break; + case 'o': /* unsigned integer */ + case 'u': + case 'x': case 'X': + expected_t = infer_integral_abbr(dir, 0); + validate_type(expected_t); + break; + case 'f': case 'F': /* double */ + case 'e': case 'E': + case 'g': case 'G': + case 'a': case 'A': + /* All floating point modifiers (aAeEfFgG) expect doubles except for + the case when 'L' length modifier is given in which case it expects + long double. Any other length modifier leads to an undefined + behaviour. Checking that does not happen is done in + ::validate_applications */ + expected_t = (dir->length.mod == 'L') ? FLongDouble : FDouble; + validate_type(expected_t); + break; + case 'c': /* character */ + /* On all occasions 'c' expects an `int`. This is because `char` is + always promoted. However, in case `l` length modifier is specified + (i.e., "%lc") then it expects an argument be of type `wint_t` and + can either be signed or unsigned. So let's compute it! */ + if (dir->length.mod == 'l') { + wint_t wi = 1; + int sign = UNSIGNED(wi); + expected_t = size2abbri(sizeof(wint_t), !sign); + } else + expected_t = IInt; + validate_type(expected_t); + break; + case 's': { /* character string */ + int wide = (dir->length.mod == 'l'); + if (wide) { /* same as with %lc, compute sign of wchar_t */ + wchar_t wi = 1; + int sign = UNSIGNED(wi); + expected_t = size2abbri(sizeof(wint_t), !sign); + expected_t = abbr2ptr(expected_t); + } else + expected_t = PChar; + validate_type(expected_t); + /* Check that a string is valid */ + int asz = validate_format_string_argument((char*)addr, dir, func, wide); + validate_overlapping_buffer + (buffer, buf_size, (void*)addr, asz, func, dir); + break; + } + case 'p': + validate_type(PVoid); + if (!allocated(addr, 1, addr)) + vabort("%s: argument %d of directive %s not allocated\n", func, + argno + 1, dir->directive); + validate_overlapping_buffer + (buffer, buf_size, (void*)addr, 1, func, dir); + break; + case 'n': { + expected_t = infer_n_abbr(dir); + validate_type(expected_t); + /* 'n' modifier writes the number of bytes corresponding to characters + written by a function so far to a pointer of an integral type. Make + sure that the provided pointer corresponds to writeable memory. */ + int size = dir->length.bytes == 0 ? sizeof(int) : dir->length.bytes; + if (!writeable(addr, size, addr)) + vabort("%s: argument %d of directive %s not allocated or writeable\n", + func, argno, dir->directive); + validate_overlapping_buffer + (buffer, buf_size, (void*)addr, size, func, dir); + break; + } + default: + vabort(INT_ERROR "Unexpected format specifier '%c'\n", dir->specifier); + } + dirs++; +#undef validate_type + } + release_directives(fmt, dirs_c); +} +/* }}} */ + +/* Printf and friends {{{ */ +int builtin_printf(const char *fmtdesc, const char *fmt, ...) { + va_list ap; + va_start(ap, fmt); + validate_format(fmtdesc, fmt, ap, "printf", NULL, 0); + va_start(ap, fmt); + return vprintf(fmt, ap); +} + +int builtin_fprintf(const char *fmtdesc, FILE *stream, const char *fmt, ...) { + va_list ap; + va_start(ap, fmt); + /* First check that stream belongs to allocated space */ + if (!allocated((uintptr_t)stream, 1, (uintptr_t)stream)) + vabort("fprintf: attempt to write to an invalid stream\n", NULL); + /* Check if stream is a valid stream and that is open */ + int fd = fileno(stream); + if (fd == -1) + vabort("fprintf: attempt to write to an invalid stream\n", NULL); + /* Since we have a file descriptor check if it is open. + This may not be really necessary since `fileno` should be able to tell us + that. Does not hurt though. That's a fast check. + It should be noted that `fileno` is a POSIX function and not in the C99 + standard. */ + if (fcntl(fd, F_GETFD) == -1) + vabort("fprintf: attempt to write to a closed stream\n", NULL); + + validate_format(fmtdesc, fmt, ap, "fprintf", NULL, 0); + va_start(ap, fmt); + return vfprintf(stream, fmt, ap); +} + +int builtin_dprintf(const char *fmtdesc, int fd, const char *fmt, ...) { + va_list ap; + va_start(ap, fmt); + /* Make sure that the designated file descriptor is open */ + if (fcntl(fd, F_GETFD) == -1) + vabort("dprintf: attempt to write to a closed file descriptor %d\n", fd); + validate_format(fmtdesc, fmt, ap, "dprintf", NULL, 0); + va_start(ap, fmt); + return vdprintf(fd, fmt, ap); +} + +int builtin_sprintf(const char *fmtdesc, char *buffer, const char *fmt, ...) { + va_list ap; + /* Make sure that the buffer has sufficient space to store the result of the + function. Luckily this can be accomplished via `snprintf(buf, n, mfmt,...)` + that can take `NULL` and `0` as its first two arguments (nothing is + printed) but still returns the number of characters that would have been + printed if both `buf` and `n` were sufficiently large. This behaviour is + C99-compliant and described in par. 7.19.6.5 of the C99 standard */ + va_start(ap, fmt); + int len = vsnprintf(NULL, 0, fmt, ap); + if (!writeable((uintptr_t)buffer, len + 1, (uintptr_t)buffer)) + vabort("sprintf: output buffer is unallocated or has insufficient length " + "to store %d characters or not writeable\n", len + 1); + va_start(ap, fmt); + validate_format(fmtdesc, fmt, ap, "sprintf", buffer, len + 1); + va_start(ap, fmt); + return vsprintf(buffer, fmt, ap); +} + +int builtin_snprintf(const char *fmtdesc, char *buffer, size_t size, + const char *fmt, ...) { + va_list ap; + va_start(ap, fmt); + validate_format(fmtdesc, fmt, ap, "snprintf", buffer, size); + /* Check that the input buffer is large enough. However, if there are zero + characters to write, it does not matter */ + if (size > 0 && !writeable((uintptr_t)buffer, size, (uintptr_t)buffer)) + vabort("sprintf: output buffer is unallocated or has insufficient length " + "to store %d characters and \0 terminator or not writeable\n", size); + va_start(ap, fmt); + return vsnprintf(buffer, size, fmt, ap); +} + +int builtin_syslog(const char *fmtdesc, int priority, const char *fmt, ...) { + va_list ap; + va_start(ap, fmt); + validate_format(fmtdesc, fmt, ap, "syslog", NULL, 0); + va_start(ap, fmt); + return vsyslog(priority, fmt, ap); +} + +/* }}} */ +#endif /* E_ACSL_VALIDATE_FORMAT_STRINGS */ +#endif /* E_ACSL_FORMAT_H */ diff --git a/src/plugins/e-acsl/share/e-acsl/e_acsl_gmp_api.h b/src/plugins/e-acsl/share/e-acsl/e_acsl_gmp_api.h new file mode 100644 index 0000000000000000000000000000000000000000..2f60cf14470eeed8a42500fdb97c4b45c7b9b9d1 --- /dev/null +++ b/src/plugins/e-acsl/share/e-acsl/e_acsl_gmp_api.h @@ -0,0 +1,307 @@ +/**************************************************************************/ +/* */ +/* This file is part of the Frama-C's E-ACSL plug-in. */ +/* */ +/* Copyright (C) 2012-2018 */ +/* CEA (Commissariat à l'énergie atomique et aux énergies */ +/* alternatives) */ +/* */ +/* you can redistribute it and/or modify it under the terms of the GNU */ +/* Lesser General Public License as published by the Free Software */ +/* Foundation, version 2.1. */ +/* */ +/* It is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Lesser General Public License for more details. */ +/* */ +/* See the GNU Lesser General Public License version 2.1 */ +/* for more details (enclosed in the file licenses/LGPLv2.1). */ +/* */ +/**************************************************************************/ + +/*! *********************************************************************** + * \file e_acsl_gmp.h + * \brief Prototypes of functions belonging to GNU Multiple + * Precision Arithmetic Library (GMP) used within E-ACSL +***************************************************************************/ + +/******************/ +/* GMP prototypes */ +/******************/ + +#ifndef E_ACSL_GMP_API_H +#define E_ACSL_GMP_API_H + +#include "stdlib.h" +#include "e_acsl_alias.h" + +#define mpz_struct export_alias(mpz_struct) +#define mpz_t export_alias(mpz_t) +#define mpq_struct export_alias(mpq_struct) +#define mpq_t export_alias(mpq_t) + +struct mpz_struct { + int _mp_alloc; + int _mp_size; + unsigned long *_mp_d; +}; + +typedef struct mpz_struct mpz_struct; +typedef mpz_struct (__attribute__((__FC_BUILTIN__)) mpz_t)[1]; + +struct mpq_struct { + mpz_struct _mp_num; + mpz_struct _mp_den; +}; + +typedef struct mpq_struct mpq_struct; +typedef mpq_struct (__attribute__((__FC_BUILTIN__)) mpq_t)[1]; + +/****************/ +/* Initializers */ +/****************/ + +/*@ ghost extern int __e_acsl_init; */ + +/*@ requires ! \initialized(z); + @ ensures \valid(z); + @ allocates z; + @ assigns *z \from __e_acsl_init; */ +extern void __gmpz_init(mpz_t z) + __attribute__((FC_BUILTIN)); + +/*@ requires ! \initialized(q); + @ ensures \valid(q); + @ allocates q; + @ assigns *q \from __e_acsl_init; */ +extern void __gmpq_init(mpq_t q) + __attribute__((FC_BUILTIN)); + +/*@ requires \valid_read(z_orig); + @ requires ! \initialized(z); + @ allocates z; + @ ensures \valid(z); +// @ ensures z->n == z_orig->n; + @ assigns *z \from *z_orig; */ +extern void __gmpz_init_set(mpz_t z, const mpz_t z_orig) + __attribute__((FC_BUILTIN)); + +/*@ requires ! \initialized(z); + @ allocates z; + @ ensures \valid(z); + @ ensures \initialized(z); +// @ ensures z->n == n; + @ assigns *z \from n; */ +extern void __gmpz_init_set_ui(mpz_t z, unsigned long int n) + __attribute__((FC_BUILTIN)); + +/*@ requires ! \initialized(z); + @ allocates z; + @ ensures \valid(z); + @ ensures \initialized(z); +// @ ensures z->n == n; + @ assigns *z \from n; */ +extern void __gmpz_init_set_si(mpz_t z, signed long int n) + __attribute__((FC_BUILTIN)); + +/*@ requires ! \initialized(z); + @ allocates z; + @ ensures \valid(z); + @ ensures \initialized(z); + @ assigns *z \from str[0..],base; + @ assigns \result \from str[0..],base; */ +extern int __gmpz_init_set_str(mpz_t z, const char *str, int base) + __attribute__((FC_BUILTIN)); + +/*@ requires ! \initialized(z); + @ allocates z; + @ ensures \valid(z); + @ ensures \initialized(z); + @ assigns *z \from base; */ +extern void __gmpz_import (mpz_t z, size_t, int, size_t, int, size_t, const void *base) + __attribute__((FC_BUILTIN)); + +/***************/ +/* Assignments */ +/***************/ + +/*@ requires \valid_read(z_orig); + @ requires \valid(z); +// @ ensures z->n == z_orig->n; + @ assigns *z \from *z_orig; */ +extern void __gmpz_set(mpz_t z, const mpz_t z_orig) + __attribute__((FC_BUILTIN)); + +/*@ requires \valid_read(q_orig); + @ requires \valid(q); + @ assigns *q \from *q_orig; */ +extern void __gmpq_set(mpq_t q, const mpq_t q_orig) + __attribute__((FC_BUILTIN)); + +/*@ requires \valid(q); + @ assigns *q \from d; */ +extern void __gmpq_set_d(mpq_t q, double d) + __attribute__((FC_BUILTIN)); + +/*@ requires \valid(q); + @ assigns *q \from n; */ +extern void __gmpq_set_si(mpq_t q, signed long int n) + __attribute__((FC_BUILTIN)); + +/*@ allocates q; + @ ensures \valid(q); + @ ensures \initialized(q); + @ assigns *q \from str[0..],base; + @ assigns \result \from str[0..],base; */ +extern int __gmpq_set_str(mpq_t q, const char *str, int base) + __attribute__((FC_BUILTIN)); + +/*@ requires \valid(z); +// @ ensures z->n == n; + @ assigns *z \from n; */ +extern void __gmpz_set_ui(mpz_t z, unsigned long int n) + __attribute__((FC_BUILTIN)); + +/*@ requires \valid(z); +// @ ensures z->n == n; + @ assigns *z \from n; */ +extern void __gmpz_set_si(mpz_t z, signed long int n) + __attribute__((FC_BUILTIN)); + +/*************/ +/* Finalizer */ +/*************/ + +/*@ requires \valid(x); +// @ frees x; + @ assigns *x \from *x; */ +extern void __gmpz_clear(mpz_t x) + __attribute__((FC_BUILTIN)); + +/*@ requires \valid(x); +// @ frees x; + @ assigns *x \from *x; */ +extern void __gmpq_clear(mpq_t x) + __attribute__((FC_BUILTIN)); + +/********************/ +/* Logical operator */ +/********************/ + +/*@ requires \valid_read(z1); + @ requires \valid_read(z2); + @ assigns \result \from *z1, *z2; */ +extern int __gmpz_cmp(const mpz_t z1, const mpz_t z2) + __attribute__((FC_BUILTIN)); + +/*@ requires \valid_read(q1); + @ requires \valid_read(q2); + @ assigns \result \from *q1, *q2; */ +extern int __gmpq_cmp(const mpq_t q1, const mpq_t q2) + __attribute__((FC_BUILTIN)); + +/************************/ +/* Arithmetic operators */ +/************************/ + +/*@ requires \valid(z1); + @ requires \valid_read(z2); + @ assigns *z1 \from *z2; */ +extern void __gmpz_neg(mpz_t z1, const mpz_t z2) + __attribute__((FC_BUILTIN)); + +/*@ requires \valid(z1); + @ requires \valid_read(z2); + @ requires \valid_read(z3); + @ assigns *z1 \from *z2, *z3; */ +extern void __gmpz_add(mpz_t z1, const mpz_t z2, const mpz_t z3) + __attribute__((FC_BUILTIN)); + +/*@ requires \valid(q1); + @ requires \valid_read(q2); + @ requires \valid_read(q3); + @ assigns *q1 \from *q2, *q3; */ +extern void __gmpq_add(mpq_t q1, const mpq_t q2, const mpq_t q3) + __attribute__((FC_BUILTIN)); + +/*@ requires \valid(z1); + @ requires \valid_read(z2); + @ requires \valid_read(z3); + @ assigns *z1 \from *z2, *z3; */ +extern void __gmpz_sub(mpz_t z1, const mpz_t z2, const mpz_t z3) + __attribute__((FC_BUILTIN)); + +/*@ requires \valid(q1); + @ requires \valid_read(q2); + @ requires \valid_read(q3); + @ assigns *q1 \from *q2, *q3; */ +extern void __gmpq_sub(mpq_t q1, const mpq_t q2, const mpq_t q3) + __attribute__((FC_BUILTIN)); + +/*@ requires \valid(z1); + @ requires \valid_read(z2); + @ requires \valid_read(z3); + @ assigns *z1 \from *z2, *z3; */ +extern void __gmpz_mul(mpz_t z1, const mpz_t z2, const mpz_t z3) + __attribute__((FC_BUILTIN)); + +/*@ requires \valid(q1); + @ requires \valid_read(q2); + @ requires \valid_read(q3); + @ assigns *q1 \from *q2, *q3; */ +extern void __gmpq_mul(mpq_t q1, const mpq_t q2, const mpq_t q3) + __attribute__((FC_BUILTIN)); + +/*@ requires \valid(z1); + @ requires \valid_read(z2); + @ requires \valid_read(z3); + @ assigns *z1 \from *z2, *z3; */ +extern void __gmpz_tdiv_q(mpz_t z1, const mpz_t z2, const mpz_t z3) + __attribute__((FC_BUILTIN)); + +/*@ requires \valid(z1); + @ requires \valid_read(z2); + @ requires \valid_read(z3); + @ assigns *z1 \from *z2, *z3; */ +extern void __gmpz_tdiv_r(mpz_t z1, const mpz_t z2, const mpz_t z3) + __attribute__((FC_BUILTIN)); + +/*@ requires \valid(q1); + @ requires \valid_read(q2); + @ requires \valid_read(q3); + @ assigns *q1 \from *q2, *q3; */ +extern void __gmpq_div(mpq_t q1, const mpq_t q2, const mpq_t q3) + __attribute__((FC_BUILTIN)); + +/*********************/ +/* Bitwise operators */ +/*********************/ + +/*@ requires \valid(z1); + @ requires \valid_read(z2); + @ assigns *z1 \from *z2; + @ assigns \result \from *z1,*z2; */ +extern int __gmpz_com(mpz_t z1, const mpz_t z2) + __attribute__((FC_BUILTIN)); + +/************************/ +/* Coercions to C types */ +/************************/ + +/*@ requires \valid_read(z); + @ assigns \result \from *z; */ +extern long __gmpz_get_si(const mpz_t z) + __attribute__((FC_BUILTIN)); + +/*@ requires \valid_read(q); + @ assigns \result \from *q; */ +extern double __gmpq_get_d(const mpq_t q) + __attribute__((FC_BUILTIN)); + +/*@ requires \valid_read(z); + @ assigns \result \from *z; */ +extern unsigned long __gmpz_get_ui(const mpz_t z) + __attribute__((FC_BUILTIN)); + +#endif diff --git a/src/plugins/e-acsl/share/e-acsl/e_acsl_leak.h b/src/plugins/e-acsl/share/e-acsl/e_acsl_leak.h new file mode 100644 index 0000000000000000000000000000000000000000..2b2f517986b940539192ee572dcefadefcb1c065 --- /dev/null +++ b/src/plugins/e-acsl/share/e-acsl/e_acsl_leak.h @@ -0,0 +1,70 @@ +/**************************************************************************/ +/* */ +/* This file is part of the Frama-C's E-ACSL plug-in. */ +/* */ +/* Copyright (C) 2012-2018 */ +/* CEA (Commissariat à l'énergie atomique et aux énergies */ +/* alternatives) */ +/* */ +/* you can redistribute it and/or modify it under the terms of the GNU */ +/* Lesser General Public License as published by the Free Software */ +/* Foundation, version 2.1. */ +/* */ +/* It is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Lesser General Public License for more details. */ +/* */ +/* See the GNU Lesser General Public License version 2.1 */ +/* for more details (enclosed in the file licenses/LGPLv2.1). */ +/* */ +/**************************************************************************/ + +/*! *********************************************************************** + * \file e_acsl_leak.h + * + * \brief Functionality to report/track memory leaks. Shared between models +***************************************************************************/ + +#ifndef E_ACSL_HEAP_LEAK_H +#define E_ACSL_HEAP_LEAK_H + +#include "e_acsl.h" + +/* Variable tracking byte-count of user-allocated heap memory. + Visible externally via __e_acsl_ prefix */ +size_t heap_allocation_size = 0; + +/* Variable tracking count of heap memory blocks */ +static size_t heap_allocated_blocks = 0; + +/* Return the number of bytes in heap application allocation */ +size_t get_heap_allocation_size(void) { + return heap_allocation_size; +} + +/* Return the number of blocks in heap application allocation */ +static inline size_t get_heap_allocated_blocks(void) { + return heap_allocated_blocks; +} + +/* Update heap allocation stats */ +static void update_heap_allocation(long size) { + heap_allocation_size += size; + if (size > 0) + heap_allocated_blocks++; + else if (size < 0) + heap_allocated_blocks--; +} + +static void report_heap_leaks() { +#if defined(E_ACSL_VERBOSE) || defined(E_ACSL_DEBUG) + size_t size = get_heap_allocation_size(); + size_t blocks = get_heap_allocated_blocks(); + if (size) { + rtl_printf(" *** WARNING: Leaked %lu bytes of heap memory in %ld block%s\n", + size, blocks, (blocks == 1) ? "" : "s"); + } +#endif +} +#endif diff --git a/src/plugins/e-acsl/share/e-acsl/e_acsl_libc_replacements.h b/src/plugins/e-acsl/share/e-acsl/e_acsl_libc_replacements.h new file mode 100644 index 0000000000000000000000000000000000000000..0ef0a734af48c90cb852f3c2a565f2447064a32f --- /dev/null +++ b/src/plugins/e-acsl/share/e-acsl/e_acsl_libc_replacements.h @@ -0,0 +1,303 @@ +/**************************************************************************/ +/* */ +/* This file is part of the Frama-C's E-ACSL plug-in. */ +/* */ +/* Copyright (C) 2012-2018 */ +/* CEA (Commissariat à l'énergie atomique et aux énergies */ +/* alternatives) */ +/* */ +/* you can redistribute it and/or modify it under the terms of the GNU */ +/* Lesser General Public License as published by the Free Software */ +/* Foundation, version 2.1. */ +/* */ +/* It is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Lesser General Public License for more details. */ +/* */ +/* See the GNU Lesser General Public License version 2.1 */ +/* for more details (enclosed in the file licenses/LGPLv2.1). */ +/* */ +/**************************************************************************/ + +/*! *********************************************************************** + * \file e_acsl_libc_replacements.h + * \brief Drop-in replacements for C library functions +***************************************************************************/ + +#ifndef E_ACSL_LIBC_REPLACEMENTS_H +#define E_ACSL_LIBC_REPLACEMENTS_H + +/************************************************************************/ +/*** Support functionality {{{ ***/ +/************************************************************************/ + +/* *** String validation {{{ */ + +/*! \brief Determine if `s` describes a C string up to length `n`. + + @return the index of `\0` character (i.e., the length of the string) + if `s` is a valid pointer of byte-size `len`, and + - `n` is negative and there is `\0` between `s` and the end of + the block `s` points to. + - `n` is positive and there is `\0` at index `i` (`i` < `n`) + and `s+i` belongs to the same block as `s`. + @return `n` if there is no `\0` between `s` and `s+n-1` but both + `s` and `s+n-1` belong to the same block. + + @return -1 if `s` does not belong to tracked allocation + @return -2 if `wrtbl` is set to a non-zero value and `s` is read-only + @return -3 if there is no `\0` between `s` and the end of its block and + `s+n-1` is unallocated or belongs to a different block. + @return -4 if `n` is negative and `s` is not NUL-terminated */ +static long valid_nstring(char *s, long n, int wrtbl) { + if (n == 0) + return n; + + int alc = allocated((uintptr_t)s, 1, (uintptr_t)s); + if (alc) { + if (wrtbl && readonly(s)) + return -2; /* Not writeable */ + long size = block_length(s) - offset(s); + long i; + for (i = 0; i < size; i++) { + if (s[i] == '\0' || n == i) + return i; + } + if (n == size) + return n; + if (n > size) + return -3; /* Insufficient length */ + return -4; /* Not NUL-terminated */ + } + return -1 /* Not allocated */; +} + +/*!\brief Same as ::valid_nstring but for wide characters. + + This function is very similar to ::valid_nstring. It is possible make it + more concise (say define it as a macro with types provided explicitly) yet + it is left this way for readibility reasons. */ +static long valid_nwstring(wchar_t *s, long n, int wrtbl) { + if (n == 0) + return n; + + int alc = allocated((uintptr_t)s, 1, (uintptr_t)s); + if (alc) { + if (wrtbl && readonly(s)) + return -2; /* Not writeable */ + long size = (block_length(s) - offset(s))/sizeof(wchar_t); + long i; + for (i = 0; i < size; i++) { + if (s[i] == L'\0' || n == i) + return i; + } + if (n == size) + return n; + if (n > size) + return -3; /* Insufficient length */ + return -4; /* Not NUL-terminated */ + } + return -1 /* Not allocated */; +} + +/*! \brief Same as ::valid_nstring but check a NUL-terminated string */ +static long inline valid_string(char *s, int wrtbl) { + return valid_nstring(s, -1, wrtbl); +} + +/*! \brief same as ::valid_string but for wide characters */ +static long inline valid_wstring(wchar_t *s, int wrtbl) { + return valid_nwstring(s, -1, wrtbl); +} + +static long validate_string + (char *s, long n, int wrtbl, const char *fun, const char *desc) +{ + long size = valid_nstring(s, n, wrtbl); + + switch(size) { + case -1: + vabort("%s: %sstring unallocated\n", fun, desc); + case -2: + vabort("%s: %sstring is not writable\n", fun, desc); + case -3: + vabort("%s: %sstring has insufficient length\n", fun, desc); + case -4: + vabort("%s: %sstring not NUL-terminated\n", fun, desc); + } + /* at this point negative return values should have been handled */ + vassert(size >= 0, "unexpected return value of %d\n", size); + return size; +} + +static inline long validate_writeable_string + (char *s, long n, const char *fun, const char *desc) +{ + return validate_string(s, n, 1, fun, desc); +} + +static inline long validate_allocated_string + (char *s, long n, const char *fun, const char *desc) +{ + return validate_string(s, n, 0, fun, desc); +} +/* }}} */ + +/* *** Memory spaces {{{ */ +/** \brief Return a true value if memory spaces given by intervals + [s1, s1 + s1_sz] and [s2, s2 + s2_sz] are disjoint */ +static inline int disjoint_spaces + (uintptr_t s1, size_t s1_sz, uintptr_t s2, size_t s2_sz) +{ + return s1 + s1_sz <= s2 || s2 + s2_sz <= s1; +} + +static inline void validate_allocated_space + (void *p, size_t sz, const char *func, const char *space) +{ + if (!allocated((uintptr_t)p, sz, (uintptr_t)p)) { + vabort("%s: unallocated (or insufficient) space in %s\n", func, space); + } +} + +static inline void validate_writeable_space(void *p, size_t sz, + const char *func, const char *space) { + if (!writeable((uintptr_t)p, sz, (uintptr_t)p)) { + if (writeable((uintptr_t)p, 1, (uintptr_t)p)) { + vabort("%s: insufficient space in %s, " + "at least %lu bytes required\n", func, space, sz); + } else { + vabort("%s: %s space unallocated or cannot be written\n", func, space); + } + } +} + +static inline void validate_overlapping_spaces + (uintptr_t s1, size_t s1_sz, uintptr_t s2, size_t s2_sz, const char *func) +{ + if (!disjoint_spaces(s1, s1_sz, s2, s2_sz)) + vabort("%s: overlapping memory areas\n", func); +} +/* }}} */ +/* }}} */ + +/************************************************************************/ +/*** strlen/strcpy/strcat/strcmp {{{ ***/ +/************************************************************************/ + +/* drop-in replacement for `strlen` */ +size_t builtin_strlen(const char *s) { + return validate_allocated_string((char*)s, -1, "strlen", "input "); +} + +/* drop-in replacement for `strcpy` */ +char *builtin_strcpy(char *dest, const char *src) { + // `src` string should be a valid NUL-terminated C string + size_t size = + validate_allocated_string((char*)src, -1, "strlen", "source string "); + /* `dest` should be writable and at least `size + 1` bytes long to + accommodate the NUL-terminator */ + validate_writeable_space(dest, size + 1, "strlen", "destination string"); + /* source and destination strings should not overlap */ + validate_overlapping_spaces + ((uintptr_t)dest, size + 1, (uintptr_t)src, size + 1, "strcpy"); + return strcpy(dest, src); +} + +/* drop-in replacement for `strncpy` */ +char *builtin_strncpy(char *dest, const char *src, size_t n) { + /* `src` should be a valid string up to `nth` character */ + validate_allocated_string((char*)src, n, "strncpy", "source string "); + /* `dest` should be allocated and writeable up to `nth` character */ + validate_writeable_space(dest, n, "strncpy", "destination string "); + /* source and destination strings should not overlap */ + validate_overlapping_spaces((uintptr_t)dest, n, (uintptr_t)src, n, "strncpy"); + return strncpy(dest, src, n); +} + +/* drop-in replacement for `strcmp` */ +int builtin_strcmp(const char *s1, const char *s2) { + /* both strings should be valid NUL-terminated strings */ + validate_allocated_string((char*)s1, -1, "strcmp", "string 1 "); + validate_allocated_string((char*)s2, -1, "strcmp", "string 2 "); + return strcmp(s1, s2); +} + +/* drop-in replacement for `strcmp` */ +int builtin_strncmp(const char *s1, const char *s2, size_t n) { + /* both strings should be valid up to nth character */ + validate_allocated_string((char*)s1, n, "strncmp", "string 1 "); + validate_allocated_string((char*)s2, n, "strncmp", "string 2 "); + return strncmp(s1, s2, n); +} + +/* drop-in replacement for `strcat` */ +char *builtin_strcat(char *dest, const char *src) { + long src_sz = + validate_allocated_string((char*)src, -1, "strcat", "source string "); + long dest_sz = + validate_writeable_string((char*)dest, -1, "strcat", "destination string "); + size_t avail_sz = block_length(dest) - offset(dest); + if (!(avail_sz >= src_sz + dest_sz + 1)) { + vabort("strcat: insufficient space in destination string, " + "available: %lu bytes, requires at least %lu bytes\n", + avail_sz, src_sz + dest_sz + 1); + } + validate_overlapping_spaces + ((uintptr_t)src, src_sz + 1, (uintptr_t)dest, dest_sz + 1, "strcat"); + return strcat(dest, src); +} + +/* drop-in replacement for `strncat` */ +char *builtin_strncat(char *dest, const char *src, size_t n) { + validate_allocated_string((char*)src, n, "strncat", "source string "); + long dest_sz = + validate_writeable_string((char*)dest, -1, "strcat", "destination string "); + size_t avail_sz = block_length(dest) - offset(dest); + if (!(avail_sz >= n + dest_sz + 1)) { + vabort("strncat: insufficient space in destination string, " + "available: %lu bytes, requires at least %lu bytes\n", + avail_sz, n + dest_sz + 1); + } + validate_overlapping_spaces + ((uintptr_t)src, n, (uintptr_t)dest, dest_sz, "strcat"); + return strncat(dest, src, n); +} +/* }}} */ + +/************************************************************************/ +/*** memcpy/memcmp/memset/memmove {{{ ***/ +/************************************************************************/ + +/* drop-in replacement for `memcpy` */ +void *builtin_memcpy(void *dest, const void *src, size_t n) { + validate_allocated_space((void*)src, n, "memcpy", "source space "); + validate_writeable_space((void*)dest, n, "memcpy", "destination space "); + validate_overlapping_spaces((uintptr_t)src, n, (uintptr_t)dest, n, "memcpy"); + return memcpy(dest, src, n); +} + +/* drop-in replacement for `memset` */ +void *builtin_memset(void *s, int c, size_t n) { + validate_writeable_space((void*)s, n, "memset", "space "); + return memset(s, c, n); +} + +/* drop-in replacement for `memcmp` */ +int builtin_memcmp(const void *s1, const void *s2, size_t n) { + validate_allocated_space((void*)s1, n, "memcmp", "space 1 "); + validate_allocated_space((void*)s2, n, "memcmp", "space 1 "); + validate_overlapping_spaces((uintptr_t)s1, n, (uintptr_t)s2, n, "memcpy"); + return memcmp(s1, s2, n); +} + +/* drop-in replacement for `memmove` */ +void *builtin_memmove(void *dest, const void *src, size_t n) { + validate_allocated_space((void*)src, n, "memcmp", "source space "); + validate_writeable_space((void*)dest, n, "memcmp", "destination space "); + return memmove(dest, src, n); +} + +/* }}} */ +#endif diff --git a/src/plugins/e-acsl/share/e-acsl/e_acsl_malloc.h b/src/plugins/e-acsl/share/e-acsl/e_acsl_malloc.h new file mode 100644 index 0000000000000000000000000000000000000000..c216fba3fadd0487360883484698cd5d59a0a2b0 --- /dev/null +++ b/src/plugins/e-acsl/share/e-acsl/e_acsl_malloc.h @@ -0,0 +1,145 @@ +/**************************************************************************/ +/* */ +/* This file is part of the Frama-C's E-ACSL plug-in. */ +/* */ +/* Copyright (C) 2012-2018 */ +/* CEA (Commissariat à l'énergie atomique et aux énergies */ +/* alternatives) */ +/* */ +/* you can redistribute it and/or modify it under the terms of the GNU */ +/* Lesser General Public License as published by the Free Software */ +/* Foundation, version 2.1. */ +/* */ +/* It is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Lesser General Public License for more details. */ +/* */ +/* See the GNU Lesser General Public License version 2.1 */ +/* for more details (enclosed in the file licenses/LGPLv2.1). */ +/* */ +/**************************************************************************/ + +/*! *********************************************************************** + * \file e_acsl_malloc.h + * + * \brief E-ACSL memory allocation bindings. +***************************************************************************/ + +#ifndef E_ACSL_MALLOC_H +#define E_ACSL_MALLOC_H + +#include <stdint.h> +#include <stddef.h> + +/* Memory allocated for internal use of RTL and for the use by the application + * is split into two mspaces (memory spaces). Memory allocation itself is + * delegated to a slightly customised version of dlmalloc shipped with the + * RTL. The overall pattern is as follows: + * mspace space = create_mspace(capacity, locks); + * char *p = mspace_malloc(space, size); */ + +/* Block size units in bytes */ +#define KB (1024) //!< Bytes in a kilobyte +#define MB (1024*KB) //!< Bytes in a megabyte +#define GB (1024*MB) //!< Bytes in a gigabyte +#define KB_SZ(_s) (_s/KB) //!< Convert bytes to kilobytes +#define MB_SZ(_s) (_s/MB) //!< Convert bytes to megabytes +#define GB_SZ(_s) (_s/GB) //!< Convert bytes to gigabytes + +typedef void* mspace; + +static struct memory_spaces { + mspace rtl_mspace; /* `private` (RTL) mspace */ + mspace heap_mspace; /* `public` (application) mspace */ + uintptr_t heap_start; /* least address in application mspace */ + uintptr_t heap_end; /* greatest address in application mspace */ + uintptr_t heap_mspace_least; /* Initial least address in heap mspace */ +} mem_spaces; + +/* While it is possible to generate prefixes using an extra level of + * indirection with macro definitions it is probably best not to do it, + * becomes barely readable ...*/ + +/* Mspace allocators {{{ */ +extern mspace __e_acsl_create_mspace(size_t, int); +extern size_t __e_acsl_destroy_mspace(mspace); +extern void* __e_acsl_mspace_malloc(mspace, size_t); +extern void __e_acsl_mspace_free(mspace, void*); +extern void* __e_acsl_mspace_calloc(mspace msp, size_t, size_t); +extern void* __e_acsl_mspace_realloc(mspace msp, void*, size_t); +extern void* __e_acsl_mspace_aligned_alloc(mspace, size_t, size_t); +extern int __e_acsl_mspace_posix_memalign(mspace, void **, size_t, size_t); +extern void* __e_acsl_mspace_least_addr(mspace); + +#define create_mspace __e_acsl_create_mspace +#define destroy_mspace __e_acsl_destroy_mspace +#define mspace_least_addr __e_acsl_mspace_least_addr +#define mspace_malloc __e_acsl_mspace_malloc +#define mspace_free __e_acsl_mspace_free +#define mspace_calloc __e_acsl_mspace_calloc +#define mspace_realloc __e_acsl_mspace_realloc +#define mspace_posix_memalign __e_acsl_mspace_posix_memalign +#define mspace_aligned_alloc __e_acsl_mspace_aligned_alloc +/* }}} */ + +/* Public allocators used within RTL to override standard allocation {{{ */ +/* Shortcuts for public allocation functions */ +# define public_malloc(...) mspace_malloc(mem_spaces.heap_mspace, __VA_ARGS__) +# define public_realloc(...) mspace_realloc(mem_spaces.heap_mspace, __VA_ARGS__) +# define public_calloc(...) mspace_calloc(mem_spaces.heap_mspace, __VA_ARGS__) +# define public_free(...) mspace_free(mem_spaces.heap_mspace, __VA_ARGS__) +# define public_aligned_alloc(...) mspace_aligned_alloc(mem_spaces.heap_mspace, __VA_ARGS__) +# define public_posix_memalign(...) mspace_posix_memalign(mem_spaces.heap_mspace, __VA_ARGS__) +/* }}} */ + +/* Private allocators usable within RTL and GMP {{{ */ +void * __e_acsl_private_malloc(size_t sz) { + return mspace_malloc(mem_spaces.rtl_mspace, sz); +} + +void *__e_acsl_private_calloc(size_t nmemb, size_t sz) { + return mspace_calloc(mem_spaces.rtl_mspace, nmemb, sz); +} + +void *__e_acsl_private_realloc(void *p, size_t sz) { + return mspace_realloc(mem_spaces.rtl_mspace, p, sz); +} + +void __e_acsl_private_free(void *p) { + mspace_free(mem_spaces.rtl_mspace, p); +} + +#define private_malloc __e_acsl_private_malloc +#define private_calloc __e_acsl_private_calloc +#define private_realloc __e_acsl_private_realloc +#define private_free __e_acsl_private_free +/* }}} */ + +/* \brief Create two memory spaces, one for RTL and the other for application + memory. This function *SHOULD* be called before any allocations are made + otherwise execution fails */ +static void make_memory_spaces(size_t rtl_size, size_t heap_size) { + mem_spaces.rtl_mspace = create_mspace(rtl_size, 0); + mem_spaces.heap_mspace = create_mspace(heap_size, 0); + /* Do not use `mspace_least_addr` here, as it returns the address of the + mspace header. */ + mem_spaces.heap_start = (uintptr_t)mspace_malloc(mem_spaces.heap_mspace,1); + mem_spaces.heap_end = mem_spaces.heap_start + heap_size; + /* Save initial least address of heap memspace. This address is used later + to check whether memspace has been moved. */ + mem_spaces.heap_mspace_least = (uintptr_t)mspace_least_addr(mem_spaces.heap_mspace); +} + +static void destroy_memory_spaces() { + destroy_mspace(mem_spaces.rtl_mspace); + destroy_mspace(mem_spaces.heap_mspace); +} + +/* \return a true value if x is a power of 2 and false otherwise */ +static int powof2(size_t x) { + while (((x & 1) == 0) && x > 1) /* while x is even and > 1 */ + x >>= 1; + return (x == 1); +} +#endif diff --git a/src/plugins/e-acsl/share/e-acsl/e_acsl_printf.h b/src/plugins/e-acsl/share/e-acsl/e_acsl_printf.h new file mode 100644 index 0000000000000000000000000000000000000000..729e8a1d633f1523679017d1180ad82622e0965e --- /dev/null +++ b/src/plugins/e-acsl/share/e-acsl/e_acsl_printf.h @@ -0,0 +1,442 @@ +/****************************************************************************/ +/* */ +/* Copyright (c) 2004,2012 Kustaa Nyholm / SpareTimeLabs */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions */ +/* are met: */ +/* */ +/* Redistributions of source code must retain the above copyright */ +/* notice, this list of conditions and the following disclaimer. */ +/* */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the name of the Kustaa Nyholm or SpareTimeLabs nor the names */ +/* of its contributors may be used to endorse or promote products derived */ +/* from this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* File modified by CEA (Commissariat à l'énergie atomique et aux */ +/* énergies alternatives). */ +/* */ +/****************************************************************************/ + +/*! *********************************************************************** + * \file e_acsl_printf.h + * \brief Malloc and stdio free implementation printf. + * + * Supported format strings: + * - Flag characters: + * - 0 - the following value will be is zero-padded. + * + * - Field width: + * - Optional positive decimal integer following flag characters. + * + * - Length modifier: + * - l - the following integer conversion corresponds to a long int or + * unsigned long int argument. + * + * - Standard conversion specifiers: + * - d - signed integers. + * - u - unsigned integers. + * - f - floating point numbers. Floating point numbers do not support + * - precision specification. + * - x,X - hexadecimal numbers. + * - p - void pointers. + * + * - Non-standard conversion specifiers: + * - a - memory-address. + * - b, B - print field width bits of a number left-to-right (b) or + * right-to-left (B). Unless specified field-width of 8 is used. Bits + * over a 64-bit boundary are ignored. + * - v, V - print first field width bits of a memory region given by a + * void pointer left-to-right (v) or right-to-left (V). Unless specified + * field-width of 8 is used. +***************************************************************************/ + +#ifndef E_ACSL_PRINTF_H +#define E_ACSL_PRINTF_H + +#include <unistd.h> +#include <stdint.h> +#include <stdarg.h> +#include "e_acsl_alias.h" + +/* ****************** */ +/* Public API */ +/* ****************** */ + +/* Replacement for printf with support for the above specifiers */ +static int rtl_printf(char *fmt, ...); + +/* Same as printf but write to a string buffer */ +static int rtl_sprintf(char* s, char *fmt, ...); + +/* Same as printf but write to the error stream. */ +static int rtl_eprintf(char *fmt, ...); + +/* Same as printf but write to a file descriptor. */ +static int rtl_dprintf(int fd, char *fmt, ...); + +/* ****************** */ +/* Implementation */ +/* ****************** */ + +typedef void (*putcf) (void*,char); + +/* Unsigned long integers to string conversion (%u) */ +static void uli2a(unsigned long int num, unsigned int base, int uc,char * bf) { + int n=0; + unsigned long int d=1; + while (num/d >= base) + d*=base; + while (d!=0) { + int dgt = num / d; + num%=d; + d/=base; + if (n || dgt>0|| d==0) { + *bf++ = dgt+(dgt<10 ? '0' : (uc ? 'A' : 'a')-10); + ++n; + } + } + *bf=0; +} + +/* Unsigned pointer-wide integers to memory address conversion (%a) */ +static void addr2a(uintptr_t addr, char * bf) { + *bf++ = '0'; + *bf++ = 'x'; + + unsigned int digits = 1; + int n=0; + unsigned long int d=1; + while (addr/d >= 10) { + d*=10; + digits++; + } + + unsigned int ctr = 0; + while (d!=0) { + ctr++; + int dgt = addr / d; + addr%=d; + d/=10; + if (n || dgt>0|| d==0) { + *bf++ = dgt+(dgt<10 ? '0' : 'a' - 10); + ++n; + } + if (--digits%5 == 0 && d != 0) + *bf++ = '-'; + } + *bf=0; +} + +/* Pointer to string conversion (%p) */ +static void ptr2a(void *p, char *bf) { + *bf++ = '0'; + *bf++ = 'x'; + uli2a((intptr_t)p,16,0,bf); +} + +/* Signed long integer to string conversion (%ld) */ +static void li2a (long num, char * bf) { + if (num<0) { + num=-num; + *bf++ = '-'; + } + uli2a(num,10,0,bf); +} + +/* Signed integer to string conversion (%d) */ +static void ui2a(unsigned int num, unsigned int base, int uc,char * bf) { + int n=0; + unsigned int d=1; + while (num/d >= base) + d*=base; + while (d!=0) { + int dgt = num / d; + num%= d; + d/=base; + if (n || dgt>0 || d==0) { + *bf++ = dgt+(dgt<10 ? '0' : (uc ? 'A' : 'a')-10); + ++n; + } + } + *bf=0; +} + +/* Integer bit-fields to string conversion (%b, %B) */ +static void bits2a(long int v, int size, char *bf, int l2r) { + int i; + if (l2r) { + for(i = 0; i < size; i++) { + *bf++ = '0' + ((v >> i) & 1); + if (i && i+1 < size && (i+1)%8 == 0) + *bf++ = ' '; + } + } else { + for(i = size - 1; i >= 0; i--) { + *bf++ = '0' + ((v >> i) & 1); + if (i && i+1 < size && i%4 == 0) + *bf++ = ' '; + } + } + *bf=0; +} + +/* Pointer bit-fields to string conversion (%v, %V) */ +static void pbits2a(void *p, int size, char *bf, int l2r) { + char *v = (char*)p; + int i; + if (l2r) { + for(i = 0; i < size; i++) { + *bf++ = '0' + ((v[i/8] >> i%8) & 1); + if (i && i+1 < size && (i+1)%4 == 0) + *bf++ = ' '; + } + } else { + for(i = size - 1; i >= 0; i--) { + *bf++ = '0' + ((v[i/8] >> i%8) & 1); + if (i && i+1 < size && i%4 == 0) + *bf++ = ' '; + } + } + *bf=0; +} + +/* Signed integer to string (%d) */ +static void i2a (int num, char * bf) { + if (num<0) { + num=-num; + *bf++ = '-'; + } + ui2a(num,10,0,bf); +} + +/* Char to int conversion */ +static int a2d(char ch) { + if (ch>='0' && ch<='9') + return ch-'0'; + else if (ch>='a' && ch<='f') + return ch-'a'+10; + else if (ch>='A' && ch<='F') + return ch-'A'+10; + else return -1; +} + +static char a2i(char ch, char** src, int base, int* nump) { + char* p= *src; + int num=0; + int digit; + while ((digit=a2d(ch))>=0) { + if (digit>base) break; + num=num*base+digit; + ch=*p++; + } + *src=p; + *nump=num; + return ch; +} + +static void putchw(void* putp, putcf putf, int n, char z, char* bf) { + char fc=z? '0' : ' '; + char ch; + char* p=bf; + while (*p++ && n > 0) + n--; + while (n-- > 0) + putf(putp,fc); + while ((ch= *bf++)) + putf(putp,ch); +} + +static void putcp(void* p,char c) { + *(*((char**)p))++ = c; +} + +static void _format(void* putp, putcf putf, char *fmt, va_list va) { + char bf[256]; + char ch; + while ((ch=*(fmt++))) { + if (ch!='%') // if not '%' print character as is + putf(putp,ch); + else { // otherwise do the print based on the format following '%' + char lz=0; + char lng=0; // long (i.e., 'l' specifier) + int w=0; + ch=*(fmt++); + if (ch=='0') { // '0' specifier - padding with zeroes + ch=*(fmt++); + lz=1; + } + if (ch>='0' && ch<='9') { + ch=a2i(ch,&fmt,10,&w); + } + if (ch=='l') { + ch=*(fmt++); + lng=1; + } + switch (ch) { + case 0: + break; + case 'u': { + if (lng) + uli2a(va_arg(va, unsigned long int),10,0,bf); + else + ui2a(va_arg(va, unsigned int),10,0,bf); + putchw(putp,putf,w,lz,bf); + break; + } + case 'd': { + if (lng) + li2a(va_arg(va, unsigned long int),bf); + else + i2a(va_arg(va, int),bf); + putchw(putp,putf,w,lz,bf); + break; + } + case 'p': + ptr2a(va_arg(va, void*), bf); + putchw(putp,putf,w,lz,bf); + break; + case 'a': + addr2a(va_arg(va, uintptr_t), bf); + putchw(putp,putf,w,lz,bf); + break; + case 'b': + bits2a(va_arg(va, long), w > 64 ? 64 : w ? w : 8, bf, 1); + putchw(putp,putf,0,0,bf); + break; + case 'B': + bits2a(va_arg(va, long), w > 64 ? 64 : w ? w : 8, bf, 0); + putchw(putp,putf,0,0,bf); + break; + case 'v': + pbits2a(va_arg(va, void*), w ? w : 8, bf, 1); + putchw(putp,putf,0,0,bf); + break; + case 'V': + pbits2a(va_arg(va, void*), w ? w : 8, bf, 0); + putchw(putp,putf,0,0,bf); + break; + case 'x': + case 'X': + if (lng) + uli2a(va_arg(va, unsigned long int),16,(ch=='X'),bf); + else + ui2a(va_arg(va, unsigned int),16,(ch=='X'),bf); + putchw(putp,putf,w,lz,bf); + break; + case 'f' : { + double num = va_arg(va, double); + int ord = (int)num; + i2a(ord,bf); + putchw(putp,putf,w,lz,bf); + putf(putp,'.'); + num = num - ord; + num *= 1000; + ord = (int)num; + i2a(ord,bf); + putchw(putp,putf,w,lz,bf); + break; + } + case 'c' : + putf(putp,(char)(va_arg(va, int))); + break; + case 's' : + putchw(putp,putf,w,0,va_arg(va, char*)); + break; + case '%' : + putf(putp,ch); + default: + break; + } + } + } +} + +static void _charc_stdout (void* p, char c) { write(1,&c,1); } +static void _charc_stderr (void* p, char c) { write(2,&c,1); } +static void _charc_file (void* p, char c) { write((size_t)p,&c,1); } + +static void _charc_literal (void* p, char c) { + switch(c) { + case '\r': + write((size_t)p,"\\r",2); + break; + case '\f': + write((size_t)p,"\\f",2); + break; + case '\b': + write((size_t)p,"\\b",2); + break; + case '\a': + write((size_t)p,"\\a",2); + break; + case '\n': + write((size_t)p,"\\n",2); + break; + case '\t': + write((size_t)p,"\\t",2); + break; + case '\0': + write((size_t)p,"\\0",2); + break; + default: + write((size_t)p,&c,1); + } +} + +static int rtl_printf(char *fmt, ...) { + va_list va; + va_start(va,fmt); + _format(NULL,_charc_stdout,fmt,va); + va_end(va); + return 1; +} + +static int rtl_eprintf(char *fmt, ...) { + va_list va; + va_start(va,fmt); + _format(NULL,_charc_stderr,fmt,va); + va_end(va); + return 1; +} + +static int rtl_dprintf(int fd, char *fmt, ...) { + va_list va; + va_start(va,fmt); + intptr_t fd_long = fd; + _format((void*)fd_long,_charc_file,fmt,va); + va_end(va); + return 1; +} + +static int rtl_sprintf(char* s, char *fmt, ...) { + va_list va; + va_start(va,fmt); + _format(&s,putcp,fmt,va); + putcp(&s,0); + va_end(va); + return 1; +} + +#define STDOUT(...) rtl_printf(__VA_ARGS__) +#define STDERR(...) rtl_eprintf(__VA_ARGS__) + +#endif diff --git a/src/plugins/e-acsl/share/e-acsl/e_acsl_rtl.c b/src/plugins/e-acsl/share/e-acsl/e_acsl_rtl.c new file mode 100644 index 0000000000000000000000000000000000000000..2d5d3668076182414bcd4f60d586221bccbd6bfb --- /dev/null +++ b/src/plugins/e-acsl/share/e-acsl/e_acsl_rtl.c @@ -0,0 +1,141 @@ +/**************************************************************************/ +/* */ +/* This file is part of the Frama-C's E-ACSL plug-in. */ +/* */ +/* Copyright (C) 2012-2018 */ +/* CEA (Commissariat à l'énergie atomique et aux énergies */ +/* alternatives) */ +/* */ +/* you can redistribute it and/or modify it under the terms of the GNU */ +/* Lesser General Public License as published by the Free Software */ +/* Foundation, version 2.1. */ +/* */ +/* It is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Lesser General Public License for more details. */ +/* */ +/* See the GNU Lesser General Public License version 2.1 */ +/* for more details (enclosed in the file licenses/LGPLv2.1). */ +/* */ +/**************************************************************************/ + +/*! *********************************************************************** + * \file e_acsl_rtl.c + * \brief RTL configuration and assembly +***************************************************************************/ + +/* Get default definitions and macros e.g., PATH_MAX */ +#ifndef _DEFAULT_SOURCE +# define _DEFAULT_SOURCE 1 +#endif + +#include "e_acsl_alias.h" +#include "e_acsl_malloc.h" +#include "e_acsl_string.h" +#include "e_acsl_bits.h" +#include "e_acsl_printf.h" +#include "e_acsl_debug.h" +#include "e_acsl_shexec.h" +#include "e_acsl_trace.h" +#include "e_acsl_assert.h" +#include "e_acsl_floating_point.h" +#include "e_acsl_safe_locations.h" +#include "e_acsl_temporal_timestamp.h" +#include "e_acsl.h" + +/* Memory model settings + * Memory model: + * E_ACSL_BITTREE_MMODEL - use Patricia-trie (tree-based) memory model, or + * E_ACSL_SEGMENT_MMODEL - use segment-based (shadow) memory model + * Verbosity level: + * E_ACSL_VERBOSE - put an executable in verbose mode that + * prints extra messages (unset by default) + * Debug Features: + * E_ACSL_DEBUG - enable debug features in RTL (unset by default) + * E_ACSL_DEBUG_VERBOSE - verbose debug output (via DVLOG macro) + * E_ACSL_DEBUG_LOG - name of the log file where debug messages are + * output. The file name should be unquoted string with '-' + * (set by default) indicating a standard stream + * Validity: + * E_ACSL_WEAK_VALIDITY - use notion of weak validity + * Given an expression `(p+i)`, where `p` is a pointer and `i` is an + * integer offset weak validity indicates that `(p+i)` is valid if it + * belongs to memory allocation. In strong validity `(p+i)` is valid + * iff both `p` and `(p+i)` belong to memory allocation and to the same + * memory block. + * Temporal analysis: + * E_ACSL_TEMPORAL - enable temporal analysis in RTL + * Assertions: + * E_ACSL_NO_ASSERT_FAIL - do not issue abort signal of E-ACSL + * assertion failure + * E_ACSL_FAIL_EXITCODE - do not issue abort signal but exit with a + * given code + * Shadow spaces (only for segment model): + * E_ACSL_STACK_SIZE - size (in MB) of the tracked program stack + * E_ACSL_HEAP_SIZE - size (in MB) of the tracked program heap + * String functions: + * E_ACSL_NO_COMPILER_BUILTINS - if undefined (default) then use + * compiler builtin string functions (e.g., memset -> __builtin_memset) + * Behaviour of assert: + * E_ACSL_EXTERNAL_ASSERT - if this macro is defined then function + * `__e_acsl_assert` is excluded from compilation. This is to allow + * providing alternative definitions of assertions by users. + * Memory deallocation: + * E_ACSL_FREE_VALID_ADDRESS -- Clause 7.20.3.2 of C99 standard states + * that NULL is a valid input to free: + * "The free function causes the space pointed to by ptr [its argument] + * to be deallocated, that is, made available for further allocation. + * If ptr is a null pointer, no action occurs." + * Yet, some tools insist that it is a bug. For instance, there is a + * bunch of test cases in Toyota ITC Benchmarks. To make such tools + * happy the following option is introduced. By default it should be + * undefined (disabled) though. +*/ + +/* Functionality tracking leaks is shared between models */ +#include "e_acsl_leak.h" + +/* Print a header indicating current configuration of a run to STDIN. */ +static void describe_run(); + +/* Select memory model, either segment-based or bittree-based model should + be defined */ +#if defined E_ACSL_SEGMENT_MMODEL +# include "segment_model/e_acsl_segment_mmodel.c" +#elif defined E_ACSL_BITTREE_MMODEL +# include "bittree_model/e_acsl_bittree_mmodel.c" +#else +# error "No E-ACSL memory model defined. Aborting compilation" +#endif + +/* Headers containing implementation of functions belonging to the E-ACSL + external API shared across different memory models */ +#include "e_acsl_libc_replacements.h" /* */ +#include "e_acsl_format.h" /* format functions with error checking */ +#include "e_acsl_temporal.h" /* temporal analysis */ + +#ifdef E_ACSL_WEAK_VALIDITY +# define E_ACSL_VALIDITY_DESC "weak" +#else +# define E_ACSL_VALIDITY_DESC "strong" +#endif + +/* Print basic configuration before each run */ +static void describe_run() { +#if defined(E_ACSL_VERBOSE) + rtl_printf("/* ========================================================= */\n"); + rtl_printf(" * E-ACSL instrumented run\n" ); + rtl_printf(" * Memory tracking: %s\n", E_ACSL_MMODEL_DESC); +#ifdef E_ACSL_SEGMENT_MMODEL + rtl_printf(" * Heap %d MB\n", E_ACSL_HEAP_SIZE); + rtl_printf(" * Stack %d MB\n", E_ACSL_STACK_SIZE); +#endif + rtl_printf(" * Temporal checks: %s\n", E_ACSL_TEMPORAL_DESC); + rtl_printf(" * Execution mode: %s\n", E_ACSL_DEBUG_DESC); + rtl_printf(" * Assertions mode: %s\n", E_ACSL_ASSERT_NO_FAIL_DESC); + rtl_printf(" * Validity notion: %s\n", E_ACSL_VALIDITY_DESC); + rtl_printf(" * Format Checks: %s\n", E_ACSL_FORMAT_VALIDITY_DESC); + rtl_printf("/* ========================================================= */\n"); +#endif +} diff --git a/src/plugins/e-acsl/share/e-acsl/e_acsl_safe_locations.h b/src/plugins/e-acsl/share/e-acsl/e_acsl_safe_locations.h new file mode 100644 index 0000000000000000000000000000000000000000..d98a944cc10831639161c033795ba7d590c7c4ac --- /dev/null +++ b/src/plugins/e-acsl/share/e-acsl/e_acsl_safe_locations.h @@ -0,0 +1,77 @@ +/**************************************************************************/ +/* */ +/* This file is part of the Frama-C's E-ACSL plug-in. */ +/* */ +/* Copyright (C) 2012-2018 */ +/* CEA (Commissariat à l'énergie atomique et aux énergies */ +/* alternatives) */ +/* */ +/* you can redistribute it and/or modify it under the terms of the GNU */ +/* Lesser General Public License as published by the Free Software */ +/* Foundation, version 2.1. */ +/* */ +/* It is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Lesser General Public License for more details. */ +/* */ +/* See the GNU Lesser General Public License version 2.1 */ +/* for more details (enclosed in the file licenses/LGPLv2.1). */ +/* */ +/**************************************************************************/ + +/*! *********************************************************************** + * \file e_acsl_malloc.h + * + * \brief E-ACSL memory allocation bindings. +***************************************************************************/ + +/* Declaration of memory locations considered safe before a program starts. + * Most of these should be declared somewhere in start procedures of c + * and gcc libraries. One example of a safe location is errno. */ + +#ifndef E_ACSL_SAFE_LOCATIONS_H +#define E_ACSL_SAFE_LOCATIONS_H + +#include <stdio.h> +#include <stdint.h> +#include <errno.h> + +/* Simple representation of a safe location */ +struct memory_location { + uintptr_t address; /* Address */ + uintptr_t length; /* Byte-length */ + int is_initialized; /* Notion of initialization */ +}; + +typedef struct memory_location memory_location; + +/* An array storing safe locations up to `safe_location_counter` position. + * This array should be initialized via a below function called + * `collect_safe_locations`. */ +static memory_location safe_locations [16]; +static int safe_location_counter = 0; + +#define add_safe_location(_addr,_len,_init) { \ + safe_locations[safe_location_counter].address = _addr; \ + safe_locations[safe_location_counter].length = _len; \ + safe_location_counter++; \ +} + +#ifdef errno +#undef errno +extern __thread int errno; +#endif + +extern FILE *stdin; /* Standard input stream. */ +extern FILE *stdout; /* Standard output stream. */ +extern FILE *stderr; /* Standard error output stream. */ + +static void collect_safe_locations() { + /* Tracking of errno and standard streams */ + add_safe_location((uintptr_t)&errno, sizeof(int), "errno"); + add_safe_location((uintptr_t)stdout, sizeof(FILE), "stdout"); + add_safe_location((uintptr_t)stderr, sizeof(FILE), "stderr"); + add_safe_location((uintptr_t)stdin, sizeof(FILE), "stdin"); +} +#endif diff --git a/src/plugins/e-acsl/share/e-acsl/e_acsl_shexec.h b/src/plugins/e-acsl/share/e-acsl/e_acsl_shexec.h new file mode 100644 index 0000000000000000000000000000000000000000..fea42b6d1e5d5764c24a3bbdda82d3ac3e698052 --- /dev/null +++ b/src/plugins/e-acsl/share/e-acsl/e_acsl_shexec.h @@ -0,0 +1,228 @@ +/**************************************************************************/ +/* */ +/* This file is part of the Frama-C's E-ACSL plug-in. */ +/* */ +/* Copyright (C) 2012-2018 */ +/* CEA (Commissariat à l'énergie atomique et aux énergies */ +/* alternatives) */ +/* */ +/* you can redistribute it and/or modify it under the terms of the GNU */ +/* Lesser General Public License as published by the Free Software */ +/* Foundation, version 2.1. */ +/* */ +/* It is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Lesser General Public License for more details. */ +/* */ +/* See the GNU Lesser General Public License version 2.1 */ +/* for more details (enclosed in the file licenses/LGPLv2.1). */ +/* */ +/**************************************************************************/ + +/*! *********************************************************************** + * \file e_acsl_shexec.h + * \brief Interface for running shell commands +***************************************************************************/ + +#ifndef E_ACSL_SHEXEC_H +#define E_ACSL_SHEXEC_H + +#include <stddef.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <unistd.h> +#include <errno.h> +#include "e_acsl_string.h" + +/*! \class ipr_t + * \brief Result struct for `shexec` function -- execute a command in the + * shell via fork/exec and return results */ +typedef struct { + /** \brief resulting STDERR stream as \p const \p char* */ + char *stderrs; + /** \brief Supplied STDIN stream as \p const \p char* */ + char *stdins; + /** \brief resulting STDOUT stream as \p const \p char* */ + char *stdouts; + /** \brief Exit status of a program */ + int exit_status; + /** \brief ID of a child process this command has been executed in */ + pid_t pid; + /** \brief Set to non-zero if child process is interrupted via a signal */ + int signaled; + /** \brief If \p signalled is set, \p signo is set to the number of signal + * that interrupted execution of a child process */ + int signo; + /** \brief A command to execute. Needs to be NULL terminated */ + char **argv; /** \brief ARGV */ + /** \brief Message if the command has failed to run */ + char *error; +} ipr_t; + +/* \brief Read characters from a buffer associated with a file descriptor into + * a C string + * + * Read a string from a buffer associated with a file descriptor by allocating + * a string of an initial size and increasing the size of a buffer with + * realloc. This is for the cases when we can not quickly seek through the + * file and identify the size of a buffer associated with a file descriptor + * + * \param fd - file descriptor to read from + * \param bufsize - the number of characters we read a t a time + * + * \return NUL-terminated C string on success + * \return NULL on failure */ +static char* fd_read (int fd, short bufsize) { + /* Read `buffer_size` chars at a time */ + short buffer_size = bufsize*sizeof(char); + /* Size of the fetched string */ + int size = buffer_size; + /* Buffer where for read data */ + char *buffer = (char*)private_malloc(size); + /* The number of read bytes */ + short fetched = 0; + int rd = 0; /* Count of fetched characters */ + + /* Each time the pointer is moved by `size - buffer_size`. + * This is because initially the size of `buffer` is `buffer_size`. */ + while ((fetched = read(fd, buffer + size - buffer_size, buffer_size))) { + rd += fetched; + if (fetched != -1) { + size += fetched*sizeof(char); + buffer = private_realloc(buffer, size + 1); + } else { + return NULL; + } + } + buffer[rd] = '\0'; + return buffer; +} + +/* Execute a command in the shell and place results to data */ +static ipr_t* __shexec (ipr_t *data) { + int outfd[2], errfd[2], infd[2]; + int oldstdout, oldstderr, oldstdin; + + if (pipe(infd)) /* From where parent is going to read */ + data->error = nstrdup("Can not create a pipe for STDIN"); + if (pipe(outfd)) /* From where parent is going to read */ + data->error = nstrdup("Can not create a pipe for STDOUT"); + if (pipe(errfd)) /* From where parent is going to read */ + data->error = nstrdup("Can not create a pipe for STDERR"); + + /* Immediately return if reading from one of the STD pipes failed */ + if (data->error) + return data; + + /* Save stdin, stdout and stderr */ + oldstdin = dup(0); + oldstdout = dup(1); + oldstderr = dup(2); + + /* Close stdin, stdout and stderr */ + close(0); + close(1); + close(2); + + dup2(infd[0], 0); /* Make the read end of infd as STDIN */ + dup2(outfd[1],1); /* Make the write end of outfd as STDOUT */ + dup2(errfd[1],2); /* Make the write end of outfd as STDERR */ + + pid_t pid = fork(); + + if(!pid) { + /* Close the streams as they are not required for a child */ + close(infd[0]); close(outfd[0]); close(errfd[0]); + close(infd[1]); close(outfd[1]); close(errfd[1]); + + execvp(data->argv[0],data->argv); + if (errno) { + data->error = nstrdup("Failed to execute:\n "); + char **arg = data->argv - 1; + while(*++arg) + data->error = sappend(*arg, data->error, " "); + } + } else { + close(0); + close(1); + close(2); + dup2(oldstdin, 0); + dup2(oldstdout,1); + dup2(oldstderr,2); + close(outfd[1]); + close(errfd[1]); + close(infd[0]); + + /* If data->stdin string is supplied, write that string to the child's + stdin first */ + if (data->stdins) /* Return NULL if write fails */ + if (write(infd[1], data->stdins, strlen(data->stdins)) == -1) + return NULL; + + /* Read from child's stdout and stderr */ + data->stdouts = fd_read(outfd[0], 256); + if (!data->stdouts) + data->error = nstrdup("Error reading from STDOUT pipe"); + data->stderrs = fd_read(errfd[0], 256); + if (!data->stderrs) + data->error = nstrdup("Error reading from STDERR pipe"); + + /* Close file descriptors that are still open */ + close(outfd[0]); /* read end of STDOUT */ + close(errfd[0]); /* read end of STDERR */ + close(infd[1]); /* write end of STDIN */ + + int status; + waitpid(pid, &status, 0); /* wait for the child to finish */ + + data->exit_status = WEXITSTATUS(status); /* exit status */ + data->pid = pid; /* process number */ + data->signaled = WIFSIGNALED(status); /* signal caught */ + data->signo = WTERMSIG(status); /* signal number caught */ + return data; + } + return NULL; +} + +/* \brief Deallocate an `ipr_t` structure returned by `shexec` */ +static void free_ipr (ipr_t* ipr) { + if (ipr) { + if (ipr->stdouts) + private_free(ipr->stdouts); + if (ipr->stderrs) + private_free(ipr->stderrs); + if (ipr->error) + private_free(ipr->error); + if (ipr->stdins) + private_free(ipr->stdins); + private_free(ipr); + } +} + +/* \brief Execute a command given via parameter `data` in the current shell + * and return the dynamically allocated struct `ipr_t` which captures the + * results of the command's execution. + * + * \param data - command to execute. `data` is expected to be a NULL-terminated + * array of C strings. + * \param sin - if not NULL, a C string given via `sin` is supplied as standard + * input to the executed command. + * \return - heap-allocated struct `ipr_t` which describes the output of the + * executed command. Deallocation of this struct must be performed via the + * `free_ipr` function. */ +static ipr_t* shexec (char **data, const char *sin) { + /* Allocate and initialise the `ipr_t` struct to store the results + * of the command execution */ + ipr_t *ipr = (ipr_t*)private_malloc(sizeof(ipr_t)); + ipr->stderrs = NULL; + ipr->stdouts = NULL; + ipr->stdins = nstrdup(sin); + ipr->argv = data; + ipr->exit_status = 0; + ipr->pid = 0; + ipr->signaled = 0; + /* Run the command returning a pointer to `ipr_t` */ + return __shexec(ipr); +} +#endif diff --git a/src/plugins/e-acsl/share/e-acsl/e_acsl_string.h b/src/plugins/e-acsl/share/e-acsl/e_acsl_string.h new file mode 100644 index 0000000000000000000000000000000000000000..c0e694b58157f227929ff61420d7e3da2d004096 --- /dev/null +++ b/src/plugins/e-acsl/share/e-acsl/e_acsl_string.h @@ -0,0 +1,146 @@ +/**************************************************************************/ +/* */ +/* This file is part of the Frama-C's E-ACSL plug-in. */ +/* */ +/* Copyright (C) 2012-2018 */ +/* CEA (Commissariat à l'énergie atomique et aux énergies */ +/* alternatives) */ +/* */ +/* you can redistribute it and/or modify it under the terms of the GNU */ +/* Lesser General Public License as published by the Free Software */ +/* Foundation, version 2.1. */ +/* */ +/* It is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Lesser General Public License for more details. */ +/* */ +/* See the GNU Lesser General Public License version 2.1 */ +/* for more details (enclosed in the file licenses/LGPLv2.1). */ +/* */ +/**************************************************************************/ + +/*! *********************************************************************** + * \file e_acsl_string.h + * \brief Replacement of system-wide \p <string.h> header for use with E-ACSL + * runtime library. + * + * Intended use: + * - For the case when the sources are compiled using GCC prefer \p __builtin_ + * versions of some of the string.h functions (e.g., \p memset). This is + * mostly because the GCC builtins are on average faster. + * - For the case it is not GCC system-wide versions should be used. This + * and the above options require \p E_ACSL_BUILTINS macro to be defined + * at compile-time. + * - For the case when the analysed program contains customised definitions + * of string.h functions use GLIBC-based implementations. +***************************************************************************/ + +#ifndef E_ACSL_STD_STRING_H +#define E_ACSL_STD_STRING_H + +#ifndef E_ACSL_NO_COMPILER_BUILTINS +# define memset __builtin_memset +# define memcmp __builtin_memcmp +# define memcpy __builtin_memcpy +# define memmove __builtin_memmove +# define strncat __builtin_strncat +# define strcat __builtin_strcat +# define strlen __builtin_strlen +# define strcmp __builtin_strcmp +# define strncmp __builtin_strncmp +# define strcpy __builtin_strcpy +# define strncpy __builtin_strncpy +# define strchr __builtin_strchr +#else +# include <string.h> +#endif + +#include <stddef.h> +#include "e_acsl_malloc.h" + +/* \brief Local version of `strcat` */ +static char *nstrcat(char *dest, const char *src) { + memcpy(dest + strlen(dest), src, strlen(src) + 1); + return dest; +} + +/* \brief Local version of `strdup` */ +static char *nstrdup(const char *s) { + if (s) { + size_t len = strlen(s) + 1; + void *n = private_malloc(len); + return (n == NULL) ? NULL : (char*)memcpy(n, s, len); + } + return NULL; +} + +/* \brief Append `src` to `dest` by re-allocating `dest`. + * + * `sappend` assumes that `dest` is either NULL (in which case it is + * allocated on the heap) or a heap-allocated C string that can be passed + * as an input to realloc. If `delim` and `dest` are not NULLs them string + * `delim` is appended to `dest` before `src` + * + * \return Result of concatenation of `dest` and `src` */ +static char *sappend(char *dest, const char *src, const char *delim) { + if (!dest && src) + dest = nstrdup(src); + else if (src && dest) { + size_t ldelim = delim ? strlen(delim) : 0; + size_t len = strlen(src) + strlen(dest) + 1; + if (ldelim) + len += ldelim; + dest = private_realloc(dest, len); + if (ldelim) + dest = nstrcat(dest, delim); + dest = nstrcat(dest, src); + } + return dest; +} + +/** \brief Return 0 if C string `str` ends with string `pat` and a non-zero + * value otherwise. The function assumes that both, `str` and `path` are valid, + * NUL-terminated C strings. If any of the input strings are NULLs, a non-zero + * value is returned. */ +static int endswith(char *str, char *pat) { + if (str && pat) { + size_t slen = strlen(str); + size_t plen = strlen(pat); + if (slen >= plen) { + str += slen - plen; + return strncmp(str, pat, plen); + } + } + return 1; +} + +#define ZERO_BLOCK_SIZE 1024 +static unsigned char zeroblock [ZERO_BLOCK_SIZE]; + +/** \brief Return a non-zero value if `size` bytes past address `p` are + * nullified and zero otherwise. */ +static int zeroed_out(const void *p, size_t size) { + size_t lim = size/ZERO_BLOCK_SIZE, + rem = size%ZERO_BLOCK_SIZE; + unsigned char *pc = (unsigned char *)p; + + size_t i; + for (i = 0; i < lim; i++) { + if (memcmp(pc, &zeroblock, ZERO_BLOCK_SIZE)) + return 0; + pc += ZERO_BLOCK_SIZE; + } + return !memcmp(pc, &zeroblock, rem); +} + +/** \brief Count the number of occurrences of char `c` in a string `s` */ +static int charcount(const char *s, char c) { + int count = 0; + while ((s = strchr(s,c)) != NULL) { + count++; + s++; + } + return count; +} +#endif diff --git a/src/plugins/e-acsl/share/e-acsl/e_acsl_temporal.h b/src/plugins/e-acsl/share/e-acsl/e_acsl_temporal.h new file mode 100644 index 0000000000000000000000000000000000000000..6caa803e1b127d577f3689fa8ae51426a4dd629d --- /dev/null +++ b/src/plugins/e-acsl/share/e-acsl/e_acsl_temporal.h @@ -0,0 +1,163 @@ +/**************************************************************************/ +/* */ +/* This file is part of the Frama-C's E-ACSL plug-in. */ +/* */ +/* Copyright (C) 2012-2018 */ +/* CEA (Commissariat à l'énergie atomique et aux énergies */ +/* alternatives) */ +/* */ +/* you can redistribute it and/or modify it under the terms of the GNU */ +/* Lesser General Public License as published by the Free Software */ +/* Foundation, version 2.1. */ +/* */ +/* It is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Lesser General Public License for more details. */ +/* */ +/* See the GNU Lesser General Public License version 2.1 */ +/* for more details (enclosed in the file licenses/LGPLv2.1). */ +/* */ +/**************************************************************************/ + +/*! *********************************************************************** + * \file e_acsl_temporal.h + * \brief Implementation of the tenporal API shared by all models +***************************************************************************/ +#ifndef E_ACSL_TEMPORAL_H +#define E_ACSL_TEMPORAL_H + +#include "e_acsl_temporal_timestamp.h" + +#ifdef E_ACSL_TEMPORAL +#define E_ACSL_TEMPORAL_DESC "enabled" + +/* Temporal timestamp retrieval [forward declarations] {{{ */ +/*! \brief Return origin time stamp associated with a memory block containing + * address given by `ptr`. `0` indicates an invalid timestamp, i.e., timestamp + * of a memory block which does not exist. */ +static uint32_t origin_timestamp(void *ptr); + +/*! \brief Return address of referent shadow */ +static uintptr_t temporal_referent_shadow(void *addr); + +/*! \brief Return referent time stamp associated with a pointer which address + * is given by `ptr`. This function expects that `ptr` is allocated and at + * least `sizeof(uintptr_t)` bytes long */ +uint32_t referent_timestamp(void *ptr); + +/*! \brief Store a referent number `ref` in the shadow of `ptr` */ +void store_temporal_referent(void *ptr, uint32_t ref); +/* }}} */ + +/* Temporal store {{{ */ +void temporal_store_nblock(void *lhs, void *rhs) { + store_temporal_referent(lhs, origin_timestamp(rhs)); +} + +void temporal_store_nreferent(void *lhs, void *rhs) { + store_temporal_referent(lhs, referent_timestamp(rhs)); +} + +/* }}} */ + +/* Memcpy/memset {{{ */ +void temporal_memcpy(void *dest, void *src, size_t size) { + /* Memcpy is only relevant for pointers here, so if there is a + * copy under a pointer's size then there no point in copying memory*/ + if (size >= sizeof(void*)) { + DVALIDATE_ALLOCATED(src, size, src); + DVALIDATE_WRITEABLE(dest, size, dest); + void *dest_shadow = (void *)temporal_referent_shadow(dest); + void *src_shadow = (void *)temporal_referent_shadow(src); + memcpy(dest_shadow, src_shadow, size); + } +} + +void temporal_memset(void *dest, int c, size_t size) { + DVALIDATE_WRITEABLE(dest, size, dest); + void *dest_shadow = (void *)temporal_referent_shadow(dest); + memset(dest_shadow, 0, size); +} +/* }}} */ + +/* Function parameters {{{ */ +void temporal_save_nblock_parameter(void *ptr, unsigned int param) { + parameter_referents[param].ptr = ptr; + parameter_referents[param].temporal_flow = TBlockN; +} + +void temporal_save_nreferent_parameter(void *ptr, unsigned int param) { + parameter_referents[param].ptr = ptr; + parameter_referents[param].temporal_flow = TReferentN; +} + +void temporal_save_copy_parameter(void *ptr, unsigned int param) { + parameter_referents[param].ptr = ptr; + parameter_referents[param].temporal_flow = TCopy; +} + +void temporal_pull_parameter(void *ptr, unsigned int param, size_t size) { + struct temporal_parameter *tpar = ¶meter_referents[param]; + switch(tpar->temporal_flow) { + case TBlockN: + store_temporal_referent(ptr, origin_timestamp(tpar->ptr)); + break; + case TReferentN: + store_temporal_referent(ptr, referent_timestamp(tpar->ptr)); + break; + case TCopy: + temporal_memcpy(ptr, tpar->ptr, size); + break; + default: + vassert(0, "Unreachable", NULL); + } +} + +void temporal_reset_parameters() { + reset_parameter_referents(); +} +/* }}} */ + +/* Return values {{{ */ +void temporal_save_return(void *ptr) { + return_referent = (ptr, sizeof(void*)) ? referent_timestamp(ptr) : 0; +} + +void temporal_pull_return(void *ptr) { + store_temporal_referent(ptr, return_referent); +} + +void temporal_reset_return() { + return_referent = 0; +} +/* }}} */ + +/* Temporal valid {{{ */ +int temporal_valid(void *ptr, void *addr_of_ptr) { + /* Could check for NULL, but since temporal_valid if ran by `valid`, this + * has been already checked. + * FIXME: If the address of pointer and the pointer itself reference the same + * address the access is deemed temporally valid by default. + * One issue associated with such checking is the case when a pointer points + * to itself. One way to address such issue is to mark pointers, arrays and + * integers differently. Here one can use the "readonly" bit to mark + * something which does not need to be checked (e.g. arrays) and then + * recognise this mark. Blocks can be recognised as readonly by using range + * checking. For instance if some existing block belongs to a text segment + * then it is readonly. */ + if (addr_of_ptr && (uintptr_t)ptr != (uintptr_t)addr_of_ptr) { + /* The case where there is an actual pointer pointing to some memory + * chunk, otherwise temporal valid holds trivially since the block points + * to itself */ + uint32_t stored_referent = referent_timestamp(addr_of_ptr); + uint32_t actual_referent = origin_timestamp(ptr); + return stored_referent == actual_referent; + } + return 1; +} +/* }}} */ +#else +# define E_ACSL_TEMPORAL_DESC "disabled" +#endif +#endif diff --git a/src/plugins/e-acsl/share/e-acsl/e_acsl_temporal_timestamp.h b/src/plugins/e-acsl/share/e-acsl/e_acsl_temporal_timestamp.h new file mode 100644 index 0000000000000000000000000000000000000000..107f12ea88cbfddb823d56c49c9b304e7ab924a3 --- /dev/null +++ b/src/plugins/e-acsl/share/e-acsl/e_acsl_temporal_timestamp.h @@ -0,0 +1,77 @@ +/**************************************************************************/ +/* */ +/* This file is part of the Frama-C's E-ACSL plug-in. */ +/* */ +/* Copyright (C) 2012-2018 */ +/* CEA (Commissariat à l'énergie atomique et aux énergies */ +/* alternatives) */ +/* */ +/* you can redistribute it and/or modify it under the terms of the GNU */ +/* Lesser General Public License as published by the Free Software */ +/* Foundation, version 2.1. */ +/* */ +/* It is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Lesser General Public License for more details. */ +/* */ +/* See the GNU Lesser General Public License version 2.1 */ +/* for more details (enclosed in the file licenses/LGPLv2.1). */ +/* */ +/**************************************************************************/ + +/*! *********************************************************************** + * \file e_acsl_temporal_timestamp.h + * \brief Generating temporal timestamps +***************************************************************************/ + +#ifndef E_ACSL_TEMPORAL_TIMESTAMP_H /*{{{*/ +#define E_ACSL_TEMPORAL_TIMESTAMP_H + +#include <stdint.h> + +#ifdef E_ACSL_TEMPORAL /*{{{*/ +/*! Temporal time stamp generator variable + * Time stamp is generated by incrementing `temporal_timestamp` variable. + * Value distribution is as follows: + * `0` - invalid time stamp, i.e., a pointer carrying the referent of 0 does + * not point to anything + * `1` - timestamp associated with global variables, i.e., each global variable + * has allocation time stamp of '1' + * `>1` - heap or stack blocks allocated during a program's execution */ +static uint32_t temporal_timestamp = 2; + +#define INVALID_TEMPORAL_TIMESTAMP 0 +#define GLOBAL_TEMPORAL_TIMESTAMP 1 +#define NEW_TEMPORAL_TIMESTAMP() (++temporal_timestamp) + +/*! Maximal number of parameters a function can accept + * [ C99, 5.2.4.1 Translation Limits ] */ +#define MAX_PARAMETERS 127 + +struct temporal_parameter { + void *ptr; + /* Number all members such that there is no `0` which potentially + corresponds to an invalid number */ + enum { + TBlockN = 10, + TReferentN = 20, + TCopy = 30 + } temporal_flow; +}; + +typedef struct temporal_parameter temporal_parameter; + +/*! \brief External array used to transfer parameters from one function + * to another. + * + * WARNING! NOT thread-safe! A better way would probably have it as + * __thread so it is local to every thread. */ +static temporal_parameter parameter_referents[MAX_PARAMETERS]; +static uint32_t return_referent; + +#define reset_parameter_referents() \ + memset(parameter_referents, 0, sizeof(parameter_referents)) + +#endif /*}}} E_ACSL_TEMPORAL */ +#endif /*}}} E_ACSL_TEMPORAL_TIMESTAMP */ diff --git a/src/plugins/e-acsl/share/e-acsl/e_acsl_trace.h b/src/plugins/e-acsl/share/e-acsl/e_acsl_trace.h new file mode 100644 index 0000000000000000000000000000000000000000..4ba3454d2663531e1c1a76947ef13722308d9f48 --- /dev/null +++ b/src/plugins/e-acsl/share/e-acsl/e_acsl_trace.h @@ -0,0 +1,110 @@ +/**************************************************************************/ +/* */ +/* This file is part of the Frama-C's E-ACSL plug-in. */ +/* */ +/* Copyright (C) 2012-2018 */ +/* CEA (Commissariat à l'énergie atomique et aux énergies */ +/* alternatives) */ +/* */ +/* you can redistribute it and/or modify it under the terms of the GNU */ +/* Lesser General Public License as published by the Free Software */ +/* Foundation, version 2.1. */ +/* */ +/* It is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Lesser General Public License for more details. */ +/* */ +/* See the GNU Lesser General Public License version 2.1 */ +/* for more details (enclosed in the file licenses/LGPLv2.1). */ +/* */ +/**************************************************************************/ + +/*! *********************************************************************** + * \file e_acsl_trace.h + * \brief Interface for producing backtrace. Requires GLIBC. +***************************************************************************/ + +#ifndef E_ACSL_TRACE_H +#define E_ACSL_TRACE_H + +#include <stddef.h> +#include <limits.h> +#include "e_acsl_printf.h" +#include "e_acsl_shexec.h" + +extern void *__libc_stack_end; + +struct frame_layout { + void *next; + void *return_address; +}; + +/* The following implementation of malloc-free backtrace [native_backtrace] + is mostly taken from Glibc-2.22 (see file debug/backtrace.c) */ +static int native_backtrace (void **array, int size) { + struct frame_layout *current; + void *top_frame, + *top_stack; + int cnt = 0; + + top_frame = __builtin_frame_address(0); + /* Some notion of current stack. Need not be exactly the top of the stack, + just something somewhere in the current frame. */ + top_stack = ({ char __csf; &__csf; }); + + /* We skip the call to this function, it makes no sense to record it. */ + current = ((struct frame_layout *) top_frame); + while (cnt < size) { + /* Assume that the stack grows downwards */ + if ((void *) current < top_stack || !((void *) current < __libc_stack_end)) + /* This means the address is out of range. Note that for the + toplevel we see a frame pointer with value NULL which clearly is + out of range. */ + break; + array[cnt++] = current->return_address; + current = ((struct frame_layout *) (current->next)); + } + return cnt; +} + +static void trace() { +# ifdef __linux__ + + int size = 24; + void **bb = private_malloc(sizeof(void*)*size); + native_backtrace(bb, size); + + char executable [PATH_MAX]; + rtl_sprintf(executable, "/proc/%d/exe", getpid()); + + STDOUT("/** Backtrace **************************/\n"); + int counter = 0; + while (*bb) { + char *addr = (char*)private_malloc(21); + rtl_sprintf(addr,"%p", *bb); + char *ar[] = { "addr2line", "-f", "-p", "-C", "-s", "-e", + executable, addr, NULL}; + ipr_t *ipr = shexec(ar, NULL); + char *prefix = (counter) ? " - " : ""; + if (ipr) { + char *outs = (char*)ipr->stdouts; + if (outs) { + outs[strlen(outs)-1] = '\0'; + if (strlen(outs) && endswith(outs, "??:0") && endswith(outs, "??:?")) { + STDOUT("%s%s\n", prefix, outs); + } + } else { + char *errs = (char*)ipr->stderrs; + if (errs) { + STDOUT("%s\n", errs); + } + } + } + bb++; + counter++; + } + STDOUT("/***************************************/\n"); +# endif /* __linux__ */ +} +#endif diff --git a/src/plugins/e-acsl/share/e-acsl/segment_model/e_acsl_segment_mmodel.c b/src/plugins/e-acsl/share/e-acsl/segment_model/e_acsl_segment_mmodel.c new file mode 100644 index 0000000000000000000000000000000000000000..251d7dd9ce265cc87e0a30a87227c6e3e5d11f85 --- /dev/null +++ b/src/plugins/e-acsl/share/e-acsl/segment_model/e_acsl_segment_mmodel.c @@ -0,0 +1,287 @@ +/**************************************************************************/ +/* */ +/* This file is part of the Frama-C's E-ACSL plug-in. */ +/* */ +/* Copyright (C) 2012-2018 */ +/* CEA (Commissariat à l'énergie atomique et aux énergies */ +/* alternatives) */ +/* */ +/* you can redistribute it and/or modify it under the terms of the GNU */ +/* Lesser General Public License as published by the Free Software */ +/* Foundation, version 2.1. */ +/* */ +/* It is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Lesser General Public License for more details. */ +/* */ +/* See the GNU Lesser General Public License version 2.1 */ +/* for more details (enclosed in the file licenses/LGPLv2.1). */ +/* */ +/**************************************************************************/ + +/*! *********************************************************************** + * \file e_acsl_segment_mmodel.c + * \brief Implementation of E-ACSL public API for a segment (shadow) memory + * model. See e_acsl.h for details. +***************************************************************************/ + +#include <sys/time.h> +#include <sys/resource.h> +#include "e_acsl_shadow_layout.h" +#include "e_acsl_segment_tracking.h" + +#define E_ACSL_MMODEL_DESC "shadow memory" + +void * store_block(void *ptr, size_t size) { + /* Only stack-global memory blocks are recorded explicitly via this function. + Heap blocks should be tracked internally using memory allocation functions + such as malloc or calloc. */ + shadow_alloca(ptr, size); + return ptr; +} + +void delete_block(void *ptr) { + /* Block deletion should be performed on stack/global addresses only, + * heap blocks should be deallocated manually via free/cfree/realloc. */ + shadow_freea(ptr); +} + +void * store_block_duplicate(void *ptr, size_t size) { + if (allocated((uintptr_t)ptr, size, (uintptr_t)ptr)) + delete_block(ptr); + shadow_alloca(ptr, size); + return ptr; +} + +/*! \brief Initialize a chunk of memory given by its start address (`addr`) + * and byte length (`n`). */ +void initialize(void *ptr, size_t n) { + TRY_SEGMENT( + (uintptr_t)ptr, + initialize_heap_region((uintptr_t)ptr, n), + initialize_static_region((uintptr_t)ptr, n) + ) +} + +void full_init(void *ptr) { + initialize(ptr, _block_length(ptr)); +} + +void mark_readonly(void *ptr) { + mark_readonly_region((uintptr_t)ptr, _block_length(ptr)); +} + +/* ********************** */ +/* E-ACSL annotations {{{ */ +/* ********************** */ + +int valid(void *ptr, size_t size, void *ptr_base, void *addrof_base) { + return + allocated((uintptr_t)ptr, size, (uintptr_t)ptr_base) + && !readonly(ptr) +#ifdef E_ACSL_TEMPORAL + && temporal_valid(ptr_base, addrof_base) +#endif + ; +} + +int valid_read(void *ptr, size_t size, void *ptr_base, void *addrof_base) { + return allocated((uintptr_t)ptr, size, (uintptr_t)ptr_base) +#ifdef E_ACSL_TEMPORAL + && temporal_valid(ptr_base, addrof_base) +#endif + ; +} + +/*! NB: The implementation for this function can also be specified via + \p _base_addr macro that will eventually call ::TRY_SEGMENT. The following + implementation is preferred for performance reasons. */ +void * base_addr(void *ptr) { + TRY_SEGMENT(ptr, + return (void*)heap_info((uintptr_t)ptr, 'B'), + return (void*)static_info((uintptr_t)ptr, 'B')); + return NULL; +} + +/*! NB: Implementation of the following function can also be specified + via \p _block_length macro. A more direct approach via ::TRY_SEGMENT + is preferred for performance reasons. */ +size_t block_length(void *ptr) { + TRY_SEGMENT(ptr, + return heap_info((uintptr_t)ptr, 'L'), + return static_info((uintptr_t)ptr, 'L')) + return 0; +} + +size_t offset(void *ptr) { + TRY_SEGMENT(ptr, + return heap_info((uintptr_t)ptr, 'O'), + return static_info((uintptr_t)ptr, 'O')); + return 0; +} + +int initialized(void *ptr, size_t size) { + uintptr_t addr = (uintptr_t)ptr; + TRY_SEGMENT_WEAK(addr, + return heap_initialized(addr, size), + return static_initialized(addr, size)); + return 0; +} +/* }}} */ + +/* Track program arguments (ARGC/ARGV) {{{ */ + +/* POSIX-compliant array of character pointers to the environment strings. */ +extern char ** environ; + +static void argv_alloca(int *argc_ref, char *** argv_ref) { + /* Track a top-level containers */ + shadow_alloca((void*)argc_ref, sizeof(int)); + shadow_alloca((void*)argv_ref, sizeof(char**)); + int argc = *argc_ref; + char** argv = *argv_ref; + /* Track argv */ + size_t argvlen = (argc + 1)*sizeof(char*); + shadow_alloca(argv, argvlen); + initialize_static_region((uintptr_t)argv, (argc + 1)*sizeof(char*)); + + /* Track argument strings */ + while (*argv) { + /* Account for `\0` when copying C strings */ + size_t arglen = strlen(*argv) + 1; +#ifdef E_ACSL_TEMPORAL + /* Move `argv` strings to heap. This is because they are allocated + sparcely and there is no way to align they (if they are small), so there + may no be sufficient space for storing origin time stamps. + Generally speaking, this is not the best of ideas, more of a temporary + fix to avoid various range comparisons. A different approach is + therefore more than welcome. */ + *argv = shadow_copy(*argv, arglen, 1); + /* TODO: These heap allocations are never freed in fact. Not super + important, but for completeness purposes it may be feasible to define + a buffer of implicitly allocated memory locations which need to be + freed before a program exists. */ +#else + shadow_alloca(*argv, arglen); + initialize_static_region((uintptr_t)*argv, arglen); +#endif + argv++; + } +#ifdef E_ACSL_TEMPORAL + /* Fill temporal shadow */ + int i; + argv = *argv_ref; + temporal_store_nblock(argv_ref, *argv_ref); + for (i = 0; i < argc; i++) + temporal_store_nblock(argv + i, *(argv+i)); +#endif + + while (*environ) { + size_t envlen = strlen(*environ) + 1; +#ifdef E_ACSL_TEMPORAL + *environ = shadow_copy(*environ, envlen, 1); +#else + shadow_alloca(*environ, envlen); + initialize_static_region((uintptr_t)*environ, envlen); +#endif + environ++; + } +} +/* }}} */ + +/* Program initialization {{{ */ +extern int main(void); + +void mspaces_init() { + /* [already_run] avoids reentrancy issue (see Gitlab issue #83), + e.g. in presence of a GCC's constructors that invokes malloc possibly + several times before calling main. */ + static char already_run = 0; + if (! already_run) { + describe_run(); + make_memory_spaces(64*MB, get_heap_size()); + /* Allocate and log shadow memory layout of the execution. + Case of the heap, globals and tls. */ + init_shadow_layout_heap_global_tls(); + already_run = 1; + } +} + +void memory_init(int *argc_ref, char *** argv_ref, size_t ptr_size) { + /* [already_run] avoids reentrancy issue (see Gitlab issue #83), + e.g. in presence of a recursive call to 'main' */ + static char already_run = 0; + if (! already_run) { + mspaces_init(); + /* Verify that the given size of a pointer matches the one in the present + architecture. This is a guard against Frama-C instrumentations using + architectures different to the given one. */ + arch_assert(ptr_size); + /* Initialize report file with debug logs (only in debug mode). */ + initialize_report_file(argc_ref, argv_ref); + /* Lift stack limit to account for extra stack memory overhead. */ + increase_stack_limit(get_stack_size()*2); + /* Allocate and log shadow memory layout of the execution. Case of stack. */ + init_shadow_layout_stack(argc_ref, argv_ref); + //DEBUG_PRINT_LAYOUT; + /* Make sure the layout holds */ + DVALIDATE_SHADOW_LAYOUT; + /* Track program arguments. */ + if (argc_ref && argv_ref) + argv_alloca(argc_ref, argv_ref); + /* Track main function */ + shadow_alloca(&main, sizeof(&main)); + initialize_static_region((uintptr_t)&main, sizeof(&main)); + /* Tracking safe locations */ + collect_safe_locations(); + int i; + for (i = 0; i < safe_location_counter; i++) { + void *addr = (void*)safe_locations[i].address; + uintptr_t len = safe_locations[i].length; + shadow_alloca(addr, len); + if (safe_locations[i].is_initialized) + initialize(addr, len); + } + init_infinity_values(); + already_run = 1; + } +} + +void memory_clean(void) { + clean_shadow_layout(); + report_heap_leaks(); +} +/* }}} */ + +/* Local operations on temporal timestamps {{{ */ +/* Remaining functionality (shared between all models) is located in e_acsl_temporal.h */ +#ifdef E_ACSL_TEMPORAL +static uintptr_t temporal_referent_shadow(void *addr) { + TRY_SEGMENT(addr, + return TEMPORAL_HEAP_SHADOW(addr), + return TEMPORAL_SECONDARY_STATIC_SHADOW(addr)); + return 0; +} + +static uint32_t origin_timestamp(void *ptr) { + TRY_SEGMENT_WEAK(ptr, + return heap_origin_timestamp((uintptr_t)ptr), + return static_origin_timestamp((uintptr_t)ptr)); + return INVALID_TEMPORAL_TIMESTAMP; +} + +static uint32_t referent_timestamp(void *ptr) { + TRY_SEGMENT(ptr, + return heap_referent_timestamp((uintptr_t)ptr), + return static_referent_timestamp((uintptr_t)ptr)); + return INVALID_TEMPORAL_TIMESTAMP; +} + +static void store_temporal_referent(void *ptr, uint32_t ref) { + TRY_SEGMENT(ptr, + heap_store_temporal_referent((uintptr_t)ptr, ref), + static_store_temporal_referent((uintptr_t)ptr,ref)); +} +#endif +/* }}} */ diff --git a/src/plugins/e-acsl/share/e-acsl/segment_model/e_acsl_segment_tracking.h b/src/plugins/e-acsl/share/e-acsl/segment_model/e_acsl_segment_tracking.h new file mode 100644 index 0000000000000000000000000000000000000000..0db0885ed6544725cb88230836030c1bc30f8ed6 --- /dev/null +++ b/src/plugins/e-acsl/share/e-acsl/segment_model/e_acsl_segment_tracking.h @@ -0,0 +1,1504 @@ +/**************************************************************************/ +/* */ +/* This file is part of the Frama-C's E-ACSL plug-in. */ +/* */ +/* Copyright (C) 2012-2018 */ +/* CEA (Commissariat à l'énergie atomique et aux énergies */ +/* alternatives) */ +/* */ +/* you can redistribute it and/or modify it under the terms of the GNU */ +/* Lesser General Public License as published by the Free Software */ +/* Foundation, version 2.1. */ +/* */ +/* It is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Lesser General Public License for more details. */ +/* */ +/* See the GNU Lesser General Public License version 2.1 */ +/* for more details (enclosed in the file licenses/LGPLv2.1). */ +/* */ +/**************************************************************************/ + +/*! *********************************************************************** + * \file e_acsl_segment_tracking.h + * \brief Core functionality of the segment-based memory model +***************************************************************************/ + +/* Segment settings and shadow values interpretation {{{ */ + +/* This file implements segment-based and offset-based shadow memory models + * (shadow encodings) (see draft of the PLDI'17 paper). + * + * IMPORTANT: While the implementation of the offset-based encoding mostly + * follows the description given by the paper, there are differences in the + * segment-based encoding for tracking heap memory. Some of these differences + * are as follows: + * 1) Size of a heap segment is increased to 32 bytes + * 2) Heap meta-segments are no longer used, segment-based representation of + * a heap block considers only block segments, such that: + * - Lowest `intptr_t` bytes of each shadow segment tracking an application + * block store the base address of that block; + * - `intptr_t` bytes of the first segment following the initial `intptr_t` + * bytes store the length of the block. Note, the length is only stored + * by the first segment. + * 3) Per-byte initialization of application bytes is tracked via a disjoint + * shadow region, which maps one bit of shadow memory to a byte of + * application memory. Comments within this file often refer to a shadow + * region tracking application blocks by segments as to `block shadow`, + * and to the region tracking initialization as to `init shadow`. +*/ + +/*! @brief Byte size of a heap segment. + * This size is potentially used as an argument to `memalign`. + * It SHOULD be a multiple of 2 and a multiple of a pointer size. + * + * \b FIXME: in the current implementation there might be issues with segment + * size greater than 64 bytes. This is because presently some initialization + * functionality relies on the fact that initialization per segment can be set + * and/or evaluated using an 8-byte bitmask. */ +#define HEAP_SEGMENT 32 + +/*! \brief Size (in bytes) of a long block on the stack. */ +#define LONG_BLOCK 8 + +/*! \brief Bit offset in a primary shadow byte that represents initialization. */ +#define INIT_BIT 0 + +/*! \brief Bit offset in a primary shadow byte that represents read-only or + * read-write access. + * + * This is such that the value of 1 is read-only, and 0 is read/write */ +#define READONLY_BIT 1 + +/*! \brief Evaluate to a non-zero value if the size of a memory + * block indicates that it is a long one */ +#define IS_LONG_BLOCK(_size) (_size > LONG_BLOCK) + +/*! \brief Offset within a long block that identifies the portion of the block + * that does not have a corresponding shadow and reuse the shadow of a previous + * segment. + * E.g., given a long block of 11 bytes the boundary is 8. Then, bytes [0,7] of + * the block are shadowed (storing block offset and size) and bytes 8-10 are + * not. This is because 3 bytes are not sufficient to store size and offset. + * These remaining bytes reuse the shadow of [0,7]. */ +#define LONG_BLOCK_BOUNDARY(_size) (_size - _size%LONG_BLOCK) + +/*! \brief Primary shadow of a long block consists of a 8-byte segment + a + * remainder. For instance, a 18-byte block is represented by two 8-byte + * segments + 2 bytes. Each byte of a segment stores an offset in the secondary + * shadow. The offsets for each such segment can be expressed using the + * following number obtained by compressing all eight bytes with offsets set + * into a single block. */ +#define LONG_BLOCK_MASK 15913703276567643328UL + +/*! \brief 6 higher bytes of a memory cell on stack that belongs to a long + * memory block store offsets relative to meta-data in the secondary shadow. The + * offsets start with the below number. E.g., if the bits store 51, then the + * offset at which to read meta-data is (51 - 48). */ +#define LONG_BLOCK_INDEX_START 48 + +/*! \brief Decrease _n to be a multiple of _m */ +#define ALIGN_LEFT(_n, _m) (_n - _n%_m) + +/*! \brief Increase _n to be a multiple of _m */ +#define ALIGN_RIGHT(_n, _m) (_n + ((_n%_m) ? (_m - _n%_m) : 0)) + +/*! \brief Heap shadow address aligned at a segment boundary */ +#define ALIGNED_HEAP_SHADOW(_addr) \ + HEAP_SHADOW(ALIGN_LEFT(_addr,HEAP_SEGMENT)) + +/* \brief Maximal size_t value that does not cause overflow via addition + * when segment size is added. */ +static const size_t max_allocated = ALIGN_LEFT(SIZE_MAX,HEAP_SEGMENT); + +/* \brief Return actual allocation size which takes into account aligned + * allocation. In the present implementation it is the requested size of + * a heap block aligned at a segment boundary */ +#define ALLOC_SIZE(_s) \ + (_s < max_allocated ? ALIGN_RIGHT(_s, HEAP_SEGMENT) : 0) + +/** \brief Evaluate to `true` if address _addr belongs to a memory block + * with base address _base and length _length */ +#define BELONGS(_addr, _base, _length) \ + (_addr >= _base && _addr < _base + _length) + +/*! \brief For short blocks numbers 1 to 36 represent lengths and offsets, + * such that: + * - 0 -> length 0, offset 0 + * - 1 -> length 1, offset 0, + * - 2 -> length 2, offset 0, + * - 3 -> length 2, offset 1 and so on. + * + * The below data is used to identify lengths and offsets: + * Given x is a number from [1, 36] range: + * - short_lengths[x] -> length of a block + * - short_offsets[x] -> offset within a block */ +static const char short_lengths[] = { + 0, + 1, + 2,2, + 3,3,3, + 4,4,4,4, + 5,5,5,5,5, + 6,6,6,6,6,6, + 7,7,7,7,7,7,7, + 8,8,8,8,8,8,8,8 +}; + +static const char short_offsets[] = { + 0, + 0, + 0,1, + 0,1,2, + 0,1,2,3, + 0,1,2,3,4, + 0,1,2,3,4,5, + 0,1,2,3,4,5,6, + 0,1,2,3,4,5,6,7 +}; + +/*! \brief Mask for marking a heap segment as initialized. + * For instance, let `uintptr_t *p' point to the start of a heap segment + * in the heap shadow, then 'p[1] | heap_init_mask` sets initialization bits. + * NOTE: This approach cannot deal with segments larger than 64 bits. */ +static const uint64_t heap_init_mask = ~(ONE << HEAP_SEGMENT); + +/*! \brief Masks for checking of initialization of global/stack allocated blocks. + * A byte allocated globally or on stack is deemed initialized if its + * least significant bit is set to `1' and uninitialized otherwise. + * The binary representation is then as follows (assuming the leftmost + * bit is the least significant one): + * + * 00000000 00000000 00000000 00000000 ... (0) + * 10000000 00000000 00000000 00000000 ... (1) + * 10000000 10000000 00000000 00000000 ... (257) + * 10000000 10000000 10000000 00000000 ... (65793) + * 10000000 10000000 10000000 10000000 ... (16843009) + * ... + * + * For instance, mark first X bytes of a number N as initialised: + * N |= static_init_masks[X] */ +static const uint64_t static_init_masks [] = { + 0, /* 0 bytes */ + 1, /* 1 byte */ + 257, /* 2 bytes */ + 65793, /* 3 bytes */ + 16843009, /* 4 bytes */ + 4311810305, /* 5 bytes */ + 1103823438081, /* 6 bytes */ + 282578800148737, /* 7 bytes */ + 72340172838076673 /* 8 bytes */ +}; + +/*! \brief Bit masks for setting read-only (second least significant) bits. + * Binary representation (assuming the least significant bit is the + * leftmost bit) is follows: + * + * 00000000 00000000 00000000 00000000 ... (0) + * 01000000 00000000 00000000 00000000 ... (2) + * 01000000 01000000 00000000 00000000 ... (514) + * 01000000 01000000 01000000 00000000 ... (131586) + * 01000000 01000000 01000000 01000000 ... (33686018) + * ... + * + * For instance, mark first X bytes of a number N as read-only: + * N |= static_readonly_masks[X] */ +static const uint64_t static_readonly_masks [] = { + 0, /* 0 bytes */ + 2, /* 1 byte */ + 514, /* 2 bytes */ + 131586, /* 3 bytes */ + 33686018, /* 4 bytes */ + 8623620610, /* 5 bytes */ + 2207646876162, /* 6 bytes */ + 565157600297474, /* 7 bytes */ + 144680345676153346 /* 8 bytes */ +}; +/* }}} */ + +/* Runtime assertions (debug mode) {{{ */ +#ifdef E_ACSL_DEBUG +#define DVALIDATE_ALIGNMENT(_addr) \ + DVASSERT(((uintptr_t)_addr) % HEAP_SEGMENT == 0, \ + "Heap base address %a is unaligned", _addr) + +#define DVALIDATE_MEMORY_INIT \ + DVASSERT(mem_layout.is_initialized != 0, "Un-initialized shadow layout", NULL) + +/* Debug function making sure that the order of program segments is as expected + * and that the program and the shadow segments used do not overlap. */ +static void validate_shadow_layout() { + /* Check that the struct holding memory layout is marked as initialized. */ + DVALIDATE_MEMORY_INIT; + + /* Each segment has 3 partitions: + - application memory + - primary/secondary shadows */ + int num_partitions = sizeof(mem_partitions)/sizeof(memory_partition*); + int num_seg_in_part = 3; +#ifdef E_ACSL_TEMPORAL + num_seg_in_part = 5; +#endif + int num_segments = num_partitions*num_seg_in_part; + uintptr_t segments[num_segments][2]; + + size_t i; + for (i = 0; i < num_partitions; i++) { + memory_partition *p = mem_partitions[i]; + segments[num_seg_in_part*i][0] = p->application.start; + segments[num_seg_in_part*i][1] = p->application.end; + segments[num_seg_in_part*i+1][0] = p->primary.start; + segments[num_seg_in_part*i+1][1] = p->primary.end; + segments[num_seg_in_part*i+2][0] = p->secondary.start; + segments[num_seg_in_part*i+2][1] = p->secondary.end; +#ifdef E_ACSL_TEMPORAL + segments[num_seg_in_part*i+3][0] = p->temporal_primary.start; + segments[num_seg_in_part*i+3][1] = p->temporal_primary.end; + segments[num_seg_in_part*i+4][0] = p->temporal_secondary.start; + segments[num_seg_in_part*i+4][1] = p->temporal_secondary.end; +#endif + } + + /* Make sure all segments (shadow or otherwise) are disjoint */ + size_t j; + for (int i = 0; i < num_segments; i++) { + uintptr_t *src = segments[i]; + DVASSERT(src[0] < src[1], + "Segment start is greater than segment end %lu < %lu\n", src[0], src[1]); + for (j = 0; j < num_segments; j++) { + if (i != j) { + uintptr_t *dest = segments[j]; + DVASSERT(src[1] < dest[0] || src[0] > dest[1], + "Segment [%lu, %lu] overlaps with segment [%lu, %lu]", + src[0], src[1], dest[0], dest[1]); + } + } + } +} + +/* Assert that memory layout has been initialized and all segments appear + * in the expected order */ +# define DVALIDATE_SHADOW_LAYOUT validate_shadow_layout() + +/* Assert that boundaries of a block [_addr, _addr+_size] are within a segment + * given by `_s`. `_s` is either HEAP, STACK, TLS, GLOBAL or STATIC. */ +#define DVALIDATE_IS_ON(_addr, _size, _s) \ + DVASSERT(IS_ON_##_s(_addr), "Address %a not on %s", _addr, #_s); \ + DVASSERT(IS_ON_##_s(_addr+_size), "Address %a not on %s", _addr+_size, #_s) + +/* Assert that [_addr, _addr+_size] are within heap segment */ +#define DVALIDATE_IS_ON_HEAP(_addr, _size) \ + DVALIDATE_IS_ON(_addr, _size, HEAP) +/* Assert that [_addr, _addr+_size] are within stack segment */ +#define DVALIDATE_IS_ON_STACK(_addr, _size) \ + DVALIDATE_IS_ON(_addr, _size, STACK) +/* Assert that [_addr, _addr+_size] are within global segment */ +#define DVALIDATE_IS_ON_GLOBAL(_addr, _size) \ + DVALIDATE_IS_ON(_addr, _size, GLOBAL) +/* Assert that [_addr, _addr+_size] are within TLS segment */ +#define DVALIDATE_IS_ON_TLS(_addr, _size) \ + DVALIDATE_IS_ON(_addr, _size, TLS) +/* Assert that [_addr, _addr+_size] are within stack, global or TLS segments */ +#define DVALIDATE_IS_ON_STATIC(_addr, _size) \ + DVALIDATE_IS_ON(_addr, _size, STATIC) + +/* Assert that `_addr` is on heap and it is the base address of an allocated + * heap memory block */ +#define DVALIDATE_FREEABLE(_addr) \ + DVASSERT(IS_ON_HEAP(_addr), "Expected heap location: %a\n", _addr); \ + DVASSERT(_addr == _base_addr(_addr), \ + "Expected base address, i.e., %a, not %a\n", _base_addr(_addr), _addr); + +/* Assert that a memory block [_addr, _addr + _size] is allocated on a + * program's heap */ +# define DVALIDATE_HEAP_ACCESS(_addr, _size) \ + DVASSERT(IS_ON_HEAP(_addr), "Expected heap location: %a\n", _addr); \ + DVASSERT(heap_allocated((uintptr_t)_addr, _size, (uintptr_t)_addr), \ + "Operation on unallocated heap block [%a + %lu]\n", _addr, _size) + +/* Assert that every location belonging to the range [_addr, _addr + _size] is + * - belongs to a tracked static region (i.e., stack, TLS or global) + * - not allocated */ +# define DVALIDATE_HEAP_FREE(_addr, _size) { \ + uintptr_t i, a = (uintptr_t)_addr; \ + for (i = 0; i < _size; i++) { \ + DVASSERT(IS_ON_HEAP(a + i), "Expected heap location: %a\n", a + i); \ + DVASSERT(!heap_allocated(a + i, 1, a + i), \ + "Expected heap unallocated location: [%a + %lu]\n", a, i); \ + } \ +} + +/* Assert that memory block [_addr, _addr + _size] is allocated on stack, TLS + * or globally */ +# define DVALIDATE_STATIC_ACCESS(_addr, _size) \ + DVASSERT(IS_ON_STATIC(_addr), \ + "Expected static location: [%a + %lu], \n", _addr, _size); \ + DVASSERT(static_allocated((uintptr_t)_addr, _size,(uintptr_t)_addr), \ + "Operation on unallocated static block [%a + %lu]\n", _addr, _size) + +/* Same as ::DVALIDATE_STATIC_LOCATION but for a single memory location */ +# define DVALIDATE_STATIC_LOCATION(_addr) \ + DVASSERT(IS_ON_STATIC(_addr), \ + "Expected static location: %a\n", _addr); \ + DVASSERT(static_allocated_one((uintptr_t)_addr), \ + "Operation on unallocated static block [%a]\n", _addr) + +/* Assert that every location belonging to the range [_addr, _addr + _size] is + * - belongs to a tracked static region (i.e., stack, TLS or global) + * - not allocated */ +# define DVALIDATE_STATIC_FREE(_addr, _size) { \ + uintptr_t i, a = (uintptr_t)_addr; \ + for (i = 0; i < _size; i++) { \ + DVASSERT(IS_ON_STATIC(a + i), \ + "Expected static location in freea: %a\n", a + i); \ + DVASSERT(!static_allocated_one(a + i), \ + "Expected static unallocated location in freea: [%a + %lu]\n", a, i); \ + } \ +} + +/* Assert that neither of `_len - 1` addresses immediately preceding `_addr` + * are base addresses of some other block and that `_len` addresses past + * `_addr` are free */ +#define DVALIDATE_STATIC_SUFFICIENTLY_ALIGNED(_addr, _len) { \ + int _i; \ + for (_i = 0; _i < _len; _i++) { \ + uintptr_t _prev = _addr - _i; \ + if (static_allocated_one(_prev)) { \ + vassert(_base_addr(_prev) != _prev, \ + "Potential backward overlap of: \n previous block [%a]\n" \ + " with allocated block [%a]\n", _prev, _addr); \ + } \ + uintptr_t _next = _addr + _i; \ + vassert(!static_allocated_one(_next), \ + "Potential forward overlap of:\n following block location [%a]\n" \ + " with allocated block [%a]\n", _next, _addr); \ + } \ +} + +/* Assert that a memory block [_addr, _addr + _size] is nullified */ +# define DVALIDATE_NULLIFIED(_addr, _size) \ + DVASSERT(zeroed_out((void *)_addr, _size), \ + "Block [%a, %a+%lu] not nullified", _addr, _addr, _size) + +/* Assert that memory block [_addr, _addr + _size] is allocated */ +# define DVALIDATE_ALLOCATED(_addr, _size, _base) \ + vassert(allocated((uintptr_t)_addr, _size, (uintptr_t)_base), \ + "Operation on unallocated block [%a + %lu] with base %a\n", \ + _addr, _size, _base); + +/* Assert that memory block [_addr, _addr + _size] is allocated + * and can be written to */ +# define DVALIDATE_WRITEABLE(_addr, _size, _base) \ + vassert(writeable((uintptr_t)_addr, _size, (uintptr_t)_base), \ + "Operation on unallocated block [%a + %lu] with base %a\n", \ + _addr, _size, _base); +#else +/*! \cond exclude from doxygen */ +# define DVALIDATE_MEMORY_INIT +# define DVALIDATE_SHADOW_LAYOUT +# define DVALIDATE_HEAP_ACCESS +# define DVALIDATE_STATIC_ACCESS +# define DVALIDATE_STATIC_LOCATION +# define DVALIDATE_ALIGNMENT +# define DVALIDATE_NULLIFIED +# define DVALIDATE_IS_ON +# define DVALIDATE_IS_ON_HEAP +# define DVALIDATE_IS_ON_STACK +# define DVALIDATE_IS_ON_GLOBAL +# define DVALIDATE_IS_ON_TLS +# define DVALIDATE_IS_ON_STATIC +# define DVALIDATE_FREEABLE +# define DVALIDATE_STATIC_FREE +# define DVALIDATE_HEAP_FREE +# define DVALIDATE_ALLOCATED +# define DVALIDATE_WRITEABLE +# define DVALIDATE_STATIC_SUFFICIENTLY_ALIGNED +/*! \endcond */ +#endif +/* }}} */ + +/* E-ACSL predicates {{{ */ +/* See definitions for documentation */ +static void *shadow_copy(const void *ptr, size_t size, int init); +static uintptr_t heap_info(uintptr_t addr, char type); +static uintptr_t static_info(uintptr_t addr, char type); +static int heap_allocated(uintptr_t addr, size_t size, uintptr_t base_ptr); +static int static_allocated(uintptr_t addr, long size, uintptr_t base_ptr); +static int allocated(uintptr_t addr, long size, uintptr_t base_ptr); +static int writeable(uintptr_t addr, long size, uintptr_t base_ptr); +static int readonly (void *ptr); + +/*! \brief Quick test to check if a static location belongs to allocation. + * This macro really belongs where static_allocated is defined, but + * since it is used across this whole file it needs to be defined here. */ +#define static_allocated_one(_addr) \ + (*((unsigned char*)PRIMARY_SHADOW(_addr))) + +/*! \brief Shortcut for executing statements based on the segment a given + * address belongs to. + * \param intptr_t _addr - a memory address + * \param code_block _heap_stmt - code executed if `_addr` is a heap address + * \param code_block _static_stmt - code executed if `_addr` is a static address */ +#define TRY_SEGMENT_WEAK(_addr, _heap_stmt, _static_stmt) \ + if (IS_ON_HEAP(_addr)) { \ + _heap_stmt; \ + } else if (IS_ON_STATIC(_addr)) { \ + _static_stmt; \ + } + +/*! \brief Same as TRY_SEGMENT but performs additional checks aborting the + * execution if the given address is `NULL` or does not belong to known + * segments. Note that `NULL` also does not belong to any of the tracked + * segments but it is treated separately for debugging purposes. + * + * The \b WEAK notion refers to the behaviour where no action is performed if + * the given address does not belong to any of the known segments. */ +#define TRY_SEGMENT(_addr, _heap_stmt, _static_stmt) { \ + TRY_SEGMENT_WEAK(_addr, _heap_stmt, _static_stmt) \ + else { \ + vassert(0, "Use of invalid address %a in %s\n", _addr, __func__); \ + } \ +} + +/*! \brief Wrapper around ::heap_info and ::static_info functions that + * dispatches one of the above functions based on the type of supplied memory + * address (`addr`) (static, global, tls or heap). For the case when the + * supplied address does not belong to the track segments 0 is returned. + * + * \param uintptr_t addr - a memory address + * \param char p - predicate type. See ::static_info for further details. */ +static uintptr_t predicate(uintptr_t addr, char p) { + TRY_SEGMENT( + addr, + return heap_info((uintptr_t)addr, p), + return static_info((uintptr_t)addr, p)); + return 0; +} + +/*! \brief Return the byte length of the memory block containing `_addr` */ +#define _block_length(_addr) predicate((uintptr_t)_addr, 'L') +/*! \brief Return the base address of the memory block containing `_addr` */ +#define _base_addr(_addr) predicate((uintptr_t)_addr, 'B') +/* }}} */ + +/* Static allocation {{{ */ + +/** The below numbers identify offset "bases" for short block lengths. + * An offset base is a number (a code) that represents the length of a + * short block with a byte offset of `0`. + * For instance, for a block of 4 bytes its offset base if 7, that is + * length 4, offset 0 => 7, + * length 4, offset 1 => 8, + * length 4, offset 2 => 9, + * length 4, offset 3 => 10, + * and then for a block of 5 bytes its base offset if 11 etc. */ +static const char short_offsets_base [] = { 0, 1, 2, 4, 7, 11, 16, 22, 29 }; + +/** Shadow masks for setting values of short blocks */ +static const uint64_t short_shadow_masks[] = { + 0UL, + 4UL, + 3080UL, + 1578000UL, + 673456156UL, + 258640982060UL, + 92703853921344UL, + 31644393008028760UL, + 10415850140873816180UL +}; + +/*! \brief Record allocation of a given memory block and update shadows + * using offset-based encoding. + * + * \param ptr - pointer to a base memory address of the stack memory block. + * \param size - size of the stack memory block. */ +static void shadow_alloca(void *ptr, size_t size) { + DVALIDATE_IS_ON_STATIC(ptr, size); +#ifdef E_ACSL_TEMPORAL + /* Make sure that during temporal analysis there is + * sufficient space to store an origin timestamp. + * NOTE: This does not apply to globals, because all the globals + * have the timestamp of `1`. */ + if (!IS_ON_GLOBAL(ptr)) { + DVALIDATE_STATIC_SUFFICIENTLY_ALIGNED((uintptr_t)ptr, 4); + } +#endif + + unsigned char *prim_shadow = (unsigned char*)PRIMARY_SHADOW(ptr); + uint64_t *prim_shadow_alt = (uint64_t *)PRIMARY_SHADOW(ptr); + unsigned int *sec_shadow = (unsigned int*)SECONDARY_SHADOW(ptr); + + /* Make sure shadows are nullified */ + DVALIDATE_NULLIFIED(prim_shadow, size); + DVALIDATE_NULLIFIED(sec_shadow, size); + + /* Flip read-only bit for zero-size blocks. That is, physically it exists + * but one cannot write to it. Further, the flipped read-only bit will also + * identify such block as allocated */ + if (!size) + setbit(READONLY_BIT, prim_shadow[0]); + + unsigned int i, j = 0, k = 0; + if (IS_LONG_BLOCK(size)) { /* Long blocks */ + unsigned int i, j = 0, k = 0; + int boundary = LONG_BLOCK_BOUNDARY(size); + for (i = 0; i < boundary; i += LONG_BLOCK) { + /* Set-up a secondary shadow segment */ + sec_shadow[j++] = size; + sec_shadow[j++] = i; + /* Set primary shadow offsets */ + prim_shadow_alt[k++] = LONG_BLOCK_MASK; + } + + /* Write out the remainder */ + for (i = boundary; i < size; i++) { + unsigned char offset = i%LONG_BLOCK + LONG_BLOCK_INDEX_START + LONG_BLOCK; + prim_shadow[i] = (offset << 2); + } + } else { /* Short blocks */ + for (i = 0; i < size; i++) { + unsigned char code = short_offsets_base[size] + i; + prim_shadow[i] = (code << 2); + } + } +#ifdef E_ACSL_TEMPORAL /*{{{*/ + /* Store a temporal origin timestamp in the first 4 bytes of a temporal + * shadow. This, however applies only to TLS of stack blocks. Global blocks + * are never deallocated, an origin time stamp of any global block is given + * via `GLOBAL_TEMPORAL_TIMESTAMP` */ + if (!IS_ON_GLOBAL(ptr)) { + uint32_t* temporal_shadow = (uint32_t*)TEMPORAL_PRIMARY_STATIC_SHADOW(ptr); + *temporal_shadow = NEW_TEMPORAL_TIMESTAMP(); + } +#endif /*}}} E_ACSL_TEMPORAL*/ +} +/* }}} */ + +/* Deletion of static blocks {{{ */ + +/*! \brief Nullifies shadow regions of a memory block given by its address. + * \param ptr - base memory address of the stack memory block. */ +void shadow_freea(void *ptr) { + DVALIDATE_STATIC_LOCATION(ptr); + DASSERT(ptr == (void*)_base_addr(ptr)); + size_t size = _block_length(ptr); + memset((void*)PRIMARY_SHADOW(ptr), 0, size); + memset((void*)SECONDARY_SHADOW(ptr), 0, size); +#ifdef E_ACSL_TEMPORAL /*{{{*/ + memset((void*)TEMPORAL_PRIMARY_STATIC_SHADOW(ptr), 0, size); + memset((void*)TEMPORAL_SECONDARY_STATIC_SHADOW(ptr), 0, size); +#endif /*}}} E_ACSL_TEMPORAL*/ +} +/* }}} */ + +/* Static querying {{{ */ + +/*! \brief Return a non-zero value if a memory region of length `size` + * starting at address `addr` belongs to a tracked stack, tls or + * global memory block and 0 otherwise. + * This function is only safe if applied to a tls, stack or global address. + * Explanations regarding the third argument - `base_ptr` - are given + * via inline documentation of function ::heap_allocated */ +static int static_allocated(uintptr_t addr, long size, uintptr_t base_ptr) { + unsigned char *prim_shadow = (unsigned char*)PRIMARY_SHADOW(addr); + /* Unless the address belongs to tracked allocation 0 is returned */ + if (prim_shadow[0]) { + unsigned int code = (prim_shadow[0] >> 2); + unsigned int long_block = (code >= LONG_BLOCK_INDEX_START); + size_t length, offset; + if (long_block) { + offset = code - LONG_BLOCK_INDEX_START; + unsigned int *sec_shadow = + (unsigned int*)SECONDARY_SHADOW(addr - offset) ; + length = sec_shadow[0]; + offset = sec_shadow[1] + offset; + } else { + offset = short_offsets[code]; + length = short_lengths[code]; + } + +#ifndef E_ACSL_WEAK_VALIDITY + if (addr != base_ptr) { + return BELONGS(base_ptr, addr - offset, length) + && offset + size <= length; + } +#endif + return offset + size <= length; + } + return 0; +} + +/*! \brief Return a non-zero value if a statically allocated memory block + * starting at `addr` of length `size` is fully initialized (i.e., each of + * its cells is initialized). */ +static int static_initialized(uintptr_t addr, long size) { + /* Return 0 right away if the address does not belong to + * static allocation */ + if (!static_allocated(addr, size, addr)) + return 0; + DVALIDATE_STATIC_ACCESS(addr, size); + + int result = 1; + uint64_t *shadow = (uint64_t*)PRIMARY_SHADOW(addr); + while (size > 0) { + int rem = (size >= ULONG_BYTES) ? ULONG_BYTES : size; + uint64_t mask = static_init_masks[rem]; + size -= ULONG_BYTES; + /* Note that most of the blocks checked for initialization will be smaller + * than 64 bits, therefore in most cases it is more efficient to complete + * the loop rather than do a test and return if the result is false */ + result = result && (((*shadow) & mask) == mask); + shadow++; + } + return result; +} + +/*! \brief Checking whether a globally allocated memory block containing an + * address _addr has read-only access. Note, this is light checking that + * relies on the fact that a single block cannot contain read/write and + * read-only parts, that is to check whether the block has read-only access it + * is sufficient to check any of its bytes. */ +#define global_readonly(_addr) \ + checkbit(READONLY_BIT, (*(char*)PRIMARY_GLOBAL_SHADOW(addr))) + +/*! \brief Querying information about a specific global or stack memory address + * (based on the value of parameter `global'). The return value is interpreted + * based on the second argument that specifies parameters of the query: + * + * - 'B' - return the base address of the memory block `addr` belongs to or `0` + * if `addr` lies outside of tracked allocation. + * - 'O' - return the offset of `addr` within its memory block or `0` + * if `addr` lies outside of tracked allocation. + * - 'L' - return the size in bytes of the memory block `addr` belongs to or `0` + * if `addr` lies outside of tracked allocation. + * + * NB: One should make sure that a given address is allocated before querying. + * That is, for the cases when addr does not refer to an allocated memory + * address belonging to static allocation the return value for this function is + * unspecified. */ +static uintptr_t static_info(uintptr_t addr, char type) { + DVALIDATE_STATIC_LOCATION(addr); + unsigned char *prim_shadow = (unsigned char*)PRIMARY_SHADOW(addr); + + /* Unless the address belongs to tracked allocation 0 is returned */ + if (prim_shadow[0]) { + unsigned int code = (prim_shadow[0] >> 2); + unsigned int long_block = (code >= LONG_BLOCK_INDEX_START); + if (long_block) { + unsigned int offset = code - LONG_BLOCK_INDEX_START; + unsigned int *sec_shadow = + (unsigned int*)SECONDARY_SHADOW(addr - offset) ; + switch(type) { + case 'B': /* Base address */ + return addr - offset - sec_shadow[1]; + case 'O': /* Offset */ + return sec_shadow[1] + offset; + case 'L': /* Length */ + return sec_shadow[0]; + default: + DASSERT(0 && "Unknown static query type"); + } + } else { + switch(type) { + case 'B': /* Base address */ + return addr - short_offsets[code]; + case 'O': /* Offset */ + return short_offsets[code]; + case 'L': /* Length */ + return short_lengths[code]; + default: + DASSERT(0 && "Unknown static query type"); + } + } + } + return 0; +} + +#ifdef E_ACSL_TEMPORAL /*{{{*/ +/*! Return either an origin (if `origin` is non-zero) or referent timestamp + * associated with a static address `addr` */ +static uint32_t static_temporal_info(uintptr_t addr, int origin) { + /* NOTE: No checking for allocated blocks, since an invalid + timestamp is zero and ununsed memory is nullified then an invalid + timestamp is also returned for allocated memory */ + if (origin) { + int allocated = static_allocated_one(addr); + if (allocated && !IS_ON_GLOBAL(addr)) { + uintptr_t base = static_info(addr, 'B'); + return *((uint32_t*)TEMPORAL_PRIMARY_STATIC_SHADOW(base)); + } else if (allocated && IS_ON_GLOBAL(addr)) { + return GLOBAL_TEMPORAL_TIMESTAMP; + } else { + return INVALID_TEMPORAL_TIMESTAMP; + } + } else { + return *((uint32_t*)TEMPORAL_SECONDARY_STATIC_SHADOW(addr)); + } +} + +#define static_origin_timestamp(_ptr) static_temporal_info((uintptr_t)(_ptr),1) +#define static_referent_timestamp(_ptr) static_temporal_info((uintptr_t)(_ptr),0) + +/*! Store a referent time stamp associated with a static pointer. + * Origin timestamps are generated via `shadow_alloca` */ +static void static_store_temporal_referent(uintptr_t addr, uint32_t ref) { + DVALIDATE_STATIC_ACCESS(addr, PTR_SZ); + *((uint32_t*)TEMPORAL_SECONDARY_STATIC_SHADOW(addr)) = ref; +} +#endif/*}}} E_ACSL_TEMPORAL*/ +/* }}} */ + +/* Static initialization {{{ */ +/*! \brief The following function marks n bytes starting from the address + * given by addr as initialized. `size` equating to zero indicates that the + * whole block should be marked as initialized. */ +static void initialize_static_region(uintptr_t addr, long size) { + DVALIDATE_STATIC_ACCESS(addr, size); + DVASSERT(!(addr - _base_addr(addr) + size > _block_length(addr)), + "Attempt to initialize %lu bytes past block boundaries\n" + "starting at %a with block length %lu at base address %a\n", + size, addr, _block_length(addr), _base_addr(addr)); + + /* Below code marks `size` bytes following `addr` in the stack shadow as + * initialized. That is, least significant bits of all 9 bytes following + * `addr` should be flipped to ones. While this is a common pattern in this + * program, here are some explanations. + * + * Here we grab a shadow region and initialize 8 (::ULONG_SIZE) bits at a + * time using masks stored in ::static_init_masks. This few lines below are + * better explained using an example. Let's say we need to mark 9 bytes as + * initialized starting from some address `addr`. + * + * In order to do that we first grab a shadow region storing it in `shadow`. + * For the first 8 bytes we grab a mask stored at ::static_init_masks[8]: + * `10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000` + * That is, `*shadow |= static_init_masks[8]` sets 8 lowest significant bits + * of the 8 bytes following *shadow to ones. + * + * After that we need to mark the remaining 1 bite as initialized. For that + * we grab mask ::static_init_masks[1]: + * `10000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000` + * That is, `*shadow |= static_init_masks[1]` will set only the least + * significant bit in *shadow. */ + + uint64_t *shadow = (uint64_t*)PRIMARY_SHADOW(addr); + while (size > 0) { + int rem = (size >= ULONG_BYTES) ? ULONG_BYTES : size; + size -= ULONG_BYTES; + *shadow |= static_init_masks[rem]; + shadow++; + } +} +/* }}} */ + +/* Read-only {{{ */ +/*! \brief Mark n bytes starting from the address given by `ptr` as initialized. + * NOTE: This function has many similarities with ::initialize_static_region + * The functionality, however is preferred to be kept separate + * because the ::mark_readonly should operate only on the global shadow. */ +static void mark_readonly_region (uintptr_t addr, long size) { + /* Since read-only blocks can only be stored in the globals segments (e.g., + * TEXT), this function required ptr carry a global address. */ + DASSERT(IS_ON_GLOBAL(addr)); + DASSERT(static_allocated_one(addr)); + DVASSERT(!(addr - _base_addr(addr) + size > _block_length(addr)), + "Attempt to mark read-only %lu bytes past block boundaries\n" + "starting at %a with block length %lu at base address %a\n", + size, addr, _block_length(addr), _base_addr(addr)); + + /* See comments in ::initialize_static_region for details */ + uint64_t *shadow = (uint64_t*)PRIMARY_GLOBAL_SHADOW(addr); + while (size > 0) { + int rem = (size >= ULONG_BYTES) ? ULONG_BYTES : size; + size -= ULONG_BYTES; + *shadow |= static_readonly_masks[rem]; + shadow++; + } +} +/* }}} */ + +/* Heap allocation {{{ (malloc/calloc) */ + +/*! \brief Create a heap shadow for an allocated memory block starting at `ptr` + * and of length `size`. Optionally mark it as initialized if `init` + * evaluates to a non-zero value. + * \b NOTE: This function assumes that `ptr` is a base address of a + * heap-allocated memory block, such that HEAP_SEGMENT bytes preceding `ptr` + * correspond to `unusable space`. + * \b WARNING: Current implementation assumes that the size of a heap segment + * does not exceed 64 bytes. */ +static void set_heap_segment(void *ptr, size_t size, size_t alloc_size, + size_t init, const char *function) { + + /* Make sure that heap memspace has not been moved. This is likely if + a really large chunk has been requested to be allocated. */ + vassert(mem_spaces.heap_mspace_least == + (uintptr_t)mspace_least_addr(mem_spaces.heap_mspace), + "Exceeded heap allocation limit of %luMB -- heap memory space moved. \n", + E_ACSL_HEAP_SIZE); + + /* Similar check, make sure that allocated space does not exceed given + allocation limit for mspace */ + uintptr_t max_addr = (uintptr_t)ptr + alloc_size; + vassert(mem_spaces.heap_end > max_addr, + "Exceeded heap allocation limit of %luMB\n", E_ACSL_HEAP_SIZE); + + DVALIDATE_MEMORY_INIT; + /* Ensure the shadowed block in on the tracked heap portion */ + DVALIDATE_IS_ON_HEAP(((uintptr_t)ptr) - HEAP_SEGMENT, size); + DVALIDATE_ALIGNMENT(ptr); /* Make sure alignment is right */ + update_heap_allocation(size); /* Adjust tracked allocation size */ + + /* Get aligned size of the block, i.e., an actual size of the + * allocated block */ + unsigned char *shadow = (unsigned char*)HEAP_SHADOW(ptr); + + /* Make sure shadow is nullified before setting it */ + DVALIDATE_NULLIFIED(shadow, alloc_size); + + /* The overall number of block segments in a tracked memory block */ + size_t segments = alloc_size/HEAP_SEGMENT; + uintptr_t *segment = (uintptr_t*)(shadow); + segment[1] = size; + +#ifdef E_ACSL_TEMPORAL /*{{{*/ + /* 4 bytes following a block's length store an origin timestamp */ + segment[2] = NEW_TEMPORAL_TIMESTAMP(); +#endif /*}}} E_ACSL_TEMPORAL*/ + + int i; + /* Write the offsets per segment */ + for (i = 0; i < segments; i++) { + segment = (uintptr_t*)(shadow + i*HEAP_SEGMENT); + *segment = (uintptr_t)ptr; + } + + /* If init is a non-zero value then mark all allocated bytes as initialized */ + if (init) { + memset((void*)HEAP_INIT_SHADOW(ptr), (unsigned int)ONE, alloc_size/8); + } +} + +extern int MSPACES_INIT; +/*! \brief Replacement for a malloc function that additionally tracks the + * allocated memory block. + * + * NOTE: This malloc returns a `NULL` pointer if the requested size is `0`. + * Such behaviour is compliant with the C99 standard, however it differs from + * the behaviour of the GLIBC malloc, which returns a zero-size block instead. + * The standard indicates that a return value for a zero-sized allocation + * is implementation specific: + * "If the size of the space requested is zero, the behaviour is + * implementation-defined: either a null pointer is returned, or the + * behaviour is as if the size were some non-zero value, except that the + * returned pointer shall not be used to access an object." */ +void* malloc(size_t size) { + + size_t alloc_size = ALLOC_SIZE(size); + + /* Return NULL if the size is too large to be aligned */ + char* res; + if (alloc_size) { + mspaces_init(); + res = (char*)public_malloc(alloc_size); + } else + res = NULL; + + if (res) { + /* Make sure there is sufficient room in shadow */ + set_heap_segment(res, size, alloc_size, 0, "malloc"); + } + + return res; +} + +/*! \brief Replacement for `calloc` that enables memory tracking */ +void* calloc(size_t nmemb, size_t size) { + /* Since both `nmemb` and `size` are both of size `size_t` the multiplication + * of the arguments (which gives the actual allocation size) might lead to an + * integer overflow. The below code checks for an overflow and sets the + * `alloc_size` (argument a memory allocation function) to zero. */ + size = (size && nmemb > SIZE_MAX/size) ? 0 : nmemb*size; + + size_t alloc_size = ALLOC_SIZE(size); + + /* Since aligned size is required by the model do the allocation through + * `malloc` and nullify the memory space by hand */ + char* res; + if (size) { + mspaces_init(); + res = (char*)public_malloc(alloc_size); + } else + res = NULL; + + if (res) { + /* Make sure there is sufficient room in shadow */ + memset(res, 0, size); + set_heap_segment(res, size, alloc_size, 1, "calloc"); + } + return res; +} + +/** \brief Return shadowed copy of a memory chunk on a program's heap using. + * If `init` parameter is set to a non-zero value the memory occupied by the + * resulting block is set to be initialized and uninitialized otherwise. */ +static void *shadow_copy(const void *ptr, size_t size, int init) { + char *ret = (init) ? calloc(1, size) : malloc(size); + vassert(ret != NULL, "Shadow copy failed\n", NULL); + /* Shadow copy is internal, therefore heap status should not be updated. + Since it is set via `set_heap_segment`, it needs to be reverted back. */ + update_heap_allocation(-size); + return memcpy(ret, ptr, size); +} +/* }}} */ + +/* Heap deallocation (free) {{{ */ + +/*! \brief Remove a memory block with base address given by `ptr` from tracking. + * This function effectively nullifies block shadow tracking an application + * block. + * + * NOTE: ::unset_heap_segment assumes that `ptr` is a base address of an + * allocated heap memory block, i.e., `freeable(ptr)` evaluates to true. + * + * \param ptr - base address of the memory block to be removed from tracking + * \param init - if evaluated to a non-zero value then initialization shadow + * of the memory block with base address `ptr` is nullified as well. + * \param function - name of the de-allocation function (e.g., `free` or `cfree`) +*/ +static void unset_heap_segment(void *ptr, int init, const char *function) { + DVALIDATE_MEMORY_INIT; + DVALIDATE_FREEABLE(((uintptr_t)ptr)); + /* Base address of shadow block */ + uintptr_t *base_shadow = (uintptr_t*)HEAP_SHADOW(ptr); + /* Physical allocation size */ + size_t alloc_size = ALLOC_SIZE(base_shadow[1]); + /* Actual block length */ + size_t length = base_shadow[1]; + /* Nullify shadow block */ + memset(base_shadow, ZERO, alloc_size); + /* Adjust tracked allocation size */ + heap_allocation_size -= length; +#ifdef E_ACSL_TEMPORAL /*{{{*/ + /* Nullify temporal shadow */ + uintptr_t *t_base_shadow = (uintptr_t*)TEMPORAL_HEAP_SHADOW(ptr); + memset(t_base_shadow, ZERO, alloc_size); +#endif /*}}} E_ACSL_TEMPORAL*/ + /* Nullify init shadow */ + if (init) { + memset((void*)HEAP_INIT_SHADOW(ptr), 0, alloc_size/8); + } +} + +/*! \brief Replacement for `free` with memory tracking */ +void free(void *ptr) { + if (ptr == NULL) { +/* Fail if instructed to treat NULL input to free as invalid. */ +#ifdef E_ACSL_FREE_VALID_ADDRESS + vabort("NULL pointer in free\n"); +#endif + return; + } + + if (ptr != NULL) { /* NULL is a valid behaviour */ + if (freeable(ptr)) { + unset_heap_segment(ptr, 1, "free"); + public_free(ptr); + } else { + vabort("Not a start of block (%a) in free\n", ptr); + } + } +} +/* }}} */ + +/* Heap reallocation (realloc) {{{ */ +void* realloc(void *ptr, size_t size) { + char *res = NULL; /* Resulting pointer */ + /* If the pointer is NULL then realloc is equivalent to malloc(size) */ + if (ptr == NULL) + return malloc(size); + /* If the pointer is not NULL and the size is zero then realloc is + * equivalent to free(ptr) */ + else if (ptr != NULL && size == 0) { + free(ptr); + } else { + if (freeable(ptr)) { /* ... and can be used as an input to `free` */ + size_t alloc_size = ALLOC_SIZE(size); + res = public_realloc(ptr, alloc_size); + DVALIDATE_ALIGNMENT(res); + + /* realloc succeeds, otherwise nothing needs to be done */ + if (res != NULL) { + size_t alloc_size = ALLOC_SIZE(size); + size_t old_size = _block_length(ptr); + size_t old_alloc_size = ALLOC_SIZE(old_size); + + /* Nullify old representation */ + unset_heap_segment(ptr, 0, "realloc"); + + /* Set up new block shadow */ + set_heap_segment(res, size, alloc_size, 0, "realloc"); + + /* Move init shadow */ + unsigned char* old_init_shadow = (unsigned char*)HEAP_INIT_SHADOW(ptr); + unsigned char* new_init_shadow = (unsigned char*)HEAP_INIT_SHADOW(res); + + /* If realloc truncates allocation in the old init shadow it is first + * needed to clear the old init shadow from the boundary of the old + * shadow block to the size of the new allocation */ + if (old_size > size) { + clearbits_right( + old_alloc_size - size, + old_init_shadow + old_alloc_size/8); + } + + /* Now init shadow can be moved (if needed), keep in mind that + * segment base addresses are aligned at a boundary of something + * divisible by 8, so instead of moving actual bits here the + * segments are moved to avoid dealing with bit-level operations + * on incomplete bytes. */ + if (res != ptr) { + size_t copy_size = (old_size > size) ? alloc_size : old_alloc_size; + memcpy(new_init_shadow, old_init_shadow, copy_size); + memset(old_init_shadow, 0, copy_size); + } + } + } else { + vabort("Not a start of block (%a) in realloc\n", ptr); + } + } + return res; +} +/* }}} */ + +/* Heap aligned allocation (aligned_alloc) {{{ */ +/*! \brief Replacement for `aligned_alloc` with memory tracking */ +void *aligned_alloc(size_t alignment, size_t size) { + /* Check if: + * - size and alignment are greater than zero + * - alignment is a power of 2 + * - size is a multiple of alignment */ + if (!size || !alignment || !powof2(alignment) || (size%alignment)) + return NULL; + + char *res = public_aligned_alloc(alignment, size); + + if (res) { + set_heap_segment(res, size, ALLOC_SIZE(size), 0, "aligned_alloc"); + } + + return (void*)res; +} +/* }}} */ + +/* Heap aligned allocation (posix_memalign) {{{ */ +/*! \brief Replacement for `posix_memalign` with memory tracking */ +int posix_memalign(void **memptr, size_t alignment, size_t size) { + /* Check if: + * - size and alignment are greater than zero + * - alignment is a power of 2 and a multiple of sizeof(void*) */ + if (!size || !alignment || !powof2(alignment) || alignment%sizeof(void*)) + return -1; + + /* Make sure that the first argument to posix memalign is indeed allocated */ + vassert(allocated((uintptr_t)memptr, sizeof(void*), (uintptr_t)memptr), + "\\invalid memptr in posix_memalign", NULL); + + int res = public_posix_memalign(memptr, alignment, size); + if (!res) { + set_heap_segment(*memptr, size, ALLOC_SIZE(size), 0, "posix_memalign"); + } + return res; +} +/* }}} */ + +/* Heap querying {{{ */ +/*! \brief Return a non-zero value if a memory region of length `size` + * starting at address `addr` belongs to an allocated (tracked) heap memory + * block and a 0 otherwise. Note, this function is only safe if applied to a + * heap address. + * + * Note the third argument `base_ptr` that represents the base of a pointer, i.e., + * `addr` of the form `base_ptr + i`, where `i` is some integer index. + * ::heap_allocated also returns zero if `base_ptr` and `addr` belong to different + * memory blocks, or if `base_ptr` lies within unallocated region. The intention + * here is to be able to detect dereferencing of an allocated memory block through + * a pointer to a different block. Consider, for instance, some pointer `p` that + * points to a memory block `B`, and an index `i`, such that `p+i` references a + * memory location belonging to a different memory block (say `C`). From a + * low-level viewpoint, dereferencing `p+i` is safe (since it belongs to a properly + * allocated block). From our perspective, however, dereference of `p+i` is + * only legal if both `p` and `p+i` point to the same block. */ +static int heap_allocated(uintptr_t addr, size_t size, uintptr_t base_ptr) { + /* Base address of the shadow segment the address belongs to */ + uintptr_t *shadow = (uintptr_t*)HEAP_SHADOW(addr - addr%HEAP_SEGMENT); + + /* Non-zero if the segment belongs to heap allocation */ + if (shadow[0]) { + uintptr_t *base_shadow = + (uintptr_t*)HEAP_SHADOW(base_ptr - base_ptr%HEAP_SEGMENT); + uintptr_t *first_segment = (uintptr_t*)HEAP_SHADOW(shadow[0]); + /* shadow[0] - base address of the tracked block + * fist_segment[1] - length (i.e., location in the first segment + * after base address) + * offset is the difference between the address and base address (shadow[0]) + * Then an address belongs to heap allocation if + * offset + size <= length + * + * Additionally, if strong validity is enforced + * (i.e., E_ACSL_WEAK_VALIDITY macro undefined) make sure that both + * `addr` and `base_ptr` belong to the same block. */ +#ifndef E_ACSL_WEAK_VALIDITY + return base_shadow[0] == shadow[0] && + (addr - shadow[0]) + size <= first_segment[1]; +#else + return (addr - shadow[0]) + size <= first_segment[1]; +#endif + } + return 0; +} + +/*! \brief Return a non-zero value if a given address is a base address of a + * heap-allocated memory block that `addr` belongs to. + * + * As some of the other functions, \b \\freeable can be expressed using + * ::IS_ON_HEAP, ::heap_allocated and ::_base_addr. Here direct + * implementation is preferred for performance reasons. */ +int freeable(void *ptr) { /* + */ + uintptr_t addr = (uintptr_t)ptr; + /* Address is not on the program's heap, so cannot be freed */ + if (!IS_ON_HEAP(addr)) + return 0; + + /* Address of the shadow segment the address belongs to */ + uintptr_t *shadow = (uintptr_t*)ALIGNED_HEAP_SHADOW(addr); + /* Non-zero if the segment belongs to heap allocation with *shadow + * capturing the base address of the tracked block */ + if (*shadow) { + /* Block is freeable if `addr` is the base address of its block */ + return (uintptr_t)*shadow == addr; + } + return 0; +} + +/*! \brief Querying information about a specific heap memory address. + * This function is similar to ::static_info except it returns data + * associated with dynamically allocated memory. + * See in-line documentation for ::static_info for further details. */ +static uintptr_t heap_info(uintptr_t addr, char type) { + /* Ensure that `addr` is an allocated location on a program's heap */ + DVALIDATE_HEAP_ACCESS(addr, 1); + /* Base address of the shadow segment the address belongs to. + * First `sizeof(uintptr_t)` bytes of each segment store application-level + * base address of the tracked block */ + uintptr_t *aligned_shadow = (uintptr_t*)ALIGNED_HEAP_SHADOW(addr); + + switch(type) { + case 'B': /* Base address */ + return *aligned_shadow; + case 'L': { /* Block length */ + /* Pointer to the first-segment in the shadow block */ + uintptr_t *base_segment = (uintptr_t*)HEAP_SHADOW(*aligned_shadow); + /* Length of the stored block is captured in `sizeof(uintptr_t)` bytes + * past `sizeof(uintptr_t)` tracking the base address */ + return base_segment[1]; + } + case 'O': + /* Offset of a given address within its block. This is the difference + * between the input address and the base address of the block. */ + return addr - *aligned_shadow; + default: + DASSERT(0 && "Unknown heap query type"); + } + return 0; +} + +/*! \brief Implementation of the \b \\initialized predicate for heap-allocated + * memory. NB: If `addr` does not belong to an allocated heap block this + * function returns 0. */ +static int heap_initialized(uintptr_t addr, long len) { + /* Base address of a shadow segment addr belongs to */ + unsigned char *shadow = (unsigned char*)(HEAP_INIT_SHADOW(addr)); + + /* See comments in the `initialize_heap_region` function for more details */ + unsigned skip = (addr - HEAP_START)%8; + unsigned set; + if (skip) { + set = 8 - skip; + set = (len > set) ? set : len; + len -= set; + unsigned char mask = 0; + setbits64_skip(set,mask,skip); + + if (*shadow != mask) + return 0; + } + if (len > 0) + return checkbits(len, shadow); + return 1; +} + +/* }}} */ + +/* Heap temporal querying {{{*/ +#ifdef E_ACSL_TEMPORAL +static uint32_t heap_temporal_info(uintptr_t addr, int origin) { + /* NOTE: No checking for allocated blocks, since an invalid + timestamp is zero and unused memory is nullified then an invalid + timestamp is also returned for allocated memory */ + if (origin) { + uintptr_t *aligned_shadow = (uintptr_t*)ALIGNED_HEAP_SHADOW(addr); + uintptr_t *base_shadow = (uintptr_t*)HEAP_SHADOW(*aligned_shadow); + return (uint32_t)base_shadow[2]; + } else { + return *((uint32_t*)TEMPORAL_HEAP_SHADOW(addr)); + } +} + +#define heap_origin_timestamp(_ptr) heap_temporal_info((uintptr_t)(_ptr),1) +#define heap_referent_timestamp(_ptr) heap_temporal_info((uintptr_t)(_ptr),0) + +static void heap_store_temporal_referent(uintptr_t addr, uint32_t ref) { + DVALIDATE_HEAP_ACCESS(addr, PTR_SZ); + uint32_t *temporal_shadow = (uint32_t*)TEMPORAL_HEAP_SHADOW(addr); + *temporal_shadow = ref; +} +#endif/*}}} E_ACSL_TEMPORAL*/ + +/* Heap initialization {{{ */ +/*! \brief Mark n bytes on the heap starting from address addr as initialized */ +static void initialize_heap_region(uintptr_t addr, long len) { + DVALIDATE_HEAP_ACCESS(addr, len); + DVASSERT(!(addr - _base_addr(addr) + len > _block_length(addr)), + "Attempt to initialize %lu bytes past block boundaries\n" + "starting at %a with block length %lu at base address %a\n", + len, addr, _block_length(addr), _base_addr(addr)); + + /* Address within init shadow tracking initialization */ + unsigned char *shadow = (unsigned char*)(HEAP_INIT_SHADOW(addr)); + + /* First check whether the address in the init shadow is divisible by 8 + * (i.e., located on a byte boundary) */ + /* Leading bits in `*shadow` byte which do not need to be set + * (i.e., skipped) */ + short skip = (addr - HEAP_START)%8; + if (skip) { + /* The remaining bits in the shadow byte */ + short set = 8 - skip; + /* The length of initialized region can be short (shorter then the + * above remainder). Adjust the number of bits to set accordingly. */ + set = (len > set) ? set : len; + len -= set; + setbits64_skip(set, *shadow, skip); + /* Move to the next location if there are more bits to set */ + shadow++; + } + + if (len > 0) { + /* Set the remaining bits. Note `shadow` is now aligned at a byte + * boundary, thus one can set `len` bits starting with address given by + * `shadow` */ + setbits(len, shadow); + } +} +/* }}} */ + +/* Any allocation {{{ */ +/*! \brief Amalgamation of ::heap_allocated and ::static_allocated */ +static int allocated(uintptr_t addr, long size, uintptr_t base) { + TRY_SEGMENT_WEAK(addr, + return heap_allocated(addr, size, base), + return static_allocated(addr, size, base)); + if (!IS_ON_VALID(addr)) + return 0; + return 0; +} + +/** \brief Return 1 if a given memory location is read-only and 0 otherwise */ +static inline int readonly (void *ptr) { + uintptr_t addr = (uintptr_t)ptr; + return IS_ON_GLOBAL(addr) && global_readonly(addr) ? 1 : 0; +} + +static inline int writeable(uintptr_t addr, long size, uintptr_t base_ptr) { + return allocated(addr, size, base_ptr) && !readonly((void*)addr); +} +/* }}} */ + +/* Internal state print (debug mode) {{{ */ +#ifdef E_ACSL_DEBUG +/* ! \brief Print human-readable representation of a byte in a primary + * shadow */ +static void printbyte(unsigned char c, char buf[]) { + if (c >> 2 < LONG_BLOCK_INDEX_START) { + rtl_sprintf(buf, "PRIMARY: I{%u} RO{%u} OF{%2u} => %u[%u]", + checkbit(INIT_BIT,c), checkbit(READONLY_BIT,c), c >> 2, + short_lengths[c >> 2], short_offsets[c >> 2]); + } else { + rtl_sprintf(buf, "SECONDARY: I{%u} RO{%u} OF{%u} => %4u", + checkbit(INIT_BIT,c), checkbit(READONLY_BIT,c), + (c >> 2), (c >> 2) - LONG_BLOCK_INDEX_START); + } +} + +/*! \brief Print human-readable (well, ish) representation of a memory block + * using primary and secondary shadows. */ +static void print_static_shadows(uintptr_t addr, size_t size) { + char prim_buf[256]; + char sec_buf[256]; + + unsigned char *prim_shadow = (unsigned char*)PRIMARY_SHADOW(addr); + unsigned int *sec_shadow = (unsigned int*)SECONDARY_SHADOW(addr); + + int i, j = 0; + for (i = 0; i < size; i++) { + sec_buf[0] = '\0'; + printbyte(prim_shadow[i], prim_buf); + if (IS_LONG_BLOCK(size) && (i%LONG_BLOCK) == 0) { + j += 2; + if (i < LONG_BLOCK_BOUNDARY(size)) { + rtl_sprintf(sec_buf, " %a SZ{%u} OF{%u}", + &sec_shadow[j], sec_shadow[j-2], sec_shadow[j-1]); + } + if (i) { + DLOG("---------------------------------------------\n"); + } + } + DLOG("| [%2d] %a | %s || %s\n", i, &prim_shadow[i], prim_buf, sec_buf); + } +#ifdef E_ACSL_TEMPORAL /* {{{ */ + uint32_t* origin_shadow = (uint32_t*)TEMPORAL_PRIMARY_STATIC_SHADOW(addr); + uint32_t* ref_shadow = (uint32_t*)TEMPORAL_SECONDARY_STATIC_SHADOW(addr); + DLOG(" | > Blk ID: %u\n", i, *origin_shadow); + for (i = 0; i < size; i+=PTR_SZ) + DLOG(" | > Ref ID[%u]: %u\n", i/8, *(ref_shadow + 1)); +#endif /*}}} E_ACSL_TEMPORAL*/ +} + +/*! \brief Print human-readable representation of a heap shadow region for a + * memory block of length `size` starting at address `addr`. This function + * assumes that `addr` is the base address of the memory block. */ +static void print_heap_shadows(uintptr_t addr) { + unsigned char *block_shadow = (unsigned char*)HEAP_SHADOW(addr); + unsigned char *init_shadow = (unsigned char*)HEAP_INIT_SHADOW(addr); + + size_t length = (size_t)((uintptr_t*)(block_shadow))[1]; + size_t alloc_size = ALLOC_SIZE(length); + size_t segments = alloc_size/HEAP_SEGMENT; + uintptr_t *segment = (uintptr_t*)(block_shadow); + + DLOG(" | === Block Shadow ======================================\n"); + DLOG(" | Access addr: %a\n", addr); + DLOG(" | Block Shadow: %a\n", block_shadow); + DLOG(" | Init Shadow: %a\n", init_shadow); + DLOG(" | Segments: %lu\n", segments); + DLOG(" | Actual size: %lu bytes\n", alloc_size); + DLOG(" | Tracked Length: %lu bytes\n", length); + + if (zeroed_out(block_shadow, alloc_size)) + DLOG(" | << Nullified >> \n"); + +#ifdef E_ACSL_TEMPORAL /*{{{*/ + DLOG(" | Origin TS: %u\n", (uint32_t)segment[2]); +#endif /*}}}*/ + + size_t i; + for (i = 0; i < segments; i++) { + segment = (uintptr_t*)(block_shadow + i*HEAP_SEGMENT); + DLOG(" | Segment: %lu, Base: %a \n", i, *segment); + } + + DLOG(" | Initialization: \n | "); + for (i = 0; i < alloc_size/8; i++) { + if (i > 0 && (i*8)%HEAP_SEGMENT == 0) + DLOG("\n | "); + DLOG("%8b ", init_shadow[i], init_shadow[i]); + } + DLOG("\n"); +} + +static void print_shadows(uintptr_t addr, size_t size) { + if (IS_ON_STATIC(addr)) + print_static_shadows(addr, size); + else if (IS_ON_HEAP(addr)) + print_heap_shadows(addr); +} + +static void print_memory_segment(struct memory_segment *p, char *lab, int off) { + DLOG(" %s: %lu MB [%lu, %lu]", lab, MB_SZ(p->size), p->start, p->end); + if (off) + DLOG("{ Offset: %ld }", p->shadow_offset); + DLOG("\n"); +} + +static void print_memory_partition(struct memory_partition *p) { + print_memory_segment(&p->application, "Application", 0); + print_memory_segment(&p->primary, "Primary ", 1); + print_memory_segment(&p->secondary, "Secondary ", 1); +#ifdef E_ACSL_TEMPORAL + print_memory_segment(&p->temporal_primary, "Temporal Primary ", 1); + print_memory_segment(&p->temporal_secondary, "Temporal Secondary ", 1); +#endif +} + +static void print_shadow_layout() { + DLOG(">>> HEAP ---------------------\n"); + print_memory_partition(&mem_layout.heap); + DLOG(">>> STACK --------------------\n"); + print_memory_partition(&mem_layout.stack); + DLOG(">>> GLOBAL -------------------\n"); + print_memory_partition(&mem_layout.global); + DLOG(">>> TLS ----------------------\n"); + print_memory_partition(&mem_layout.tls); + DLOG(">>> --------------------------\n"); +} + +/*! \brief Output the shadow segment the address belongs to */ +static const char* which_segment(uintptr_t addr) { + const char *loc = NULL; + if (IS_ON_STACK(addr)) + loc = "stack"; + else if (IS_ON_HEAP(addr)) + loc = "heap"; + else if (IS_ON_GLOBAL(addr)) + loc = "global"; + else if (IS_ON_TLS(addr)) + loc = "TLS"; + else + loc = "untracked"; + return loc; +} + +/* NOTE: Above functions are designed to be used only through the following + * macros or debug functions included/defined based on the value of the + * E_ACSL_DEBUG macro. */ + +/*! \brief Print program layout. This function outputs start/end addresses of + * various program segments, their shadow counterparts and sizes of shadow + * regions used. */ +#define DEBUG_PRINT_LAYOUT print_shadow_layout() +void ___e_acsl_debug_print_layout() { DEBUG_PRINT_LAYOUT; } + +/*! \brief Print the shadow segment address addr belongs to */ +#define DEBUG_PRINT_SEGMENT(_addr) which_segment(_addr) +void ___e_acsl_debug_print_segment(uintptr_t addr) { DEBUG_PRINT_SEGMENT(addr); } + +/*! \brief Print human-readable representation of a shadow region corresponding + * to a memory address addr. The second argument (size) if the size of the + * shadow region to be printed. Normally addr argument is a base address of a + * memory block and size is its length. */ +#define DEBUG_PRINT_SHADOW(addr, size) \ + print_shadows((uintptr_t)addr, (size_t)size) +void ___e_acsl_debug_print_shadow(uintptr_t addr, size_t size) { + DEBUG_PRINT_SHADOW(addr, size); +} + +#else +/* \cond exclude from doxygen */ +#define DEBUG_PRINT_SHADOW(addr, size) +#define DEBUG_PRINT_LAYOUT +#define DEBUG_PRINT_SEGMENT(addr) +/* \endcond */ +#endif +/* }}} */ diff --git a/src/plugins/e-acsl/share/e-acsl/segment_model/e_acsl_shadow_layout.h b/src/plugins/e-acsl/share/e-acsl/segment_model/e_acsl_shadow_layout.h new file mode 100644 index 0000000000000000000000000000000000000000..4dde664bbd05aeb488a6d009dd13fe11fef66f96 --- /dev/null +++ b/src/plugins/e-acsl/share/e-acsl/segment_model/e_acsl_shadow_layout.h @@ -0,0 +1,622 @@ +/**************************************************************************/ +/* */ +/* This file is part of the Frama-C's E-ACSL plug-in. */ +/* */ +/* Copyright (C) 2012-2018 */ +/* CEA (Commissariat à l'énergie atomique et aux énergies */ +/* alternatives) */ +/* */ +/* you can redistribute it and/or modify it under the terms of the GNU */ +/* Lesser General Public License as published by the Free Software */ +/* Foundation, version 2.1. */ +/* */ +/* It is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Lesser General Public License for more details. */ +/* */ +/* See the GNU Lesser General Public License version 2.1 */ +/* for more details (enclosed in the file licenses/LGPLv2.1). */ +/* */ +/**************************************************************************/ + +/*! *********************************************************************** + * \file e_acsl_shadow_layout.h + * \brief Setup for memory tracking using shadowing +***************************************************************************/ + +/* Default size of a program's heap tracked via shadow memory */ +#ifndef E_ACSL_HEAP_SIZE +#define E_ACSL_HEAP_SIZE 512 +#endif + +/* Default size of a program's stack tracked via shadow memory */ +#ifndef E_ACSL_STACK_SIZE +#define E_ACSL_STACK_SIZE 64 +#endif + +/* Symbols exported by the linker script */ + +/*!\brief The first address past the end of the text segment. */ +extern char etext; +/*!\brief The first address past the end of the initialized data segment. */ +extern char edata; +/*!\brief The first address past the end of the uninitialized data segment. */ +extern char end; +/*!\brief The first address of a program. */ +extern char __executable_start; + +/* \cond */ +void *sbrk(intptr_t increment); +char *strerror(int errnum); + +/* MAP_ANONYMOUS is a mmap flag indicating that the contents of allocated blocks + * should be nullified. Set value from <bits/mman-linux.h>, if MAP_ANONYMOUS is + * undefined */ +#ifndef MAP_ANONYMOUS +#define MAP_ANONYMOUS 0x20 +#endif +/* \endcond */ + +/*! \brief Byte-width of a pointer */ +#define PTR_SZ sizeof(uintptr_t) + +/*! \brief Byte-width of the largest integer type usable with bitwise + * operators */ +#define ULONG_BYTES 8 +/*! \brief Bit-width of the largest integer type usable with bitwise + * operators */ +#define ULONG_BITS 64 + +/** Hardcoded sizes of tracked program segments {{{ */ +/*! \brief Size of a program's heap */ +#define PGM_HEAP_SIZE (E_ACSL_HEAP_SIZE * MB) + +/*! \brief Size of a program's Thread-local storage (TLS). + Standard streams stdin, stdout and stderr are put here. + Some libraries such as libxml use it quite a lot: + it may occur that the given size is not enough, + in which case it MUST be increased. */ +#ifndef PGM_TLS_SIZE +#define PGM_TLS_SIZE (64 * MB) +#endif + +/*! \brief Mspace padding used by shadow segments. This is to make sure that + * some allocation which exceeds the size of an initial memspace does not + * move the mspace somewhere else. 512KB is a bit of an overkill, but should + * not hurt too much in general unless memory space is really a constraint */ +#define SHADOW_SEGMENT_PADDING (512*KB) +/* }}} */ + +/** Thread-local storage information {{{ */ + +/*! Thread-local storage (TLS) keeps track of copies of per-thread variables. + * Even though at the present stage RTL of E-ACSL is not thread-safe, some + * of the variables (for instance ::errno) are allocated there. In X86 TLS + * is typically located somewhere below the program's stack but above mmap + * areas. TLS is typically separated into two sections: .tdata and .tbss. + * Similar to globals using .data and .bss, .tdata keeps track of initialized + * thread-local variables, while .tbss holds uninitialized ones. + * + * Start and end addresses of TLS are obtained by taking addresses of + * initialized and uninitialized variables in TLS (::id_tdata and ::id_tss) + * and adding fixed amount of shadow space around them. Visually it looks + * as follows: + * + * end TLS address (&id_tdata + TLS_SHADOW_SIZE/2) + * id_tdata address + * ... + * id_tbss address + * start TLS address (&id_bss - TLS_SHADOW_SIZE/2) + * + * HOWEVER problems can occur if PGM_TLS_SIZE is too big: + * see get_tls_start for details. + */ + +/*! \brief Return byte-size of the TLS segment */ +static size_t get_tls_size() { + return PGM_TLS_SIZE; +} + +static __thread int id_tdata = 1; +static __thread int id_tbss; + +/* }}} */ + +/** Program stack information {{{ */ +extern char ** environ; + +/*! \brief Set a new soft stack limit + * \param size - new stack size in bytes */ +static size_t increase_stack_limit(const size_t size) { + rlim_t stacksz = (rlim_t)size; + struct rlimit rl; + int result = getrlimit(RLIMIT_STACK, &rl); + if (result == 0) { + if (rl.rlim_cur < stacksz) { + if (stacksz>rl.rlim_max) stacksz = rl.rlim_max; + rl.rlim_cur = stacksz; + result = setrlimit(RLIMIT_STACK, &rl); + if (result != 0) { + vabort("setrlimit: %s \n", strerror(errno)); + } + } + } else { + vabort("getrlimit: %s \n", strerror(errno)); + } + return (size_t)stacksz; +} + +/*! \brief Return byte-size of a program's stack. The return value is the soft + * stack limit, i.e., it can be programmatically increased at runtime. */ +static size_t get_default_stack_size() { + struct rlimit rlim; + vassert(!getrlimit(RLIMIT_STACK, &rlim), + "Cannot detect program's stack size", NULL); + return rlim.rlim_cur; +} + +static size_t get_stack_size() { +#ifndef E_ACSL_STACK_SIZE + return get_default_stack_size(); +#else + return increase_stack_limit(E_ACSL_STACK_SIZE*MB); +#endif +} + +/*! \brief Return greatest (known) address on a program's stack. + * This function presently determines the address using the address of the + * last string in `environ`. That is, it assumes that argc and argv are + * stored below environ, which holds for GCC/Glibc but is not necessarily + * true for some other compilers/libraries. */ +static uintptr_t get_stack_start(int *argc_ref, char *** argv_ref) { + char **env = environ; + while (env[1]) + env++; + uintptr_t addr = (uintptr_t)*env + strlen(*env); + + /* When returning the end stack address we need to make sure that + * ::ULONG_BITS past that address are actually writeable. This is + * to be able to set initialization and read-only bits ::ULONG_BITS + * at a time. If not respected, this may cause a segfault in + * ::argv_alloca. */ + uintptr_t stack_end = addr + ULONG_BITS; + uintptr_t stack_start = stack_end - get_stack_size(); + return stack_start; +} +/* }}} */ + +/** Program heap information {{{ */ +/*! \brief Return the start address of a program's heap. */ +static uintptr_t get_heap_start() { + return mem_spaces.heap_start; +} + +/*! \brief Return the tracked size of a program's heap. */ +static size_t get_heap_size() { + return PGM_HEAP_SIZE; +} + +/*! \brief Return the size of a secondary shadow region tracking + * initialization (i.e., init shadow). */ +static size_t get_heap_init_size() { + return get_heap_size()/8; +} + +/** }}} */ + +/** Program global information {{{ */ +/*! \brief Return the start address of a segment holding globals (generally + * BSS and Data segments). */ +static uintptr_t get_global_start() { + return (uintptr_t)&__executable_start; +} + +/*! \brief Return byte-size of global segment */ +static size_t get_global_size() { + return ((uintptr_t)&end - get_global_start()); +} +/** }}} */ + +/** Shadow Layout {{{ */ +/***************************************************************************** + * Memory Layout ************************************************************* + ***************************************************************************** + ----------------------------------------> Max address + Kernel Space + ----------------------------------------> + Non-canonical address space (only in 64-bit) + ----------------------------------------> + Environment variables [ GLIBC extension ] + -----------------------------------------> + Program arguments [ argc, argv ] + -----------------------------------------> Stack End + Stack [ Grows downwards ] + -----------------------------------------> + Thread-local storage (TLS) [ TDATA and TBSS ] + -----------------------------------------> + Shadow memory [ Heap, Stack, Global, TLS ] + -----------------------------------------> + Object mappings + -----------------------------------------> + -----------------------------------------> + Heap [ Grows upwards^ ] + -----------------------------------------> Heap Start [Initial Brk] + BSS Segment [ Uninitialised Globals ] + -----------------------------------------> + Data Segment [ Initialised Globals ] + -----------------------------------------> + ROData [ Potentially ] + -----------------------------------------> + Text Segment [ Constants ] + -----------------------------------------> NULL (0) + ***************************************************************************** +NOTE: Above memory layout scheme generally applies to Linux Kernel/gcc/glibc. + It is also an approximation slanted towards 64-bit virtual process layout. + In reality layouts may vary. Also, with mmap allocations heap does not + necessarily grows from program break upwards. Typically mmap will allocate + memory somewhere closer to stack. */ + +/* Struct representing a contigous memory region. Effectively this describes + * a memory segment, such as heap, stack or segments in the shadow memory + * used to track them. */ +struct memory_segment { + const char *name; //!< Symbolic name + size_t size; //!< Byte-size + uintptr_t start; //!< Least address + uintptr_t end; //!< Greatest address + mspace mspace; // !< Mspace used for the partition + /* The following are only set if the segment is a shadow segment */ + struct memory_segment *parent; //!< Pointer to the tracked segment + size_t shadow_ratio; //!< Ratio of shadow to application memory + /*!< Offset between the start of the tracked segment and the start of this + segment */ + intptr_t shadow_offset; +}; + +typedef struct memory_segment memory_segment; + +/* Struct representing a memory segment along with information about its + * shadow spaces. */ +struct memory_partition { + memory_segment application; /* Application memory segment */ + memory_segment primary; /* Primary shadow segment */ + memory_segment secondary; /* Secondary shadow segment */ +#ifdef E_ACSL_TEMPORAL + memory_segment temporal_primary; /* Primary temporal shadow segment */ + memory_segment temporal_secondary; /* Secondary temporal shadow segment */ +#endif +}; + +typedef struct memory_partition memory_partition; + +/* Struct representing memory layout of a program consisting of heap, stack, + global and tls segments */ +struct memory_layout { + memory_partition heap; + memory_partition stack; + memory_partition global; + memory_partition tls; + int is_initialized; +}; + +/*! \brief Full program memory layout. */ +static struct memory_layout mem_layout; + +/*! \brief Array of used partitions */ +static memory_partition *mem_partitions [] = { + &mem_layout.heap, + &mem_layout.stack, + &mem_layout.global, + &mem_layout.tls +}; + +/*! \brief Initialize an application memory segment. + * + * \param seg - pointer to a segment to initialize + * \param start - least address in an application's segment + * \param size - size in bytes + * \param name - segment name + * \param msp - mspace used for this segment (defined only for heap) */ +static void set_application_segment(memory_segment *seg, uintptr_t start, + size_t size, const char *name, mspace msp) { + seg->name = name; + seg->start = start; + seg->size = size; + seg->end = seg->start + seg->size; + seg->mspace = msp; + seg->parent = NULL; + seg->shadow_ratio = 0; + seg->shadow_offset = 0; +} + +/*! \brief Set a shadow memory segment + * + * \param seg - pointer to a segment to initialize + * \param parent - pointer to the segment ::seg tracks. Should be initialized + * \param ratio - ratio of shadow to application memory + * \param name - symbolic name of the segment + */ +static void set_shadow_segment(memory_segment *seg, memory_segment *parent, + size_t ratio, const char *name) { + seg->parent = parent; + seg->name = name; + seg->shadow_ratio = ratio; + seg->size = parent->size/seg->shadow_ratio; + seg->mspace = create_mspace(seg->size + SHADOW_SEGMENT_PADDING, 0); + seg->start = (uintptr_t)mspace_malloc(seg->mspace,1); + seg->end = seg->start + seg->size; + seg->shadow_offset = parent->start - seg->start; +} + +/*! \brief Initialize memory layout, i.e., determine bounds of program segments, + * allocate shadow memory spaces and compute offsets. This function populates + * global struct ::memory_layout holding that information with data. + Case of the stack. */ +static void init_shadow_layout_stack(int *argc_ref, char ***argv_ref) { + memory_partition *pstack = &mem_layout.stack; + set_application_segment(&pstack->application, get_stack_start(argc_ref, argv_ref), + get_stack_size(), "stack", NULL); + /* Changes of the ratio in the following will require changes in get_tls_start */ + set_shadow_segment(&pstack->primary, &pstack->application, 1, "stack_primary"); + set_shadow_segment(&pstack->secondary, &pstack->application, 1, "stack_secondary"); +#ifdef E_ACSL_TEMPORAL + set_shadow_segment(&pstack->temporal_primary, &pstack->application, 1, "temporal_stack_primary"); + set_shadow_segment(&pstack->temporal_secondary, &pstack->application, 1, "temporal_stack_secondary"); +#endif + + mem_layout.is_initialized = 1; +} + +/*! \brief Return start address of a program's TLS */ +static uintptr_t get_tls_start() { + size_t tls_size = get_tls_size(); + uintptr_t data = (uintptr_t)&id_tdata, + bss = (uintptr_t)&id_tbss; + /* It could happen that the shadow allocated before bss is too big. + Indeed allocating PGM_TLS_SIZE/2 could cause an overlap with the other + shadow segments AND heap.application (in case the latter is too big too). + In such cases, take the smallest available address (the max used +1). */ + uintptr_t tls_start_half = (data > bss ? bss : data) - tls_size/2; + memory_partition pheap = mem_layout.heap, + pglobal = mem_layout.global; + uintptr_t max_shadow = pheap.primary.end; + max_shadow = pheap.secondary.end > max_shadow ? + pheap.secondary.end : max_shadow; + max_shadow = pglobal.primary.end > max_shadow ? + pglobal.primary.end : max_shadow; + max_shadow = pglobal.secondary.end > max_shadow ? + pglobal.secondary.end : max_shadow; + max_shadow = pheap.application.end > max_shadow ? + pheap.application.end : max_shadow; + /* Shadow stacks are not yet allocated at his point since + init_shadow_layout_stack is called after + init_shadow_layout_heap_global_tls (for reasons related to memory + initialization in presence of things like GCC constructors). + We must leave sufficient space for them. */ + max_shadow = max_shadow + + 2*get_stack_size() + /* One for primary, one for secondary. + If ratio is changed in init_shadow_layout_stack + then update required here. + TODO: if stack too big ==> problem */ + 1; + return tls_start_half > max_shadow ? tls_start_half : max_shadow; +} + +/*! \brief Initialize memory layout, i.e., determine bounds of program segments, + * allocate shadow memory spaces and compute offsets. This function populates + * global struct ::memory_layout holding that information with data. + Case of the heap, globals and tls. */ +static void init_shadow_layout_heap_global_tls() { + memory_partition *pheap = &mem_layout.heap; + set_application_segment(&pheap->application, get_heap_start(), + get_heap_size(), "heap", mem_spaces.heap_mspace); + set_shadow_segment(&pheap->primary, &pheap->application, 1, "heap_primary"); + set_shadow_segment(&pheap->secondary, &pheap->application, 8, "heap_secondary"); +#ifdef E_ACSL_TEMPORAL + set_shadow_segment(&pheap->temporal_primary, &pheap->application, 1, "temporal_heap_primary"); + set_shadow_segment(&pheap->temporal_secondary, &pheap->application, 1, "temporal_heap_secondary"); +#endif + + memory_partition *pglobal = &mem_layout.global; + set_application_segment(&pglobal->application, get_global_start(), + get_global_size(), "global", NULL); + set_shadow_segment(&pglobal->primary, &pglobal->application, 1, "global_primary"); + set_shadow_segment(&pglobal->secondary, &pglobal->application, 1, "global_secondary"); +#ifdef E_ACSL_TEMPORAL + set_shadow_segment(&pglobal->temporal_primary, &pglobal->application, 1, "temporal_global_primary"); + set_shadow_segment(&pglobal->temporal_secondary, &pglobal->application, 1, "temporal_global_secondary"); +#endif + + memory_partition *ptls = &mem_layout.tls; + set_application_segment(&ptls->application, get_tls_start(), + get_tls_size(), "tls", NULL); + set_shadow_segment(&ptls->primary, &ptls->application, 1, "tls_primary"); + set_shadow_segment(&ptls->secondary, &ptls->application, 1, "tls_secondary"); +#ifdef E_ACSL_TEMPORAL + set_shadow_segment(&ptls->temporal_primary, &ptls->application, 1, "temporal_tls_primary"); + set_shadow_segment(&ptls->temporal_secondary, &ptls->application, 1, "temporal_tls_secondary"); +#endif + + mem_layout.is_initialized = 1; +} + +/*! \brief Deallocate shadow regions used by runtime analysis */ +static void clean_shadow_layout() { + if (mem_layout.is_initialized) { + int i; + for (i = 0; i < sizeof(mem_partitions)/sizeof(memory_partition*); i++) { + if (mem_partitions[i]->primary.mspace) + destroy_mspace(mem_partitions[i]->primary.mspace); + if (mem_partitions[i]->secondary.mspace) + destroy_mspace(mem_partitions[i]->secondary.mspace); + } + } +} +/* }}} */ + +/** Shadow access {{{ + * + * Shadow displacement offsets are stored using signed integers. + * Displacement offset between an application memory space Ma and a shadow + * memory space Ms is computed by [min(Ma) - min(Ms)], where min(Ma) and min(Ms) + * denote least addresses in application and shadow spaces Ma and Ms respectively. + * + * Correspondense between a shadow address S and an application address A + * using a displacement offset OFF is therefore as follows: + * OFF = A - S + * S = A - OFF + * A = S + OFF + * + * Conversions between application-space and shadow memory addresses + * are given by following macros. +*/ + +#define heap_primary_offset mem_layout.heap.primary.shadow_offset +#define heap_secondary_offset mem_layout.heap.secondary.shadow_offset +#define stack_primary_offset mem_layout.stack.primary.shadow_offset +#define stack_secondary_offset mem_layout.stack.secondary.shadow_offset +#define global_primary_offset mem_layout.global.primary.shadow_offset +#define global_secondary_offset mem_layout.global.secondary.shadow_offset +#define tls_primary_offset mem_layout.tls.primary.shadow_offset +#define tls_secondary_offset mem_layout.tls.secondary.shadow_offset + +/*! \brief Compute a shadow address using displacement offset + * @param _addr - an application space address + * @param _offset - a shadow displacement offset */ +#define SHADOW_ACCESS(_addr,_offset) \ + ((intptr_t)((intptr_t)_addr - (intptr_t)_offset)) + +/*! \brief Same as SHADOW_ACCESS but with an additional scale factor given via + * _scale argument. Scale factor describes ratio of application to shadow bytes, + * for instance if one bit shadow memory is used to track one byte of + * application memory then the scale factor is 8. + * Here, scale factor is the ration of application to shadow memory. */ +#define SCALED_SHADOW_ACCESS(_addr, _start, _offset, _scale) \ + (((uintptr_t)_start - _offset) + \ + ((uintptr_t)_addr - (uintptr_t)_start)/_scale) + +/*! \brief Convert a heap address into its shadow counterpart */ +#define HEAP_SHADOW(_addr) \ + SHADOW_ACCESS(_addr, heap_primary_offset) + +/*! \brief Convert a heap address into its init shadow counterpart */ +#define HEAP_INIT_SHADOW(_addr) \ + SCALED_SHADOW_ACCESS(_addr, \ + mem_layout.heap.application.start, \ + mem_layout.heap.secondary.shadow_offset, \ + mem_layout.heap.secondary.shadow_ratio) + +#define HEAP_START mem_layout.heap.application.start + +/*! \brief Convert a stack address into its primary shadow counterpart */ +#define PRIMARY_STACK_SHADOW(_addr) \ + SHADOW_ACCESS(_addr, stack_primary_offset) + +/*! \brief Convert a stack address into its secondary shadow counterpart */ +#define SECONDARY_STACK_SHADOW(_addr) \ + SHADOW_ACCESS(_addr, stack_secondary_offset) + +/*! \brief Convert a global address into its primary shadow counterpart */ +#define PRIMARY_GLOBAL_SHADOW(_addr) \ + SHADOW_ACCESS(_addr, global_primary_offset) + +/*! \brief Convert a global address into its secondary shadow counterpart */ +#define SECONDARY_GLOBAL_SHADOW(_addr) \ + SHADOW_ACCESS(_addr, global_secondary_offset) + +/*! \brief Convert a TLS address into its primary shadow counterpart */ +#define PRIMARY_TLS_SHADOW(_addr) \ + SHADOW_ACCESS(_addr, tls_primary_offset) + +/*! \brief Convert a TLS address into its secondary shadow counterpart */ +#define SECONDARY_TLS_SHADOW(_addr) \ + SHADOW_ACCESS(_addr, tls_secondary_offset) + +/* \brief Compute a primary or a secondary shadow address (based on the value of + * parameter `_region`) of an address tracked via an offset-based encoding. + * For an untracked address `0` is returned. */ +#define SHADOW_REGION_ADDRESS(_addr, _region) \ + (IS_ON_STACK(_addr) ? _region##_STACK_SHADOW(_addr) : \ + IS_ON_GLOBAL(_addr) ? _region##_GLOBAL_SHADOW(_addr) : \ + IS_ON_TLS(_addr) ? _region##_TLS_SHADOW(_addr) : 0) + +/*! \brief Primary shadow address of a non-dynamic region */ +#define PRIMARY_SHADOW(_addr) SHADOW_REGION_ADDRESS(_addr, PRIMARY) +/*! \brief Secondary shadow address of a non-dynamic region */ +#define SECONDARY_SHADOW(_addr) SHADOW_REGION_ADDRESS(_addr, SECONDARY) + +/* }}} */ + +/** Memory segment ranges {{{ */ +/*! \brief Evaluate to a true value if address _addr resides within a given + * memory segment. + * \param _addr - a memory address + * \param _seg - a memory segment (one of the structs within ::mem_layout) +*/ +#define IS_ON(_addr,_seg) ( \ + ((uintptr_t)_addr) >= _seg.start && \ + ((uintptr_t)_addr) <= _seg.end \ +) + +/*! \brief Evaluate to true if `_addr` is a heap address */ +#define IS_ON_HEAP(_addr) IS_ON(_addr, mem_layout.heap.application) + +/*! \brief Evaluate to true if `_addr` is a stack address */ +#define IS_ON_STACK(_addr) IS_ON(_addr, mem_layout.stack.application) + +/*! \brief Evaluate to true if `_addr` is a global address */ +#define IS_ON_GLOBAL(_addr) IS_ON(_addr, mem_layout.global.application) + +/*! \brief Evaluate to true if _addr is a TLS address */ +#define IS_ON_TLS(_addr) IS_ON(_addr, mem_layout.tls.application) + +/*! \brief Shortcut for evaluating an address via ::IS_ON_STACK, + * ::IS_ON_GLOBAL or ::IS_ON_TLS */ +#define IS_ON_STATIC(_addr) \ + (IS_ON_STACK(_addr) || IS_ON_GLOBAL(_addr) || IS_ON_TLS(_addr)) + +/*! \brief Evaluate to a true value if a given address belongs to tracked + * allocation (i.e., found within tls, stack, heap or globally) */ +#define IS_ON_VALID(_addr) \ + (IS_ON_STACK(_addr) || IS_ON_HEAP(_addr) || \ + IS_ON_GLOBAL(_addr) || IS_ON_TLS(_addr)) +/* }}} */ + +#ifdef E_ACSL_TEMPORAL /* {{{ */ +/*! \brief Convert a heap address into its shadow counterpart */ +#define TEMPORAL_HEAP_SHADOW(_addr) \ + SHADOW_ACCESS(_addr, mem_layout.heap.temporal_primary.shadow_offset) + +/*! \brief Convert a stack address into its primary temporal shadow counterpart */ +#define TEMPORAL_PRIMARY_STACK_SHADOW(_addr) \ + SHADOW_ACCESS(_addr, mem_layout.stack.temporal_primary.shadow_offset) + +/*! \brief Convert a stack address into its secondary temporal shadow counterpart */ +#define TEMPORAL_SECONDARY_STACK_SHADOW(_addr) \ + SHADOW_ACCESS(_addr, mem_layout.stack.temporal_secondary.shadow_offset) + +/*! \brief Convert a global address into its primary temporal shadow counterpart */ +#define TEMPORAL_PRIMARY_GLOBAL_SHADOW(_addr) \ + SHADOW_ACCESS(_addr, mem_layout.global.temporal_primary.shadow_offset) + +/*! \brief Convert a global address into its primary temporal shadow counterpart */ +#define TEMPORAL_SECONDARY_GLOBAL_SHADOW(_addr) \ + SHADOW_ACCESS(_addr, mem_layout.global.temporal_secondary.shadow_offset) + +/*! \brief Convert a TLS address into its primary temporal shadow counterpart */ +#define TEMPORAL_PRIMARY_TLS_SHADOW(_addr) \ + SHADOW_ACCESS(_addr, mem_layout.tls.temporal_primary.shadow_offset) + +/*! \brief Convert a TLS address into its secondary temporal shadow counterpart */ +#define TEMPORAL_SECONDARY_TLS_SHADOW(_addr) \ + SHADOW_ACCESS(_addr, mem_layout.tls.temporal_secondary.shadow_offset) + +/*! \brief Temporal primary shadow address of a non-dynamic region */ +#define TEMPORAL_PRIMARY_STATIC_SHADOW(_addr) \ + SHADOW_REGION_ADDRESS(_addr, TEMPORAL_PRIMARY) + +/*! \brief Temporal secondary shadow address of a non-dynamic region */ +#define TEMPORAL_SECONDARY_STATIC_SHADOW(_addr) \ + SHADOW_REGION_ADDRESS(_addr, TEMPORAL_SECONDARY) +#endif /* }}} */ diff --git a/src/plugins/e-acsl/src/analyses/exit_points.ml b/src/plugins/e-acsl/src/analyses/exit_points.ml new file mode 100644 index 0000000000000000000000000000000000000000..7df53439ef1ed31cdde557b02bc972eecd08de85 --- /dev/null +++ b/src/plugins/e-acsl/src/analyses/exit_points.ml @@ -0,0 +1,146 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C's E-ACSL plug-in. *) +(* *) +(* Copyright (C) 2012-2018 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +open Cil_types +open Cil_datatype + +module Build_env(X: sig type t end): sig + val add: stmt -> X.t -> unit + val find: stmt -> X.t (* may raise [Not_found] *) + val get_all: stmt -> X.t list + val is_empty: unit -> bool + val clear: unit -> unit +end = struct + + let tbl = Stmt.Hashtbl.create 17 + let add = Stmt.Hashtbl.add tbl + + let find stmt = Stmt.Hashtbl.find tbl stmt + let get_all stmt = try Stmt.Hashtbl.find_all tbl stmt with Not_found -> [] + let is_empty () = Stmt.Hashtbl.length tbl = 0 + let clear () = Stmt.Hashtbl.clear tbl + +end + +(* Mapping of statements to local variables available within that statement's + scope. The mappings of this structure are used to determine variables which + need to be removed before goto jumps. Generally, if some goto (with + scope variables are given by set G') jumps to a labeled statement with + scope variables given by set L', then the goto exists the scopes of + variables given via set G' \ L'. Consequently, if those variables are + tracked, they need to be removed from tracking. *) +module SLocals = Build_env(struct type t = Varinfo.Set.t end) + +(* Statement to statement mapping indicating source/destination of a jump. + For instance, break statements are mapped to switches or loops they jump + out from and goto statements are mapped to their labeled statements. Notably, + such information does not really be computed for gotos (since they already + capture references to labelled statements they jumps to). Nevertheless it is + done for consistency, so all required information is stored uniformly. *) +module Exits = Build_env(struct type t = stmt end) + +(* Map labelled statements back to gotos which lead to them *) +module LJumps = Build_env(struct type t = stmt end) + +let clear () = + SLocals.clear (); + Exits.clear (); + LJumps.clear () + +let is_empty () = + SLocals.is_empty () && Exits.is_empty () && LJumps.is_empty () + +let delete_vars stmt = + match stmt.skind with + | Goto _ | Break _ | Continue _ -> + (try Varinfo.Set.diff (SLocals.find stmt) (SLocals.find (Exits.find stmt)) + with Not_found -> Varinfo.Set.empty) + | _ -> + Varinfo.Set.empty + +let store_vars stmt = + let gotos = LJumps.get_all stmt in + List.fold_left + (fun acc goto -> + try + Varinfo.Set.union + acc + (Varinfo.Set.diff (SLocals.find stmt) (SLocals.find goto)) + with Not_found -> + assert false) + Varinfo.Set.empty + gotos + +let unify_sets = + List.fold_left (fun acc v -> Varinfo.Set.union v acc) Varinfo.Set.empty + +class jump_context = object (_) + inherit Visitor.frama_c_inplace + + val mutable locals = [] + (* Maintained list of local variables within the scope of a currently + visited statement. Variables within a single scope are given by a + single set *) + + val jumps = Stack.create () + (* Stack of entered switches and loops *) + + method !vblock blk = + (* Filter out variables which definitions appear later in the code *) + let vardefs = List.filter (fun vi -> not vi.vdefined) blk.blocals in + locals <- Varinfo.Set.of_list vardefs :: locals; + Cil.DoChildrenPost + (fun blk -> locals <- List.tl locals; blk) + + method !vstmt stmt = + let add_labels stmt = + match stmt.labels with + | [] -> () + | _ :: _ -> SLocals.add stmt (unify_sets locals) + in + match stmt.skind with + | Loop _ | Switch _ -> + SLocals.add stmt (unify_sets locals); + Stack.push stmt jumps; + Cil.DoChildrenPost (fun st -> ignore(Stack.pop jumps); st) + | Break _ | Continue _ -> + Exits.add stmt (Stack.top jumps); + SLocals.add stmt (unify_sets locals); + Cil.DoChildren + | Goto(sref, _) -> + SLocals.add stmt (unify_sets locals); + Exits.add stmt !sref; + LJumps.add !sref stmt; + Cil.DoChildren + | Instr(Local_init (vi, _, _)) -> + locals <- (Varinfo.Set.add vi (List.hd locals)) :: List.tl locals; + add_labels stmt; + Cil.DoChildren + | Instr _ | Return _ | If _ | Block _ | UnspecifiedSequence _ + | Throw _ | TryCatch _ | TryFinally _ | TryExcept _ -> + add_labels stmt; + Cil.DoChildren +end + +let generate fct = + assert (is_empty ()); + ignore (Cil.visitCilFunction (new jump_context :> Cil.cilVisitor) fct) diff --git a/src/plugins/e-acsl/src/analyses/exit_points.mli b/src/plugins/e-acsl/src/analyses/exit_points.mli new file mode 100644 index 0000000000000000000000000000000000000000..b130c98c686235f0223618a0bdc7e7f63ecc163d --- /dev/null +++ b/src/plugins/e-acsl/src/analyses/exit_points.mli @@ -0,0 +1,48 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C's E-ACSL plug-in. *) +(* *) +(* Copyright (C) 2012-2018 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(** E-ACSL tracks a local variable by injecting: + - a call to [__e_acsl_store_block] at the beginning of its scope, and + - a call to [__e_acsl_delete_block] at the end of the scope. + This is not always sufficient to track variables because execution + may exit a scope early (for instance via a goto or a break statement). + This module computes program points at which extra `delete_block` statements + need to be added to handle such early scope exits. *) + +open Cil_types +open Cil_datatype + +val generate: fundec -> unit +(** Visit a function and populate data structures used to compute exit points *) + +val clear: unit -> unit +(** Clear all gathered data *) + +val delete_vars: stmt -> Varinfo.Set.t +(** Given a statement which potentially leads to an early scope exit (such as + goto, break or continue) return the list of local variables which + need to be removed from tracking before that statement is executed. + Before calling this function [generate] need to be executed. *) + +val store_vars: stmt -> Varinfo.Set.t +(** Compute variables that should be re-recorded before a labelled statement to + which some goto jumps *) diff --git a/src/plugins/e-acsl/src/analyses/interval.ml b/src/plugins/e-acsl/src/analyses/interval.ml new file mode 100644 index 0000000000000000000000000000000000000000..948c0da9b9bbc2fb9db96b9fd8891029627a65c3 --- /dev/null +++ b/src/plugins/e-acsl/src/analyses/interval.ml @@ -0,0 +1,598 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C's E-ACSL plug-in. *) +(* *) +(* Copyright (C) 2012-2018 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +open Cil_types + +(* Implements Figure 3 of J. Signoles' JFLA'15 paper "Rester statique pour + devenir plus rapide, plus précis et plus mince". + Also implements a support for real numbers. *) + +(* ********************************************************************* *) +(* Basic datatypes and operations *) +(* ********************************************************************* *) + +type ival = + | Ival of Ival.t + | Float of fkind * float option (* a float constant, if any *) + | Rational + | Real + | Nan + +module D = + Datatype.Make_with_collections + (struct + type t = ival + let name = "E_ACSL.Interval.t" + let reprs = [ Float (FFloat, Some 0.); Rational; Real; Nan ] + include Datatype.Undefined + + let compare i1 i2 = + if i1 == i2 then 0 + else + match i1, i2 with + | Ival i1, Ival i2 -> + Ival.compare i1 i2 + | Float (k1, f1), Float (k2, f2) -> + (* faster to compare a kind than a float *) + let n = Transitioning.Stdlib.compare k1 k2 in + if n = 0 then Transitioning.Stdlib.compare f1 f2 else n + | Ival _, (Float _ | Rational | Real | Nan) + | Float _, (Rational | Real | Nan) + | Rational, (Real | Nan) + | Real, Nan -> + -1 + | Nan, (Ival _ | Float _ | Rational | Real) + | Real, (Ival _ | Float _ | Rational) + | Rational, (Ival _ | Float _) + | Float _, Ival _ -> + 1 + | Rational, Rational | Real, Real | Nan, Nan -> + assert false + + let equal = Datatype.from_compare + + let hash = function + | Ival i -> 7 * Ival.hash i + | Float(k, f) -> 17 * Hashtbl.hash f + 97 * Hashtbl.hash k + | Rational -> 787 + | Real -> 1011 + | Nan -> 1277 + + let pretty fmt = function + | Ival i -> Ival.pretty fmt i + | Float(_, Some f) -> Format.pp_print_float fmt f + | Float(FFloat, None) -> Format.pp_print_string fmt "float" + | Float(FDouble, None) -> Format.pp_print_string fmt "double" + | Float(FLongDouble, None) -> Format.pp_print_string fmt "long double" + | Rational -> Format.pp_print_string fmt "Rational" + | Real -> Format.pp_print_string fmt "Real" + | Nan -> Format.pp_print_string fmt "NaN" + + end) + +let is_included i1 i2 = match i1, i2 with + | Ival i1, Ival i2 -> Ival.is_included i1 i2 + | Float(k1, f1), Float(k2, f2) -> + Transitioning.Stdlib.compare k1 k2 <= 0 + && (match f1, f2 with + | None, None | Some _, None -> true + | None, Some _ -> false + | Some f1, Some f2 -> f1 = f2) + | (Ival _ | Float _ | Rational), (Rational | Real) + | Real, Real + | Nan, Nan -> + true + (* floats and integer are not comparable: *) + | Ival _, Float _ | Float _, Ival _ + (* nan is comparable to noone, but itself: *) + | (Ival _ | Float _ | Rational | Real), Nan + | Nan, (Ival _ | Float _ | Rational | Real) + (* cases for reals and rationals: *) + | Real, (Ival _ | Float _ | Rational) + | Rational, (Ival _ | Float _) -> + false + +let lift_unop f = function + | Ival iv -> Ival (f iv) + | Float _ -> + (* any unary operator over a float generates a rational + TODO: actually, certainly possible to generate a float *) + Rational + | Rational | Real | Nan as i -> + i + +let lift_binop ~safe_float f i1 i2 = match i1, i2 with + | Ival iv, i when Ival.is_bottom iv -> i + | i, Ival iv when Ival.is_bottom iv -> i + | Ival i1, Ival i2 -> + Ival (f i1 i2) + | Float(k1, _), Float(k2, _) when safe_float -> + let k = if Transitioning.Stdlib.compare k1 k2 >= 0 then k1 else k2 in + Float(k, None (* lost value, if any before *)) + | Ival iv, Float(k, _) + | Float(k, _), Ival iv -> + if safe_float + then + match Ival.min_and_max iv with + | None, None -> + (* unbounded integers *) + Rational + | Some min, Some max -> + (* if the interval of integers fits into the float types, then return + this float type; otherwise return Rational *) + (try + let to_float n = Int64.to_float (Integer.to_int64 n) in + let mini, maxi = to_float min, to_float max in + let minf, maxf = match k with + | FFloat -> + Floating_point.most_negative_single_precision_float, + Floating_point.max_single_precision_float + | FDouble -> + -. Transitioning.Float.max_float, + Transitioning.Float.max_float + | FLongDouble -> + raise Exit + in + if mini >= minf && maxi <= maxf then Float(k, None) else Rational + with Z.Overflow | Exit -> + Rational) + | None, Some _ | Some _, None -> + assert false + else + Rational (* sound over-approximation *) + | (Ival _ | Float _ | Rational), (Float _ | Rational) + | Rational, Ival _ -> + Rational + | (Ival _ | Float _ | Rational | Real), Real + | Real, (Ival _ | Float _ | Rational) -> + Real + | (Ival _ | Float _ | Rational | Real | Nan), Nan + | Nan, (Ival _ | Float _ | Rational | Real) -> + Nan + +let join = lift_binop ~safe_float:true Ival.join + +(* TODO: soundness of any downcast is not checked *) +let cast ~src ~dst = match src, dst with + | Ival i1, Ival i2 -> + Ival (Ival.meet i1 i2) + | _, Float(_, Some _) -> + assert false + | Rational, Real + | Float _, (Rational | Real) -> + src + | _, _ -> + (* No need to optimize the other cases: if someone writes a cast + (in particular, from integer to float/real or conversely), it is + certainly on purpose . *) + dst + +(* ********************************************************************* *) +(* constructors and destructors *) +(* ********************************************************************* *) + +let extract_ival = function + | Ival iv -> iv + | Float _ | Rational | Real | Nan -> assert false + +let bottom = Ival Ival.bottom +let top_ival = Ival (Ival.inject_range None None) +let singleton n = Ival (Ival.inject_singleton n) +let singleton_of_int n = singleton (Integer.of_int n) +let ival min max = Ival (Ival.inject_range (Some min) (Some max)) + +let interv_of_unknown_block = + (* since we have no idea of the size of this block, we take the largest + possible one which is unfortunately quite large *) + lazy (ival Integer.zero (Bit_utils.max_byte_address ())) + +(* ********************************************************************* *) +(* main algorithm *) +(* ********************************************************************* *) + +(* The boolean indicates whether we have real numbers *) +let rec interv_of_typ ty = match Cil.unrollType ty with + | TInt (k,_) as ty -> + let n = Cil.bitsSizeOf ty in + let l, u = + if Cil.isSigned k then Cil.min_signed_number n, Cil.max_signed_number n + else Integer.zero, Cil.max_unsigned_number n + in + ival l u + | TEnum(enuminfo, _) -> + interv_of_typ (TInt(enuminfo.ekind, [])) + | _ when Gmp_types.Z.is_t ty -> + top_ival + | TFloat (k, _) -> + Float(k, None) + | _ when Gmp_types.Q.is_t ty -> + Rational (* only rationals are implemented *) + | TVoid _ | TPtr _ | TArray _ | TFun _ | TComp _ | TBuiltin_va_list _ -> + Nan + | TNamed _ -> + assert false + +let interv_of_logic_typ = function + | Ctype ty -> interv_of_typ ty + | Linteger -> top_ival + | Lreal -> Real + | Ltype _ -> Error.not_yet "user-defined logic type" + | Lvar _ -> Error.not_yet "type variable" + | Larrow _ -> Nan + +let ikind_of_ival iv = + if Ival.is_bottom iv then IInt + else match Ival.min_and_max iv with + | Some l, Some u -> + let is_pos = Integer.ge l Integer.zero in + let lkind = Cil.intKindForValue l is_pos in + let ukind = Cil.intKindForValue u is_pos in + (* kind corresponding to the interval *) + let kind = if Cil.intTypeIncluded lkind ukind then ukind else lkind in + (* convert the kind to [IInt] whenever smaller. *) + if Cil.intTypeIncluded kind IInt then IInt else kind + | None, None -> raise Cil.Not_representable (* GMP *) + (* TODO: do not raise an exception, but returns a value instead *) + | None, Some _ | Some _, None -> + Kernel.fatal ~current:true "unexpected ival: %a" Ival.pretty iv + +(* function call profiles (intervals for their formal parameters) *) +module Profile = struct + include Datatype.List_with_collections + (D) + (struct + let module_name = "E_ACSL.Interval.Logic_function_env.Profile" + end) + let is_included p1 p2 = List.for_all2 is_included p1 p2 +end + +(* Imperative environments *) +module rec Env: sig + val clear: unit -> unit + val add: Cil_types.logic_var -> ival -> unit + val find: Cil_types.logic_var -> ival + val remove: Cil_types.logic_var -> unit + val replace: Cil_types.logic_var -> ival -> unit +end = struct + + open Cil_datatype + let tbl: ival Logic_var.Hashtbl.t = Logic_var.Hashtbl.create 7 + + (* TODO: when adding, also join with the old value (if any). Would certainly + be the correct way to handle a \let in a recursive logic functions (if the + \let body depends on one formal) *) + let add = Logic_var.Hashtbl.add tbl + let remove = Logic_var.Hashtbl.remove tbl + let replace = Logic_var.Hashtbl.replace tbl + let find = Logic_var.Hashtbl.find tbl + + let clear () = + Logic_var.Hashtbl.clear tbl; + Logic_function_env.clear () + +end + +(* Environment for handling logic functions *) +and Logic_function_env: sig + val widen: infer:(term -> ival) -> term -> ival -> bool * ival + val clear: unit -> unit +end = struct + + (* The environment associates to each term (denoting a logic function + application) a profile, i.e. the list of intervals for its formal + parameters. It helps to type these applications. + + For each pair of function name and profile, an interval containing the + result is also stored. It helps to generate the function definitions for + each logic function (for each function, one definition per profile) . *) + + module Terms = Hashtbl.Make + (struct + type t = term + let equal = (==) + let hash = Cil_datatype.Term.hash + end) + + module LF = + Datatype.Pair_with_collections + (Datatype.String) + (Profile) + (struct + let module_name = "E_ACSL.Interval.Logic_function_env.LF" + end) + + let terms: Profile.t Terms.t = Terms.create 7 + let named_profiles = LF.Hashtbl.create 7 + + let clear () = + Terms.clear terms; + LF.Hashtbl.clear named_profiles + + let interv_of_typ_containing_interv = function + | Float _ | Rational | Real | Nan as x -> + x + | Ival i -> + try + let kind = ikind_of_ival i in + interv_of_typ (TInt(kind, [])) + with Cil.Not_representable -> + top_ival + + let rec map3 f l1 l2 l3 = match l1, l2, l3 with + | [], [], [] -> [] + | x1 :: l1, x2 :: l2, x3 :: l3 -> f x1 x2 x3 :: map3 f l1 l2 l3 + | _, _, _ -> invalid_arg "E_ACSL.Interval.map3" + + let extract_profile ~infer old_profile t = match t.term_node with + | Tapp(li, _, args) -> + let old_profile = match old_profile with + | None -> List.map (fun _ -> bottom) li.l_profile + | Some p -> p + in + li.l_var_info.lv_name, + map3 + (fun param old_i arg -> + let i = infer arg in + (* over-approximation of the interval to reach the fixpoint + faster, and to generate fewer specialized functions *) + let larger_i = interv_of_typ_containing_interv i in + (* merge the old profile and the new one *) + let new_i = join larger_i old_i in + Env.add param new_i; + new_i) + li.l_profile + old_profile + args + | _ -> + assert false + + let widen_one_callsite ~infer old_profile t i = + let (_, p as named_p) = extract_profile ~infer old_profile t in + try + let old_i = LF.Hashtbl.find named_profiles named_p in + if is_included i old_i then true, p, old_i (* fixpoint reached *) + else begin + let j = join i old_i in + LF.Hashtbl.replace named_profiles named_p j; + false, p, j + end + with Not_found -> + LF.Hashtbl.add named_profiles named_p i; + false, p, i + + let widen ~infer t i = + try + let old_p = Terms.find terms t in + let is_included, new_p, i = widen_one_callsite ~infer (Some old_p) t i in + if Profile.is_included new_p old_p then is_included, i + else begin + Terms.replace terms t new_p; + false, i + end + with Not_found -> + let is_included, p, i = widen_one_callsite ~infer None t i in + Terms.add terms t p; + is_included, i + +end + +(* ********************************************************************* *) +(* Main algorithm *) +(* ********************************************************************* *) + +let infer_sizeof ty = + try singleton_of_int (Cil.bytesSizeOf ty) + with Cil.SizeOfError _ -> interv_of_typ Cil.theMachine.Cil.typeOfSizeOf + +let infer_alignof ty = singleton_of_int (Cil.bytesAlignOf ty) + +let rec infer t = + let get_cty t = match t.term_type with Ctype ty -> ty | _ -> assert false in + match t.term_node with + | TConst (Integer (n, _)) -> singleton n + | TConst (LChr c) -> + let n = Cil.charConstToInt c in + singleton n + | TConst (LEnum enumitem) -> + let rec find_idx n = function + | [] -> assert false + | ei :: l -> if ei == enumitem then n else find_idx (n + 1) l + in + let n = Integer.of_int (find_idx 0 enumitem.eihost.eitems) in + singleton n + | TLval lv -> infer_term_lval lv + | TSizeOf ty -> infer_sizeof ty + | TSizeOfE t -> infer_sizeof (get_cty t) + | TSizeOfStr str -> singleton_of_int (String.length str + 1 (* '\0' *)) + | TAlignOf ty -> infer_alignof ty + | TAlignOfE t -> infer_alignof (get_cty t) + + | TUnOp (Neg, t) -> + let i = infer t in + lift_unop Ival.neg_int i + | TUnOp (BNot, t) -> + let i = infer t in + lift_unop Ival.bitwise_signed_not i + | TUnOp (LNot, _) + | TBinOp ((Lt | Gt | Le | Ge | Eq | Ne | LAnd | LOr), _, _) -> + Ival Ival.zero_or_one + + | TBinOp (PlusA, t1, t2) -> + let i1 = infer t1 in + let i2 = infer t2 in + lift_binop ~safe_float:false Ival.add_int i1 i2 + | TBinOp (MinusA, t1, t2) -> + let i1 = infer t1 in + let i2 = infer t2 in + lift_binop ~safe_float:false Ival.sub_int i1 i2 + | TBinOp (Mult, t1, t2) -> + let i1 = infer t1 in + let i2 = infer t2 in + lift_binop ~safe_float:false Ival.mul i1 i2 + | TBinOp (Div, t1, t2) -> + let i1 = infer t1 in + let i2 = infer t2 in + lift_binop ~safe_float:false Ival.div i1 i2 + | TBinOp (Mod, t1, t2) -> + let i1 = infer t1 in + let i2 = infer t2 in + lift_binop ~safe_float:false Ival.c_rem i1 i2 + | TBinOp (Shiftlt , _, _) -> Error.not_yet "right shift" + | TBinOp (Shiftrt , _, _) -> Error.not_yet "left shift" + | TBinOp (BAnd, _, _) -> Error.not_yet "bitwise and" + | TBinOp (BXor, t1, t2) -> + let i1 = infer t1 in + let i2 = infer t2 in + lift_binop ~safe_float:false Ival.bitwise_xor i1 i2 + | TBinOp (BOr, t1, t2) -> + let i1 = infer t1 in + let i2 = infer t2 in + lift_binop ~safe_float:false Ival.bitwise_or i1 i2 + | TCastE (ty, t) -> + let src = infer t in + let dst = interv_of_typ ty in + cast ~src ~dst + | Tif (_, t2, t3) -> + let i2 = infer t2 in + let i3 = infer t3 in + join i2 i3 + | Tat (t, _) -> + infer t + | TBinOp (MinusPP, t, _) -> + (match Cil.unrollType (get_cty t) with + | TArray(_, _, { scache = Computed n (* size in bits *) }, _) -> + (* the second argument must be in the same block than [t]. Consequently + the result of the difference belongs to [0; \block_length(t)] *) + let nb_bytes = if n mod 8 = 0 then n / 8 else n / 8 + 1 in + ival Integer.zero (Integer.of_int nb_bytes) + | TArray _ | TPtr _ -> + Lazy.force interv_of_unknown_block + | _ -> assert false) + | Tblock_length (_, t) + | Toffset(_, t) -> + (match Cil.unrollType (get_cty t) with + | TArray(_, _, { scache = Computed n (* size in bits *) }, _) -> + let nb_bytes = if n mod 8 = 0 then n / 8 else n / 8 + 1 in + singleton_of_int nb_bytes + | TArray _ | TPtr _ -> Lazy.force interv_of_unknown_block + | _ -> assert false) + | Tnull -> singleton_of_int 0 + | TLogic_coerce (_, t) -> infer t + + | Tapp (li, _, _args) -> + (match li.l_body with + | LBpred _ -> + Ival Ival.zero_or_one + | LBterm t' -> + let rec fixpoint i = + let is_included, new_i = + Logic_function_env.widen ~infer t i + in + if is_included then begin + List.iter (fun lv -> Env.remove lv) li.l_profile; + new_i + end else + let i = infer t' in + List.iter (fun lv -> Env.remove lv) li.l_profile; + fixpoint i + in + fixpoint bottom + | LBnone + | LBreads _ -> + (match li.l_type with + | None -> assert false + | Some ret_type -> interv_of_logic_typ ret_type) + | LBinductive _ -> + Error.not_yet "logic functions inductively defined") + + | Tunion _ -> Error.not_yet "tset union" + | Tinter _ -> Error.not_yet "tset intersection" + | Tcomprehension (_,_,_) -> Error.not_yet "tset comprehension" + | Trange(Some n1, Some n2) -> + let i1 = infer n1 in + let i2 = infer n2 in + join i1 i2 + | Trange(None, _) | Trange(_, None) -> + Options.abort "unbounded ranges are not part of E-ACSl" + + | Tlet (li, t) -> + let li_t = Misc.term_of_li li in + let li_v = li.l_var_info in + let i1 = infer li_t in + Env.add li_v i1; + let i2 = infer t in + Env.remove li_v; + i2 + | TConst (LReal lr) -> + if lr.r_lower = lr.r_upper then Float(FDouble, Some lr.r_nearest) + else Rational + | TConst (LStr _ | LWStr _) + | TBinOp (PlusPI,_,_) + | TBinOp (IndexPI,_,_) + | TBinOp (MinusPI,_,_) + | TAddrOf _ + | TStartOf _ + | Tlambda (_,_) + | TDataCons (_,_) + | Tbase_addr (_,_) + | TUpdate (_,_,_) + | Ttypeof _ + | Ttype _ + | Tempty_set -> + Nan + +and infer_term_lval (host, offset as tlv) = + match offset with + | TNoOffset -> infer_term_host host + | _ -> + let ty = Logic_utils.logicCType (Cil.typeOfTermLval tlv) in + interv_of_typ ty + +and infer_term_host thost = + match thost with + | TVar v -> + (try Env.find v with Not_found -> + match v.lv_type with + | Linteger -> top_ival + | Ctype (TFloat(fk, _)) -> Float(fk, None) + | Lreal -> Real + | Ctype _ -> interv_of_typ (Logic_utils.logicCType v.lv_type) + | Ltype _ | Lvar _ | Larrow _ -> Options.fatal "unexpected logic type") + | TResult ty -> + interv_of_typ ty + | TMem t -> + let ty = Logic_utils.logicCType t.term_type in + match Cil.unrollType ty with + | TPtr(ty, _) | TArray(ty, _, _, _) -> + interv_of_typ ty + | _ -> + Options.fatal "unexpected type %a for term %a" + Printer.pp_typ ty + Printer.pp_term t + +include D + +(* +Local Variables: +compile-command: "make -C ../.." +End: + *) diff --git a/src/plugins/e-acsl/src/analyses/interval.mli b/src/plugins/e-acsl/src/analyses/interval.mli new file mode 100644 index 0000000000000000000000000000000000000000..332ba399ba8394565721ac409b3bc700977160da --- /dev/null +++ b/src/plugins/e-acsl/src/analyses/interval.mli @@ -0,0 +1,109 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C's E-ACSL plug-in. *) +(* *) +(* Copyright (C) 2012-2018 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(** Interval inference for terms. + + Compute the smallest interval that contains all the possible values of a + given integer term. The interval of C variables is directly inferred from + their C type. The interval of logic variables must be registered from + outside before computing the interval of a term containing such variables + (see module {!Interval.Env}). + + It implements Figure 3 of J. Signoles' JFLA'15 paper "Rester statique pour + devenir plus rapide, plus précis et plus mince". + Also implements a partial support for real numbers. + + Example: consider a variable [x] of type [int] on a (strange) architecture + in which values of type [int] belongs to the interval \[-128;127\] and a + logic variable [y] which was registered in the environment with an interval + \[-32;31\]. Then here are the intervals computed from the term + [1+(x+1)/(y-64)]: + 1. x in \[128;127\]; + 2. x+1 in \[129;128\]; + 3. y in \[-32;31\]; + 4. y-64 in \[-96;-33\]; + 5. (x+1)/(y-64) in \[-3;3\]; + 6. 1+(x+1)/(y-64) in \[-2;4\] + + Note: this is a partial wrapper on top of [Ival.t], to which most + functions are delegated. *) + +(* ************************************************************************** *) +(** {3 Useful operations on intervals} *) +(* ************************************************************************** *) + +type ival = + | Ival of Ival.t + | Float of Cil_types.fkind * float option + | Rational + | Real + | Nan + +include Datatype.S_with_collections with type t = ival + +val is_included: t -> t -> bool +val join: t -> t -> t + +val top_ival: t +val ival: Integer.t -> Integer.t -> t + +(** assume [Ival _] as argument *) +val extract_ival: t -> Ival.t + +val ikind_of_ival: Ival.t -> Cil_types.ikind +(** @return the smallest ikind that contains the given interval. + @raise Cil.Not_representable if the given interval does not fit into any C + integral type. *) + +val interv_of_typ: Cil_types.typ -> t +(** @return the smallest interval which contains the given C type. + @raise Is_a_real if the given type is a float type. + @raise Not_a_number if the given type does not represent any number. *) + +(* ************************************************************************** *) +(** {3 Environment for interval computations} *) +(* ************************************************************************** *) + +(** Environment which maps logic variables to intervals. This environment must + be extended from outside. *) +module Env: sig + val clear: unit -> unit + val add: Cil_types.logic_var -> t -> unit + val remove: Cil_types.logic_var -> unit + val replace: Cil_types.logic_var -> t -> unit +end + +(* ************************************************************************** *) +(** {3 Inference system} *) +(* ************************************************************************** *) + +val infer: Cil_types.term -> t +(** [infer t] infers the smallest possible integer interval which the values + of the term can fit in. + @raise Is_a_real if the term is either a float or a real. + @raise Not_a_number if the term does not represent any number. *) + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff --git a/src/plugins/e-acsl/src/analyses/literal_strings.ml b/src/plugins/e-acsl/src/analyses/literal_strings.ml new file mode 100644 index 0000000000000000000000000000000000000000..77b1cdcfcc41022856ddb9ae933f24e52f3065d4 --- /dev/null +++ b/src/plugins/e-acsl/src/analyses/literal_strings.ml @@ -0,0 +1,41 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C's E-ACSL plug-in. *) +(* *) +(* Copyright (C) 2012-2018 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +open Cil_types + +let strings + : varinfo Datatype.String.Hashtbl.t + = Datatype.String.Hashtbl.create 16 + +let reset () = Datatype.String.Hashtbl.clear strings + +let is_empty () = Datatype.String.Hashtbl.length strings = 0 + +let add = Datatype.String.Hashtbl.add strings +let find = Datatype.String.Hashtbl.find strings +let fold f = Datatype.String.Hashtbl.fold_sorted f strings + +(* +Local Variables: +compile-command: "make" +End: +*) diff --git a/src/plugins/e-acsl/src/analyses/literal_strings.mli b/src/plugins/e-acsl/src/analyses/literal_strings.mli new file mode 100644 index 0000000000000000000000000000000000000000..d73cc6e2f14f69faf5b96122d86cc05dc2788ad5 --- /dev/null +++ b/src/plugins/e-acsl/src/analyses/literal_strings.mli @@ -0,0 +1,41 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C's E-ACSL plug-in. *) +(* *) +(* Copyright (C) 2012-2018 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(** Associate literal strings to fresh varinfo. *) + +open Cil_types + +val reset: unit -> unit +(** Must be called to redo the analysis *) + +val is_empty: unit -> bool + +val add: string -> varinfo -> unit +val find: string -> varinfo + +val fold: (string -> varinfo -> 'a -> 'a) -> 'a -> 'a + +(* +Local Variables: +compile-command: "make" +End: +*) diff --git a/src/plugins/e-acsl/src/analyses/lscope.ml b/src/plugins/e-acsl/src/analyses/lscope.ml new file mode 100644 index 0000000000000000000000000000000000000000..fd040aae8a3430210bdb0af5f5653736be6f622a --- /dev/null +++ b/src/plugins/e-acsl/src/analyses/lscope.ml @@ -0,0 +1,64 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C's E-ACSL plug-in. *) +(* *) +(* Copyright (C) 2012-2018 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +open Cil_types + +type lscope_var = + | Lvs_let of logic_var * term + | Lvs_quantif of term * relation * logic_var * relation * term + | Lvs_formal of logic_var * logic_info + | Lvs_global of logic_var * term + +type t = lscope_var list +(* The logic scope is usually small, so a list is fine instead of a Map *) + +let empty = [] + +let is_empty = function [] -> true | _ :: _ -> false + +let add lscope_var t = lscope_var :: t + +let get_all t = List.rev t + +let exists lv t = + let is_lv = function + | Lvs_let(lv', _) | Lvs_quantif(_, _, lv', _, _) | Lvs_formal(lv', _) + | Lvs_global(lv', _) -> + Cil_datatype.Logic_var.equal lv lv' + in + List.exists is_lv t + +exception Lscope_used +let is_used lscope pot = + let o = object inherit Visitor.frama_c_inplace + method !vlogic_var_use lv = match lv.lv_origin with + | Some _ -> Cil.SkipChildren + | None -> if exists lv lscope then raise Lscope_used else Cil.SkipChildren + end + in + try + (match pot with + | Misc.PoT_pred p -> ignore (Visitor.visitFramacPredicate o p) + | Misc.PoT_term t -> ignore (Visitor.visitFramacTerm o t)); + false + with Lscope_used -> + true \ No newline at end of file diff --git a/src/plugins/e-acsl/src/analyses/lscope.mli b/src/plugins/e-acsl/src/analyses/lscope.mli new file mode 100644 index 0000000000000000000000000000000000000000..2583667f4eeb846419475221ac92984a0a1854f7 --- /dev/null +++ b/src/plugins/e-acsl/src/analyses/lscope.mli @@ -0,0 +1,53 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C's E-ACSL plug-in. *) +(* *) +(* Copyright (C) 2012-2018 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +open Cil_types + +(* Handle the logic scope of a term. + We define the logic scope of a term [t] to be the set of PURELY logic + variables that are visible by [t]. *) + +type lscope_var = + | Lvs_let of logic_var * term (* the expression to which the lv is binded *) + | Lvs_quantif of term * relation * logic_var * relation * term + | Lvs_formal of logic_var * logic_info (* the logic definition *) + | Lvs_global of logic_var * term (* same as Lvs_let *) + +type t + +val empty: t +(* Create an empty logic scope. *) + +val is_empty: t -> bool +(* Check whether the given logic scope is empty. *) + +val add: lscope_var -> t -> t +(* Return a new logic scope in which the given [lscope_var] has been added. *) + +val get_all: t -> lscope_var list +(* Return the list of [lscope_var] of the given logic scope. + The first element is the first [lscope_var] that was added to [t], the + second element is the second [lscope_var] that was added to [t], an so on. *) + +val is_used: t -> Misc.pred_or_term -> bool +(* [is_used lscope pot] returns [true] iff [pot] uses a variable from + [lscope]. *) \ No newline at end of file diff --git a/src/plugins/e-acsl/src/analyses/mmodel_analysis.ml b/src/plugins/e-acsl/src/analyses/mmodel_analysis.ml new file mode 100644 index 0000000000000000000000000000000000000000..6bdbcaf8c8e2c7307ea9d75243264785d67521b3 --- /dev/null +++ b/src/plugins/e-acsl/src/analyses/mmodel_analysis.ml @@ -0,0 +1,815 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C's E-ACSL plug-in. *) +(* *) +(* Copyright (C) 2012-2018 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +open Cil_types +open Cil_datatype + +module Dataflow = Dataflow2 + +let must_never_monitor vi = + (* E-ACSL, please do not monitor yourself! *) + Functions.RTL.is_rtl_name vi.vname + || + (* 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 + left-values must be tracked by the memory model library *) +(* ********************************************************************** *) + +let dkey = Options.dkey_analysis +module Env: sig + val has_heap_allocations: unit -> bool + val check_heap_allocations: kernel_function -> unit + val default_varinfos: Varinfo.Hptset.t option -> Varinfo.Hptset.t + val apply: (kernel_function -> 'a) -> kernel_function -> 'a + val clear: unit -> unit + val add: kernel_function -> Varinfo.Hptset.t option Stmt.Hashtbl.t -> unit + val add_init: kernel_function -> Varinfo.Hptset.t option -> unit + val mem_init: kernel_function -> Varinfo.Hptset.t option -> bool + val find: kernel_function -> Varinfo.Hptset.t option Stmt.Hashtbl.t + module StartData: + Dataflow.StmtStartData with type data = Varinfo.Hptset.t option + val is_consolidated: unit -> bool + val consolidate: Varinfo.Hptset.t -> unit + val consolidated_mem: varinfo -> bool + val is_empty: unit -> bool +end = struct + + let heap_allocation_ref = ref false + let has_heap_allocations () = !heap_allocation_ref + let check_heap_allocations kf = + (* a function with no definition potentially allocates memory *) + heap_allocation_ref := + !heap_allocation_ref || not (Kernel_function.is_definition kf) + + let current_kf = ref None + let default_varinfos = function None -> Varinfo.Hptset.empty | Some s -> s + + let apply f kf = + let old = !current_kf in + current_kf := Some kf; + let res = f kf in + current_kf := old; + res + + let tbl = Kernel_function.Hashtbl.create 7 + let add = Kernel_function.Hashtbl.add tbl + let find = Kernel_function.Hashtbl.find tbl + + module S = Set.Make(Datatype.Option(Varinfo.Hptset)) + + let tbl_init = Kernel_function.Hashtbl.create 7 + let add_init kf init = + let set = + try Kernel_function.Hashtbl.find tbl_init kf + with Not_found -> S.empty + in + let set = S.add init set in + Kernel_function.Hashtbl.replace tbl_init kf set + + let mem_init kf init = + try + let set = Kernel_function.Hashtbl.find tbl_init kf in + S.mem init set + with Not_found -> + false + + module StartData = struct + type data = Varinfo.Hptset.t option + let apply f = + try + let kf = Extlib.opt_conv (Kernel_function.dummy()) !current_kf in + let h = Kernel_function.Hashtbl.find tbl kf in + f h + with Not_found -> + assert false + let clear () = apply Stmt.Hashtbl.clear + let mem k = apply Stmt.Hashtbl.mem k + let find k = apply Stmt.Hashtbl.find k + let replace k v = apply Stmt.Hashtbl.replace k v + let add k v = apply Stmt.Hashtbl.add k v + let iter f = apply (Stmt.Hashtbl.iter f) + let length () = apply Stmt.Hashtbl.length + end + + (* TODO: instead of this costly consolidation, why do not take the state of + the entry point of the function? *) + + let consolidated_set = ref Varinfo.Hptset.empty + let is_consolidated_ref = ref false + + let consolidate set = + let set = Varinfo.Hptset.union set !consolidated_set in + consolidated_set := set + + let consolidated_mem v = + is_consolidated_ref := true; + Varinfo.Hptset.mem v !consolidated_set + + let is_consolidated () = !is_consolidated_ref + + let is_empty () = + try + Kernel_function.Hashtbl.iter + (fun _ h -> + Stmt.Hashtbl.iter + (fun _ set -> match set with + | None -> () + | Some s -> if not (Varinfo.Hptset.is_empty s) then raise Exit) + h) + tbl; + true + with Exit -> + false + + let clear () = + Kernel_function.Hashtbl.clear tbl; + consolidated_set := Varinfo.Hptset.empty; + is_consolidated_ref := false; + heap_allocation_ref := false + +end + +let reset () = + Options.feedback ~dkey ~level:2 "clearing environment."; + Env.clear () + +module rec Transfer + : Dataflow.BackwardsTransfer with type t = Varinfo.Hptset.t option + = struct + + let name = "E_ACSL.Pre_analysis" + + let debug = false + + type t = Varinfo.Hptset.t option + + module StmtStartData = Env.StartData + + let pretty fmt state = match state with + | None -> Format.fprintf fmt "None" + | Some s -> Format.fprintf fmt "%a" Varinfo.Hptset.pretty s + + (** The data at function exit. Used for statements with no successors. + This is usually bottom, since we'll also use doStmt on Return + statements. *) + let funcExitData = None + + (** When the analysis reaches the start of a block, combine the old data with + the one we have just computed. Return None if the combination is the same + as the old data, otherwise return the combination. In the latter case, the + predecessors of the statement are put on the working list. *) + let combineStmtStartData stmt ~old state = match stmt.skind, old, state with + | _, _, None -> assert false + | _, None, Some _ -> Some state (* [old] already included in [state] *) + | Return _, Some old, Some new_ -> + Some (Some (Varinfo.Hptset.union old new_)) + | _, Some old, Some new_ -> + if Varinfo.Hptset.equal old new_ then + None + else + Some (Some (Varinfo.Hptset.union old new_)) + + (** Take the data from two successors and combine it *) + let combineSuccessors s1 s2 = + Some + (Varinfo.Hptset.union (Env.default_varinfos s1) (Env.default_varinfos s2)) + + let is_ptr_or_array ty = Cil.isPointerType ty || Cil.isArrayType ty + + let is_ptr_or_array_exp e = + let ty = Cil.typeOf e in + is_ptr_or_array ty + + let may_alias li = match li.l_var_info.lv_type with + | Ctype ty -> is_ptr_or_array ty + | Linteger | Lreal -> false + | Ltype _ -> Error.not_yet "user defined type" + | Lvar _ -> Error.not_yet "named type" + | Larrow _ -> Error.not_yet "functional type" + + let rec base_addr_node = function + | Lval lv | AddrOf lv | StartOf lv -> + (match lv with + | Var vi, _ -> Some vi + | Mem e, _ -> base_addr e) + | BinOp((PlusPI | IndexPI | MinusPI), e1, e2, _) -> + if is_ptr_or_array_exp e1 then base_addr e1 + else begin + assert (is_ptr_or_array_exp e2); + base_addr e2 + end + | Info(e, _) | CastE(_, e) -> base_addr e + | BinOp((MinusPP | PlusA | MinusA | Mult | Div | Mod |Shiftlt | Shiftrt + | Lt | Gt | Le | Ge | Eq | Ne | BAnd | BXor | BOr | LAnd | LOr), + _, _, _) + | UnOp _ | Const _ | SizeOf _ | SizeOfE _ | SizeOfStr _ | AlignOf _ + | AlignOfE _ -> + None + + and base_addr e = base_addr_node e.enode + + let extend_to_expr always state lhost e = + let add_vi state vi = + if is_ptr_or_array_exp e && (always || Varinfo.Hptset.mem vi state) + then begin + match base_addr e with + | None -> state + | Some vi_e -> + if must_never_monitor vi then state + else begin + Options.feedback ~level:4 ~dkey + "monitoring %a from %a." + Printer.pp_varinfo vi_e + Printer.pp_lval (lhost, NoOffset); + Varinfo.Hptset.add vi_e state + end + end else + state + in + match lhost with + | Var vi -> add_vi state vi + | Mem e -> + match base_addr e with + | None -> state + | Some vi -> add_vi state vi + + (* if [e] contains a pointer left-value, then also monitor the host *) + let rec extend_from_addr state lv e = match e.enode with + | Lval(lhost, _) -> + if is_ptr_or_array_exp e then + extend_to_expr true state lhost (Cil.new_exp ~loc:e.eloc (Lval lv)), + true + else + state, false + | AddrOf(lhost, _) -> + extend_to_expr true state lhost (Cil.new_exp ~loc:e.eloc (Lval lv)), + true + | BinOp((PlusPI | IndexPI | MinusPI), e1, e2, _) -> + if is_ptr_or_array_exp e1 then extend_from_addr state lv e1 + else begin + assert (is_ptr_or_array_exp e2); + extend_from_addr state lv e2 + end + | CastE(_, e) | Info(e, _) -> extend_from_addr state lv e + | _ -> state, false + + let handle_assignment state (lhost, _ as lv) e = + (* if [e] is a pointer left-value, then also monitor the host *) + let state, always = extend_from_addr state lv e in + extend_to_expr always state lhost e + + let rec register_term_lval kf varinfos (thost, _) = + let add_vi kf vi = + Options.feedback ~level:4 ~dkey "monitoring %a from annotation of %a." + Printer.pp_varinfo vi + Kernel_function.pretty kf; + Varinfo.Hptset.add vi varinfos + in + match thost with + | TVar { lv_origin = None } -> varinfos + | TVar { lv_origin = Some vi } -> add_vi kf vi + | TResult _ -> add_vi kf (Misc.result_vi kf) + | TMem t -> register_term kf varinfos t + + and register_term kf varinfos term = match term.term_node with + | TLval tlv | TAddrOf tlv | TStartOf tlv -> + register_term_lval kf varinfos tlv + | TCastE(_, t) | Tat(t, _) -> + register_term kf varinfos t + | Tlet(li, t) -> + if may_alias li then Error.not_yet "let-binding on array or pointer" + else begin + let varinfos = register_term kf varinfos t in + register_body kf varinfos li.l_body + end + | Tif(_, t1, t2) -> + let varinfos = register_term kf varinfos t1 in + register_term kf varinfos t2 + | TBinOp((PlusPI | IndexPI | MinusPI), t1, t2) -> + (match t1.term_type with + | Ctype ty when is_ptr_or_array ty -> register_term kf varinfos t1 + | _ -> + match t2.term_type with + | Ctype ty when is_ptr_or_array ty -> register_term kf varinfos t2 + | _ -> + if Misc.is_set_of_ptr_or_array t1.term_type || + Misc.is_set_of_ptr_or_array t2.term_type then + (* Occurs for example from: + \valid(&multi_dynamic[2..4][1..7]) + where multi_dynamic has been dynamically allocated *) + let varinfos = register_term kf varinfos t1 in + register_term kf varinfos t2 + else + assert false) + | TConst _ | TSizeOf _ | TSizeOfE _ | TSizeOfStr _ | TAlignOf _ + | TAlignOfE _ | Tnull | Ttype _ | TUnOp _ | TBinOp _ -> + varinfos + | Tlambda(_, _) -> Error.not_yet "lambda function" + | Tapp(_, _, _) -> Error.not_yet "function application" + | TDataCons _ -> Error.not_yet "data constructor" + | Tbase_addr _ -> Error.not_yet "\\base_addr" + | Toffset _ -> Error.not_yet "\\offset" + | Tblock_length _ -> Error.not_yet "\\block_length" + | TLogic_coerce(_, t) -> register_term kf varinfos t + | TUpdate _ -> Error.not_yet "functional update" + | Ttypeof _ -> Error.not_yet "typeof" + | Tempty_set -> Error.not_yet "empty set" + | Tunion _ -> Error.not_yet "set union" + | Tinter _ -> Error.not_yet "set intersection" + | Tcomprehension _ -> Error.not_yet "set comprehension" + | Trange(Some t1, Some t2) -> + let varinfos = register_term kf varinfos t1 in + register_term kf varinfos t2 + | Trange(None, _) | Trange(_, None) -> + Options.abort "unbounded ranges are not part of E-ACSL" + + and register_body kf varinfos = function + | LBnone | LBreads _ -> varinfos + | LBterm t -> register_term kf varinfos t + | LBpred _ -> Options.fatal "unexpected predicate" + | LBinductive _ -> Error.not_yet "inductive definitions" + + let register_object kf state_ref = object + inherit Visitor.frama_c_inplace + method !vpredicate_node = function + | Pvalid(_, t) | Pvalid_read(_, t) | Pvalid_function t + | Pinitialized(_, t) | Pfreeable(_, t) -> + (* Options.feedback "REGISTER %a" Cil.d_term t;*) + state_ref := register_term kf !state_ref t; + Cil.DoChildren + | Pallocable _ -> Error.not_yet "\\allocable" + | Pfresh _ -> Error.not_yet "\\fresh" + | Pseparated _ -> Error.not_yet "\\separated" + | Pdangling _ -> Error.not_yet "\\dangling" + | Ptrue | Pfalse | Papp _ | Prel _ + | Pand _ | Por _ | Pxor _ | Pimplies _ | Piff _ | Pnot _ | Pif _ + | Pforall _ | Pexists _ | Pat _ -> + Cil.DoChildren + | Plet(li, _) -> + if may_alias li then Error.not_yet "let-binding on array or pointer" + else begin + state_ref := register_term kf !state_ref (Misc.term_of_li li); + Cil.DoChildren + end + method !vterm term = match term.term_node with + | Tbase_addr(_, t) | Toffset(_, t) | Tblock_length(_, t) | Tlet(_, t) -> + state_ref := register_term kf !state_ref t; + Cil.DoChildren + | TConst _ | TSizeOf _ | TSizeOfStr _ | TAlignOf _ | Tnull | Ttype _ + | Tempty_set -> + (* no left-value inside inside: skip for efficiency *) + Cil.SkipChildren + | TUnOp _ | TBinOp _ | Ttypeof _ | TSizeOfE _ + | TLval _ | TAlignOfE _ | TCastE _ | TAddrOf _ + | TStartOf _ | Tapp _ | Tlambda _ | TDataCons _ | Tif _ | Tat _ + | TUpdate _ | Tunion _ | Tinter _ + | Tcomprehension _ | Trange _ | TLogic_coerce _ -> + (* potential sub-term inside *) + Cil.DoChildren + method !vlogic_label _ = Cil.SkipChildren + method !vterm_lhost = function + | TMem t -> + (* potential RTE *) + state_ref := register_term kf !state_ref t; + Cil.DoChildren + | TVar _ | TResult _ -> + Cil.SkipChildren + end + +let register_predicate kf pred state = + let state_ref = ref state in + Error.handle + (fun () -> + ignore + (Visitor.visitFramacIdPredicate (register_object kf state_ref) pred)) + (); + !state_ref + + let register_code_annot kf a state = + let state_ref = ref state in + Error.handle + (fun () -> + ignore + (Visitor.visitFramacCodeAnnotation (register_object kf state_ref) a)) + (); + !state_ref + + let rec do_init vi init state = match init with + | SingleInit e -> handle_assignment state (Var vi, NoOffset) e + | CompoundInit(_, l) -> + List.fold_left (fun state (_, init) -> do_init vi init state) state l + + let register_initializers state = + let do_one vi init state = match init.init with + | None -> state + | Some init -> do_init vi init state + in + Globals.Vars.fold_in_file_rev_order do_one state +(* below: compatibility with Fluorine *) +(* let l = Globals.Vars.fold_in_file_order (fun v i l -> (v, i) :: l) [] in + List.fold_left (fun state (v, i) -> do_one v i state) state l*) + + (** The (backwards) transfer function for a branch. The [(Cil.CurrentLoc.get + ())] is set before calling this. If it returns None, then we have some + default handling. Otherwise, the returned data is the data before the + branch (not considering the exception handlers) *) + let doStmt stmt = + let _, kf = Kernel_function.find_from_sid stmt.sid in + let is_first = + try Stmt.equal stmt (Kernel_function.find_first_stmt kf) + with Kernel_function.No_Statement -> assert false + in + let is_last = + try Stmt.equal stmt (Kernel_function.find_return kf) + with Kernel_function.No_Statement -> assert false + in + Dataflow.Post + (fun state -> + let state = Env.default_varinfos state in + let state = + if Functions.check kf then + let state = + if (is_first || is_last) && Functions.RTL.is_generated_kf kf then + Annotations.fold_behaviors + (fun _ bhv s -> + let handle_annot test f s = + if test then + f + (fun _ p s -> register_predicate kf p s) + kf + bhv.b_name + s + else + s + in + let s = handle_annot is_first Annotations.fold_requires s in + let s = handle_annot is_first Annotations.fold_assumes s in + handle_annot + is_last + (fun f -> + Annotations.fold_ensures (fun e (_, p) -> f e p)) s) + kf + state + else + state + in + let state = + Annotations.fold_code_annot + (fun _ -> register_code_annot kf) stmt state + in + if stmt.ghost then + let rtes = Rte.stmt kf stmt in + List.fold_left + (fun state a -> register_code_annot kf a state) state rtes + else + state + else (* not (Options.Functions.check kf): do not monitor [kf] *) + state + in + let state = + (* take initializers into account *) + if is_first then + let main, lib = Globals.entry_point () in + if Kernel_function.equal kf main && not lib then + register_initializers state + else + state + else + state + in + Some state) + + let do_call res f args state = + let kf = Globals.Functions.get f in + Env.check_heap_allocations kf; + let params = Globals.Functions.get_params kf in + let state = + if Kernel_function.is_definition kf then + try + (* compute the initial state of the called function *) + let init = + List.fold_left2 + (fun acc p a -> match base_addr a with + | None -> acc + | Some vi -> + if Varinfo.Hptset.mem vi state + then Varinfo.Hptset.add p acc + else acc) + state + params + args + in + let init = match res with + | None -> init + | Some lv -> + match base_addr_node (Lval lv) with + | None -> init + | Some vi -> + if Varinfo.Hptset.mem vi state + then Varinfo.Hptset.add (Misc.result_vi kf) init + else init + in + let state = Compute.get ~init kf in + (* compute the resulting state by keeping arguments whenever the + corresponding formals must be kept *) + List.fold_left2 + (fun acc p a -> match base_addr a with + | None -> acc + | Some vi -> + if Varinfo.Hptset.mem p state then Varinfo.Hptset.add vi acc + else acc) + state + params + args + with Invalid_argument _ -> + Options.warning ~current:true + "ignoring effect of variadic function %a" + Kernel_function.pretty + kf; + state + else + state + in + let state = match res, Kernel_function.is_definition kf with + | None, _ | _, false -> state + | Some (lhost, _), true -> + (* add the result if \result must be kept after calling the kf *) + let vi = Misc.result_vi kf in + if Varinfo.Hptset.mem vi state then + match lhost with + | Var vi -> Varinfo.Hptset.add vi state + | Mem e -> + match base_addr e with + | None -> state + | Some vi -> Varinfo.Hptset.add vi state + else + state + in + Dataflow.Done (Some state) + + + (** The (backwards) transfer function for an instruction. The + [(Cil.CurrentLoc.get ())] is set before calling this. If it returns + None, then we have some default handling. Otherwise, the returned data is + the data before the branch (not considering the exception handlers) *) + let doInstr _stmt instr state = + let state = Env.default_varinfos state in + match instr with + | Set(lv, e, _) -> + let state = handle_assignment state lv e in + Dataflow.Done (Some state) + | Local_init(v,AssignInit i,_) -> + let state = do_init v i state in + Dataflow.Done (Some state) + | Local_init(v,ConsInit(f,args,Constructor),_) -> + do_call None f (Cil.mkAddrOfVi v :: args) state + | Local_init(v,ConsInit(f,args,Plain_func),_) -> + do_call (Some (Cil.var v)) f args state + | Call(result, f_exp, l, _) -> + (match f_exp.enode with + | Lval(Var vi, NoOffset) -> do_call result vi l state + | _ -> + Options.warning ~current:true + "function pointers may introduce too limited instrumentation."; +(* imprecise function call: keep each argument *) + Dataflow.Done + (Some + (List.fold_left + (fun acc e -> match base_addr e with + | None -> acc + | Some vi -> Varinfo.Hptset.add vi acc) + state + l))) + | Asm _ -> Error.not_yet "asm" + | Skip _ | Code_annot _ -> Dataflow.Default + + (** Whether to put this statement in the worklist. This is called when a + block would normally be put in the worklist. *) + let filterStmt _predecessor _block = true + +end + +and Compute: sig + val get: ?init:Varinfo.Hptset.t -> kernel_function -> Varinfo.Hptset.t +end = struct + + module D = Dataflow.Backwards(Transfer) + + let compute init_set kf = + Options.feedback ~dkey ~level:2 "entering in function %a." + Kernel_function.pretty kf; + assert (not (Misc.is_library_loc (Kernel_function.get_location kf))); + let tbl, is_init = + try Env.find kf, true + with Not_found -> Stmt.Hashtbl.create 17, false + in + (* Options.feedback "ANALYSING %a" Kernel_function.pretty kf;*) + if not is_init then Env.add kf tbl; + (try + let fundec = Kernel_function.get_definition kf in + let stmts, returns = Dataflow.find_stmts fundec in + if is_init then + Extlib.may + (fun set -> + List.iter + (fun s -> + let old = + try Extlib.the (Stmt.Hashtbl.find tbl s) + with Not_found -> assert false + in + Stmt.Hashtbl.replace + tbl + s + (Some (Varinfo.Hptset.union set old))) + returns) + init_set + else begin + List.iter (fun s -> Stmt.Hashtbl.add tbl s None) stmts; + Extlib.may + (fun set -> + List.iter (fun s -> Stmt.Hashtbl.replace tbl s (Some set)) returns) + init_set + end; + D.compute stmts + with Kernel_function.No_Definition | Kernel_function.No_Statement -> + ()); + Options.feedback ~dkey ~level:2 "function %a done." + Kernel_function.pretty kf; + tbl + + let get ?init kf = + if Misc.is_library_loc (Kernel_function.get_location kf) then + Varinfo.Hptset.empty + else + try + let stmt = Kernel_function.find_first_stmt kf in +(* Options.feedback "GETTING %a" Kernel_function.pretty kf;*) + let tbl = + if Env.mem_init kf init then + try Env.find kf with Not_found -> assert false + else begin + (* WARN: potentially incorrect in case of recursive call *) + Env.add_init kf init; + Env.apply (compute init) kf + end + in + try + let set = Stmt.Hashtbl.find tbl stmt in + Env.default_varinfos set + with Not_found -> + Options.fatal "[pre_analysis] stmt never analyzed: %a" + Printer.pp_stmt stmt + with Kernel_function.No_Statement -> + Varinfo.Hptset.empty + +end + +let consolidated_must_model_vi vi = + if Env.is_consolidated () then + Env.consolidated_mem vi + else begin + Options.feedback ~level:2 "performing pre-analysis for minimal memory \ +instrumentation."; + (try + let main, _ = Globals.entry_point () in + let set = Compute.get main in + Env.consolidate set + with Globals.No_such_entry_point s -> + Options.warning ~once:true "%s@ \ +@[The generated program may miss memory instrumentation@ \ +if there are memory-related annotations.@]" + s); + Options.feedback ~level:2 "pre-analysis done."; + Env.consolidated_mem vi + end + +let must_model_vi bhv ?kf ?stmt vi = + let vi = match bhv with + | None -> vi + | Some bhv -> Visitor_behavior.Get_orig.varinfo bhv vi + in + let _kf = match kf, stmt with + | None, None | Some _, _ -> kf + | None, Some stmt -> Some (Kernel_function.find_englobing_kf stmt) + in + (* [JS 2013/05/07] that is unsound to take the env from the given stmt in + presence of aliasing with an address (see tests address.i). + TODO: could be optimized though *) + consolidated_must_model_vi vi +(* match stmt, kf with + | None, _ -> consolidated_must_model_vi vi + | Some _, None -> + assert false + | Some stmt, Some kf -> + if not (Env.is_consolidated ()) then + ignore (consolidated_must_model_vi vi); + try + let tbl = Env.find kf in + try +let set = Stmt.Hashtbl.find tbl stmt in +Varinfo.Hptset.mem vi (Env.default_varinfos set) + with Not_found -> +(* new statement *) +consolidated_must_model_vi vi + with Not_found -> + (* [kf] is dead code *) + false + *) + +let rec apply_on_vi_base_from_lval f bhv ?kf ?stmt = function + | Var vi, _ -> f bhv ?kf ?stmt vi + | Mem e, _ -> apply_on_vi_base_from_exp f bhv ?kf ?stmt e + +and apply_on_vi_base_from_exp f bhv ?kf ?stmt e = match e.enode with + | Lval lv | AddrOf lv | StartOf lv -> + apply_on_vi_base_from_lval f bhv ?kf ?stmt lv + | BinOp((PlusPI | IndexPI | MinusPI), e1, _, _) -> + apply_on_vi_base_from_exp f bhv ?kf ?stmt e1 + | BinOp(MinusPP, e1, e2, _) -> + apply_on_vi_base_from_exp f bhv ?kf ?stmt e1 + || 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 + | Ge | Eq | Ne | BAnd | BXor | BOr | LAnd | LOr), _, _, _) + | Const _ -> (* possible in case of static address *) false + | UnOp _ | SizeOf _ | SizeOfE _ | SizeOfStr _ | AlignOf _ | AlignOfE _ -> + 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} *) +(* ************************************************************************** *) + +let must_model_vi ?bhv ?kf ?stmt vi = + not (must_never_monitor vi) + && + (Options.Full_mmodel.get () + || Error.generic_handle (must_model_vi bhv ?kf ?stmt) false vi) + +let must_model_lval ?bhv ?kf ?stmt lv = + not (must_never_monitor_lval bhv ?kf ?stmt lv) + && + (Options.Full_mmodel.get () + || Error.generic_handle (must_model_lval bhv ?kf ?stmt) false lv) + +let must_model_exp ?bhv ?kf ?stmt exp = + not (must_never_monitor_exp bhv ?kf ?stmt 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 () + || Env.has_heap_allocations () + +(* +Local Variables: +compile-command: "make" +End: +*) diff --git a/src/plugins/e-acsl/src/analyses/mmodel_analysis.mli b/src/plugins/e-acsl/src/analyses/mmodel_analysis.mli new file mode 100644 index 0000000000000000000000000000000000000000..33e41781a8553f0082da974f890afecd564d81cc --- /dev/null +++ b/src/plugins/e-acsl/src/analyses/mmodel_analysis.mli @@ -0,0 +1,53 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C's E-ACSL plug-in. *) +(* *) +(* Copyright (C) 2012-2018 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +open Cil_types + +(** Compute a sound over-approximation of what left-values must be tracked by + the memory model library *) + +val reset: unit -> unit +(** Must be called to redo the analysis *) + +val use_model: unit -> bool +(** Is one variable monitored (at least)? *) + +val must_model_vi: ?bhv:Visitor_behavior.t -> ?kf:kernel_function + -> ?stmt:stmt -> varinfo -> bool +(** [must_model_vi ?kf ?stmt vi] returns [true] if the varinfo [vi] at the given + [stmt] in the given function [kf] must be tracked by the memory model + library. If behavior [bhv] is specified then assume that [vi] is part + of the new project generated by the given copy behavior [bhv] *) + +val must_model_lval: ?bhv:Visitor_behavior.t -> ?kf:kernel_function + -> ?stmt:stmt -> lval -> bool +(** Same as {!must_model_vi}, for left-values *) + +val must_model_exp: ?bhv:Visitor_behavior.t -> ?kf:kernel_function + -> ?stmt:stmt -> exp -> bool +(** Same as {!must_model_vi}, for expressions *) + +(* + Local Variables: + compile-command: "make" + End: + *) diff --git a/src/plugins/e-acsl/src/analyses/rte.ml b/src/plugins/e-acsl/src/analyses/rte.ml new file mode 100644 index 0000000000000000000000000000000000000000..5f12d7aa07774f5524449815a5a4da19cd046b21 --- /dev/null +++ b/src/plugins/e-acsl/src/analyses/rte.ml @@ -0,0 +1,84 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C's E-ACSL plug-in. *) +(* *) +(* Copyright (C) 2012-2018 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* ************************************************************************** *) +(** {2 Generic code} *) +(* ************************************************************************** *) + +let apply_rte f x = + let signed = Kernel.SignedOverflow.get () in + let unsigned = Kernel.UnsignedOverflow.get () in + Kernel.SignedOverflow.off (); + Kernel.UnsignedOverflow.off (); + let finally () = + Kernel.SignedOverflow.set signed; + Kernel.UnsignedOverflow.set unsigned + in + Extlib.try_finally ~finally f x + +let warn_rte warn exn = + if warn then + Options.warning "@[@[cannot run RTE:@ %s.@]@ \ +Ignoring potential runtime errors in annotations." + (Printexc.to_string exn) + +(* ************************************************************************** *) +(** {2 Exported code} *) +(* ************************************************************************** *) + +open Cil_datatype + +let stmt ?(warn=true) = + try + let f = + Dynamic.get + ~plugin:"RteGen" + "stmt_annotations" + (Datatype.func2 Kernel_function.ty Stmt.ty + (let module L = Datatype.List(Code_annotation) in L.ty)) + in + (fun x y -> apply_rte (f x) y) + with Failure _ | Dynamic.Unbound_value _ | Dynamic.Incompatible_type _ as exn + -> + warn_rte warn exn; + fun _ _ -> [] + +let exp ?(warn=true) = + try + let f = + Dynamic.get + ~plugin:"RteGen" + "exp_annotations" + (Datatype.func3 Kernel_function.ty Stmt.ty Exp.ty + (let module L = Datatype.List(Code_annotation) in L.ty)) + in + (fun x y z -> apply_rte (f x y) z) + with Failure _ | Dynamic.Unbound_value _ | Dynamic.Incompatible_type _ as exn + -> + warn_rte warn exn; + fun _ _ _ -> [] + +(* +Local Variables: +compile-command: "make" +End: +*) diff --git a/src/plugins/e-acsl/src/analyses/rte.mli b/src/plugins/e-acsl/src/analyses/rte.mli new file mode 100644 index 0000000000000000000000000000000000000000..4af8130be29737ecc29f0b5ccf5338566a28662c --- /dev/null +++ b/src/plugins/e-acsl/src/analyses/rte.mli @@ -0,0 +1,37 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C's E-ACSL plug-in. *) +(* *) +(* Copyright (C) 2012-2018 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(** Accessing the RTE plug-in easily. *) + +open Cil_types + +val stmt: ?warn:bool -> kernel_function -> stmt -> code_annotation list +(** RTEs of a given stmt, as a list of code annotations. *) + +val exp: ?warn:bool -> kernel_function -> stmt -> exp -> code_annotation list +(** RTEs of a given exp, as a list of code annotations. *) + +(* +Local Variables: +compile-command: "make" +End: +*) diff --git a/src/plugins/e-acsl/src/analyses/typing.ml b/src/plugins/e-acsl/src/analyses/typing.ml new file mode 100644 index 0000000000000000000000000000000000000000..4d1ea2ba27ed606651c8f5847ceea6337eaed442 --- /dev/null +++ b/src/plugins/e-acsl/src/analyses/typing.ml @@ -0,0 +1,760 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C's E-ACSL plug-in. *) +(* *) +(* Copyright (C) 2012-2018 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +open Cil_types + +(* Implement Figure 4 of J. Signoles' JFLA'15 paper "Rester statique pour + devenir plus rapide, plus précis et plus mince". *) + +let dkey = Options.dkey_typing + +let compute_quantif_guards_ref + : (predicate -> logic_var list -> predicate -> + (term * relation * logic_var * relation * term) list) ref + = Extlib.mk_fun "compute_quantif_guards_ref" + +(******************************************************************************) +(** Datatype and constructor *) +(******************************************************************************) + +type number_ty = + | C_integer of ikind + | C_float of fkind + | Gmpz + | Rational + | Real + | Nan + +let ikind ik = C_integer ik +let c_int = ikind IInt +let gmpz = Gmpz +let fkind fk = C_float fk +let rational = Rational +let nan = Nan + +module D = + Datatype.Make_with_collections + (struct + type t = number_ty + let name = "E_ACSL.Typing.t" + let reprs = [ Gmpz; Real; Nan; c_int ] + include Datatype.Undefined + + let compare ty1 ty2 = + if ty1 == ty2 then 0 + else + match ty1, ty2 with + | C_integer i1, C_integer i2 -> + if i1 = i2 then 0 + else if Cil.intTypeIncluded i1 i2 then -1 else 1 + | C_float f1, C_float f2 -> + Transitioning.Stdlib.compare f1 f2 + | (C_integer _ | C_float _ | Gmpz | Rational | Real), Nan + | (C_integer _ | C_float _ | Gmpz | Rational ), Real + | (C_integer _ | C_float _ | Gmpz), Rational + | (C_integer _ | C_float _), Gmpz + | C_integer _, C_float _ -> + -1 + | (C_float _ | Gmpz | Rational | Real | Nan), C_integer _ + | (Gmpz | Rational | Real | Nan), C_float _ + | (Rational | Real | Nan), Gmpz + | (Real | Nan), Rational + | Nan, Real -> + 1 + | Gmpz, Gmpz + | Rational, Rational + | Real, Real + | Nan, Nan -> + assert false + + let equal = Datatype.from_compare + + let hash = function + | C_integer ik -> 7 * Hashtbl.hash ik + | C_float fk -> 97 * Hashtbl.hash fk + | Gmpz -> 787 + | Rational -> 907 + | Real -> 1011 + | Nan -> 1277 + + let pretty fmt = function + | C_integer k -> Printer.pp_ikind fmt k + | C_float k -> Printer.pp_fkind fmt k + | Gmpz -> Format.pp_print_string fmt "Gmpz" + | Rational -> Format.pp_print_string fmt "Rational" + | Real -> Format.pp_print_string fmt "Real" + | Nan -> Format.pp_print_string fmt "Nan" + end) + +(******************************************************************************) +(** Basic operations *) +(******************************************************************************) + +let join_cty ty1 ty2 = + let ty = Cil.arithmeticConversion ty1 ty2 in + match ty with + | TInt(i, _) -> C_integer i + | TFloat(f, _) -> C_float f + | _ -> + Options.fatal "[typing] join failure: unexpected result %a" + Printer.pp_typ ty + +let join ty1 ty2 = + if ty1 == ty2 then ty1 + else + match ty1, ty2 with + | Nan, Nan | Real, Real | Rational, Rational | Gmpz, Gmpz -> + assert false + | Nan, (C_integer _ | C_float _ | Gmpz | Rational | Real as ty) + | (C_integer _ | C_float _ | Gmpz | Rational | Real as ty), Nan -> + Options.fatal "[typing] join failure: number %a and nan" D.pretty ty + | Real, (C_integer _ | C_float _ | Gmpz | Rational) + | (C_integer _ | C_float _ | Rational | Gmpz), Real -> + Real + | Rational, (C_integer _ | C_float _ | Gmpz) + | (C_integer _ | C_float _ | Gmpz), Rational + | C_float _, Gmpz + | Gmpz, C_float _ -> + Rational + | Gmpz, C_integer _ + | C_integer _, Gmpz -> + Gmpz + | C_float f1, C_float f2 -> + join_cty (TFloat(f1, [])) (TFloat(f2, [])) + | C_float f, C_integer n + | C_integer n, C_float f -> + join_cty (TFloat(f, [])) (TInt(n, [])) + | C_integer i1, C_integer i2 -> + if Options.Gmp_only.get () then Gmpz + else join_cty (TInt(i1, [])) (TInt(i2, [])) + +exception Not_a_number +let typ_of_number_ty = function + | C_integer ik -> TInt(ik, []) + | C_float fk -> TFloat(fk, []) + | Gmpz -> Gmp_types.Z.t () + (* for the time being, no reals but rationals instead *) + | Rational -> Gmp_types.Q.t () + | Real -> Error.not_yet "real number type" + | Nan -> raise Not_a_number + +let typ_of_lty = function + | Ctype cty -> cty + | Linteger -> Gmp_types.Z.t () + | Lreal -> Error.not_yet "real type" + | Ltype _ | Lvar _ | Larrow _ -> Options.fatal "unexpected logic type" + +(******************************************************************************) +(** Memoization *) +(******************************************************************************) + +type computed_info = + { ty: D.t; (* type required for the term *) + op: D.t; (* type required for the operation *) + cast: D.t option; (* if not [None], type of the context which the term + must be casted to. If [None], no cast needed. *) + } + +(* Memoization module which retrieves the computed info of some terms. If the + info is already computed for a term, it is never recomputed *) +module Memo: sig + val memo: (term -> computed_info) -> term -> computed_info + val get: term -> computed_info + val clear: unit -> unit +end = struct + + module H = Hashtbl.Make(struct + type t = term + (* the comparison over terms is the physical equality. It cannot be the + structural one (given by [Cil_datatype.Term.equal]) because the very + same term can be used in 2 different contexts which lead to different + casts. + + By construction, there are no physically equal terms in the AST + built by Cil. Consequently the memoisation should be fully + useless. However the translation of E-ACSL guarded quantification + generates new terms (see module {!Quantif}) which must be typed. The term + corresponding to the bound variable [x] is actually used twice: once in + the guard and once for encoding [x+1] when incrementing it. The + memoization is only useful here and indeed prevent the generation of + one extra variable in some cases. *) + let equal (t1:term) t2 = t1 == t2 + let hash = Cil_datatype.Term.hash + end) + + let tbl = H.create 97 + + let get t = + try H.find tbl t + with Not_found -> + Options.fatal + "[typing] type of term '%a' was never computed." + Printer.pp_term t + + let memo f t = + try H.find tbl t + with Not_found -> + let x = f t in + H.add tbl t x; + x + + let clear () = H.clear tbl + +end + +(******************************************************************************) +(** {2 Coercion rules} *) +(******************************************************************************) + +(* Compute the smallest type (bigger than [int]) which can contain the whole + interval. It is the \theta operator of the JFLA's paper. *) +let ty_of_interv ?ctx = function + | Interval.Float(fk, _) -> C_float fk + | Interval.Rational -> Rational + | Interval.Real -> Real + | Interval.Nan -> Nan + | Interval.Ival iv -> + try + let kind = Interval.ikind_of_ival iv in + (match ctx with + | None + | Some (Gmpz | Nan) -> + C_integer kind + | Some (C_integer ik as ctx) -> + (* return [ctx] type for types smaller than int to prevent superfluous + casts in the generated code *) + if Cil.intTypeIncluded kind ik then ctx else C_integer kind + | Some (C_float _ | Rational | Real as ty) -> + ty) + with Cil.Not_representable -> + match ctx with + | None | Some(C_integer _ | Gmpz | Nan) -> Gmpz + | Some (C_float _ | Rational) -> Rational + | Some Real -> Real + +(* compute a new {!computed_info} by coercing the given type [ty] to the given + context [ctx]. [op] is the type for the operator. *) +let coerce ~arith_operand ~ctx ~op ty = + if D.compare ty ctx = 1 then + (* type larger than the expected context, + so we must introduce an explicit cast *) + { ty; op; cast = Some ctx } + else + (* only add an explicit cast if the context is [Gmp] and [ty] is not; + or if the term corresponding to [ty] is an operand of an arithmetic + operation which must be explicitly coerced in order to force the + operation to be of the expected type. *) + if (ctx = Gmpz && ty <> Gmpz) || arith_operand + then { ty; op; cast = Some ctx } + else { ty; op; cast = None } + +let number_ty_of_typ ty = match Cil.unrollType ty with + | TInt(ik, _) | TEnum({ ekind = ik }, _) -> C_integer ik + | TFloat(fk, _) -> C_float fk + | TVoid _ | TPtr _ | TArray _ | TFun _ | TComp _ | TBuiltin_va_list _ -> Nan + | TNamed _ -> assert false + +let ty_of_logic_ty ?term lty = + let get_ty = function + | Linteger -> Gmpz + | Ctype ty -> number_ty_of_typ ty + | Lreal -> Real + | Larrow _ -> Nan + | Ltype _ -> Error.not_yet "user-defined logic type" + | Lvar _ -> Error.not_yet "type variable" + in + match term with + | None -> get_ty lty + | Some t -> + if Options.Gmp_only.get () && lty = Linteger then Gmpz + else + let i = Interval.infer t in + ty_of_interv i + +(******************************************************************************) +(** {2 Type system} *) +(******************************************************************************) + +(* generate a context [c]. Take --e-acsl-gmp-only into account iff [use_gmp_opt] + is true. *) +let mk_ctx ~use_gmp_opt = function + | C_integer _ as c -> + if use_gmp_opt && Options.Gmp_only.get () then Gmpz + else c + | C_float _ | Gmpz | Rational | Real | Nan as c -> c + +(* the number_ty corresponding to [t] whenever use as an offset. + In that case, it cannot be a GMP, so it must be coerced to an integral type + in that case *) +let type_offset t = + let i = Interval.infer t in + match ty_of_interv i with + | Gmpz -> C_integer ILongLong (* largest possible type *) + | ty -> ty + +let type_letin li li_t = + let i = Interval.infer li_t in + Interval.Env.add li.l_var_info i + +(* type the term [t] in a context [ctx] by taking --e-acsl-gmp-only into account + iff [use_gmp_opt] is true. *) +let rec type_term ~use_gmp_opt ?(arith_operand=false) ?ctx t = + let ctx = Extlib.opt_map (mk_ctx ~use_gmp_opt) ctx in + let dup ty = ty, ty in + let compute_ctx ?ctx i = + (* in order to get a minimal amount of generated casts for operators, the + result is typed in the given context [ctx], but not the operands. + This function returns a tuple (ctx_of_result, ctx_of_operands) *) + match ctx with + | None -> + (* no context: factorize *) + dup (mk_ctx ~use_gmp_opt:true (ty_of_interv i)) + | Some ctx -> + mk_ctx ~use_gmp_opt:true (ty_of_interv ~ctx i), + mk_ctx ~use_gmp_opt:true (ty_of_interv i) + in + let infer t = + Cil.CurrentLoc.set t.term_loc; + (* this pattern matching implements the formal rules of the JFLA's paper + (and of course also covers the missing cases). Also enforce the invariant + that every subterm is typed, even if it is not an integer. *) + match t.term_node with + | TConst (Integer _ | LChr _ | LEnum _ | LReal _) + | TSizeOf _ + | TSizeOfStr _ + | TAlignOf _ -> + let i = Interval.infer t in + let ty = ty_of_interv ?ctx i in + dup ty + + | TLval tlv -> + let i = Interval.infer t in + let ty = ty_of_interv ?ctx i in + type_term_lval tlv; + dup ty + + | Toffset(_, t') + | Tblock_length(_, t') + | TSizeOfE t' + | TAlignOfE t' -> + let i = Interval.infer t in + (* [t'] must be typed, but it is a pointer *) + ignore (type_term ~use_gmp_opt:true ~ctx:Nan t'); + let ty = ty_of_interv ?ctx i in + dup ty + + | TBinOp (MinusPP, t1, t2) -> + let i = Interval.infer t in + (* [t1] and [t2] must be typed, but they are pointers *) + ignore (type_term ~use_gmp_opt:true ~ctx:Nan t1); + ignore (type_term ~use_gmp_opt:true ~ctx:Nan t2); + let ty = ty_of_interv ?ctx i in + dup ty + + | TUnOp (unop, t') -> + let i = Interval.infer t in + let i' = Interval.infer t' in + let ctx_res, ctx = compute_ctx ?ctx (Interval.join i i') in + ignore (type_term ~use_gmp_opt:true ~arith_operand:true ~ctx t'); + (match unop with + | LNot -> c_int, ctx_res (* converted into [t == 0] in case of GMP *) + | Neg | BNot -> dup ctx_res) + + | TBinOp ((PlusA | MinusA | Mult | Div | Mod | Shiftlt | Shiftrt), t1, t2) + -> + let i = Interval.infer t in + let i1 = Interval.infer t1 in + let i2 = Interval.infer t2 in + let ctx_res, ctx = + compute_ctx ?ctx (Interval.join i (Interval.join i1 i2)) + in + (* it is enough to explicitly coerce when required one operand to [ctx] + (through [arith_operand]) in order to force the type of the + operation. Heuristic: coerce the operand which is not a lval in + order to lower the number of explicit casts *) + let rec cast_first t1 t2 = match t1.term_node with + | TLval _ -> false + | TLogic_coerce(_, t) -> cast_first t t2 + | _ -> true + in + let cast_first = cast_first t1 t2 in + ignore (type_term ~use_gmp_opt:true ~arith_operand:cast_first ~ctx t1); + ignore + (type_term ~use_gmp_opt:true ~arith_operand:(not cast_first) ~ctx t2); + dup ctx_res + + | TBinOp ((Lt | Gt | Le | Ge | Eq | Ne), t1, t2) -> + assert (match ctx with None -> true | Some c -> D.compare c c_int >= 0); + let i1 = Interval.infer t1 in + let i2 = Interval.infer t2 in + let ctx = + mk_ctx ~use_gmp_opt:true (ty_of_interv ?ctx (Interval.join i1 i2)) + in + ignore (type_term ~use_gmp_opt:true ~ctx t1); + ignore (type_term ~use_gmp_opt:true ~ctx t2); + let ty = match ctx with + | Nan -> c_int + | Real | Rational | Gmpz | C_float _ | C_integer _ -> ctx + in + c_int, ty + + | TBinOp ((LAnd | LOr), t1, t2) -> + let i1 = Interval.infer t1 in + let i2 = Interval.infer t2 in + let ty = ty_of_interv ?ctx (Interval.join i1 i2) in + (* both operands fit in an int. *) + ignore (type_term ~use_gmp_opt:true ~ctx:c_int t1); + ignore (type_term ~use_gmp_opt:true ~ctx:c_int t2); + dup ty + + | TBinOp (BAnd, _, _) -> Error.not_yet "bitwise and" + | TBinOp (BXor, _, _) -> Error.not_yet "bitwise xor" + | TBinOp (BOr, _, _) -> Error.not_yet "bitwise or" + + | TCastE(_, t') -> + (* compute the smallest interval from the whole term [t] *) + let i = Interval.infer t in + (* nothing more to do: [i] is already more precise than what we could + infer from the arguments of the cast. *) + let ctx = ty_of_interv ?ctx i in + ignore (type_term ~use_gmp_opt:true ~ctx t'); + dup ctx + + | Tif (t1, t2, t3) -> + let ctx1 = + mk_ctx ~use_gmp_opt:false c_int (* an int must be generated *) + in + ignore (type_term ~use_gmp_opt:false ~ctx:ctx1 t1); + let i = Interval.infer t in + let i2 = Interval.infer t2 in + let i3 = Interval.infer t3 in + let ctx = ty_of_interv ?ctx (Interval.join i (Interval.join i2 i3)) in + let ctx = mk_ctx ~use_gmp_opt:true ctx in + ignore (type_term ~use_gmp_opt:true ~ctx t2); + ignore (type_term ~use_gmp_opt:true ~ctx t3); + dup ctx + + | Tat (t, _) + | TLogic_coerce (_, t) -> + dup (type_term ~use_gmp_opt ~arith_operand ?ctx t).ty + + | TAddrOf tlv + | TStartOf tlv -> + (* it is a pointer, but subterms must be typed. *) + type_term_lval tlv; + dup Nan + + | Tbase_addr (_, t) -> + (* it is a pointer, but subterms must be typed. *) + ignore (type_term ~use_gmp_opt:true ~ctx:Nan t); + dup Nan + + | TBinOp ((PlusPI | IndexPI | MinusPI), t1, t2) -> + (* both [t1] and [t2] must be typed. *) + ignore (type_term ~use_gmp_opt:true ~ctx:Nan t1); + let ctx = type_offset t2 in + ignore (type_term ~use_gmp_opt:false ~ctx t2); + dup Nan + + | Tapp(li, _, args) -> + if Builtins.mem li.l_var_info.lv_name then + let typ_arg lvi arg = + (* a built-in is a C function, so the context is necessarily a C + type. *) + let ctx = ty_of_logic_ty lvi.lv_type in + ignore (type_term ~use_gmp_opt:false ~ctx arg) + in + List.iter2 typ_arg li.l_profile args; + (* [li.l_type is [None] for predicate only: not possible here. + Thus using [Extlib.the] is fine *) + dup (ty_of_logic_ty (Extlib.the li.l_type)) + else begin + (* TODO: what if the type of the parameter is smaller than the infered + type of the argument? For now, it is silently ignored (both + statically and at runtime)... *) + List.iter (fun arg -> ignore (type_term ~use_gmp_opt:true arg)) args; + (* TODO: recursive call in arguments of function call *) + match li.l_body with + | LBpred _ -> + (* possible to have an [LBpred] here because we transformed + [Papp] into [Tapp] *) + dup c_int + | LBterm _ -> + begin match li.l_type with + | None -> + assert false + | Some lty -> + (* TODO: what if the function returns a real? *) + let ty = ty_of_logic_ty ~term:t lty in + dup ty + end + | LBnone -> + Error.not_yet "logic functions with no definition nor reads clause" + | LBreads _ -> + Error.not_yet "logic functions performing read accesses" + | LBinductive _ -> + Error.not_yet "logic functions inductively defined" + end + + | Tunion _ -> Error.not_yet "tset union" + | Tinter _ -> Error.not_yet "tset intersection" + | Tcomprehension (_,_,_) -> Error.not_yet "tset comprehension" + + | Trange(None, _) | Trange(_, None) -> + Options.abort "unbounded ranges are not part of E-ACSl" + | Trange(Some n1, Some n2) -> + ignore (type_term ~use_gmp_opt n1); + ignore (type_term ~use_gmp_opt n2); + let i = Interval.infer t in + let ty = ty_of_interv ?ctx i in + dup ty + + | Tlet(li, t) -> + let li_t = Misc.term_of_li li in + type_letin li li_t; + ignore (type_term ~use_gmp_opt:true li_t); + dup (type_term ~use_gmp_opt:true ?ctx t).ty + + | Tlambda (_,_) -> Error.not_yet "lambda" + | TDataCons (_,_) -> Error.not_yet "datacons" + | TUpdate (_,_,_) -> Error.not_yet "update" + + | Tnull + | TConst (LStr _ | LWStr _) + | Ttypeof _ + | Ttype _ + | Tempty_set -> dup Nan + in + Memo.memo + (fun t -> + let ty, op = infer t in + match ctx with + | None -> { ty; op; cast = None } + | Some ctx -> coerce ~arith_operand ~ctx ~op ty) + t + +and type_term_lval (host, offset) = + type_term_lhost host; + type_term_offset offset + +and type_term_lhost = function + | TVar _ + | TResult _ -> () + | TMem t -> ignore (type_term ~use_gmp_opt:false ~ctx:Nan t) + +and type_term_offset = function + | TNoOffset -> () + | TField(_, toff) + | TModel(_, toff) -> type_term_offset toff + | TIndex(t, toff) -> + let ctx = type_offset t in + ignore (type_term ~use_gmp_opt:false ~ctx t); + type_term_offset toff + +let rec type_predicate p = + Cil.CurrentLoc.set p.pred_loc; + (* this pattern matching also follows the formal rules of the JFLA's paper *) + let op = + match p.pred_content with + | Pfalse | Ptrue -> c_int + | Papp(li, _, _) -> + begin match li.l_body with + | LBpred _ -> + (* No need to type subpredicates + since Papp will be transformed into Tapp in Translate: + a retyping is done there *) + c_int + | LBnone -> (* Eg: \is_finite *) + Error.not_yet "predicate with no definition nor reads clause" + | LBreads _ | LBterm _ | LBinductive _ -> + Options.fatal "unexpected logic definition" + end + | Pseparated _ -> Error.not_yet "\\separated" + | Pdangling _ -> Error.not_yet "\\dangling" + | Prel(_, t1, t2) -> + let i1 = Interval.infer t1 in + let i2 = Interval.infer t2 in + let i = Interval.join i1 i2 in + let ctx = mk_ctx ~use_gmp_opt:true (ty_of_interv ~ctx:c_int i) in + ignore (type_term ~use_gmp_opt:true ~ctx t1); + ignore (type_term ~use_gmp_opt:true ~ctx t2); + (match ctx with + | Nan -> c_int + | Real | Rational | Gmpz | C_float _ | C_integer _ -> ctx) + | Pand(p1, p2) + | Por(p1, p2) + | Pxor(p1, p2) + | Pimplies(p1, p2) + | Piff(p1, p2) -> + ignore (type_predicate p1); + ignore (type_predicate p2); + c_int + | Pnot p -> + ignore (type_predicate p); + c_int + | Pif(t, p1, p2) -> + let ctx = mk_ctx ~use_gmp_opt:false c_int in + ignore (type_term ~use_gmp_opt:false ~ctx t); + ignore (type_predicate p1); + ignore (type_predicate p2); + c_int + | Plet(li, p) -> + let li_t = Misc.term_of_li li in + type_letin li li_t; + ignore (type_term ~use_gmp_opt:true li_t); + (type_predicate p).ty + + | Pforall(bounded_vars, { pred_content = Pimplies(hyps, goal) }) + | Pexists(bounded_vars, { pred_content = Pand(hyps, goal) }) -> + let guards = !compute_quantif_guards_ref p bounded_vars hyps in + let iv_plus_one iv = + Interval.Ival (Ival.add_singleton_int Integer.one iv) + in + List.iter + (fun (t1, r1, x, r2, t2) -> + let i1 = Interval.infer t1 in + let i1 = match r1, i1 with + | Rlt, Interval.Ival iv -> iv_plus_one iv + | Rle, _ -> i1 + | _ -> assert false + in + let i2 = Interval.infer t2 in + (* add one to [i2], since we increment the loop counter one more + time before going outside the loop. *) + let i2 = match r2, i2 with + | Rlt, _ -> i2 + | Rle, Interval.Ival iv -> iv_plus_one iv + | _ -> assert false + in + let i = Interval.join i1 i2 in + let ctx = match x.lv_type with + | Linteger -> mk_ctx ~use_gmp_opt:true (ty_of_interv ~ctx:Gmpz i) + | Ctype ty -> + (match Cil.unrollType ty with + | TInt(ik, _) -> mk_ctx ~use_gmp_opt:true (C_integer ik) + | ty -> + Options.fatal "unexpected type %a for quantified variable %a" + Printer.pp_typ ty + Printer.pp_logic_var x) + | lty -> + Options.fatal "unexpected type %a for quantified variable %a" + Printer.pp_logic_type lty + Printer.pp_logic_var x + in + (* forcing when typing bounds prevents to generate an extra useless + GMP variable when --e-acsl-gmp-only *) + ignore (type_term ~use_gmp_opt:false ~ctx t1); + ignore (type_term ~use_gmp_opt:false ~ctx t2); + (* if we must generate GMP code, degrade the interval in order to + guarantee that [x] will be a GMP when typing the goal *) + let i = match ctx with + | C_integer _ -> i + | Gmpz -> Interval.top_ival (* [ -\infty; +\infty ] *) + | C_float _ | Rational | Real | Nan -> + Options.fatal "unexpected quantification over %a" D.pretty ctx + in + Interval.Env.add x i) + guards; + (type_predicate goal).ty + + | Pinitialized(_, t) + | Pfreeable(_, t) + | Pallocable(_, t) + | Pvalid(_, t) + | Pvalid_read(_, t) + | Pvalid_function t -> + ignore (type_term ~use_gmp_opt:false ~ctx:Nan t); + c_int + + | Pforall _ -> Error.not_yet "unguarded \\forall quantification" + | Pexists _ -> Error.not_yet "unguarded \\exists quantification" + | Pat(p, _) -> (type_predicate p).ty + | Pfresh _ -> Error.not_yet "\\fresh" + in + coerce ~arith_operand:false ~ctx:c_int ~op c_int + +let type_term ~use_gmp_opt ?ctx t = + Options.feedback ~dkey ~level:4 "typing term '%a' in ctx '%a'." + Printer.pp_term t (Pretty_utils.pp_opt D.pretty) ctx; + ignore (type_term ~use_gmp_opt ?ctx t) + +let type_named_predicate ?(must_clear=true) p = + Options.feedback ~dkey ~level:3 "typing predicate '%a'." + Printer.pp_predicate p; + if must_clear then begin + Interval.Env.clear (); + Memo.clear () + end; + ignore (type_predicate p) + +let unsafe_set t ?ctx ty = + let ctx = match ctx with None -> ty | Some ctx -> ctx in + let mk _ = coerce ~arith_operand:false ~ctx ~op:ty ty in + ignore (Memo.memo mk t) + +(******************************************************************************) +(** {2 Getters} *) +(******************************************************************************) + +let get_number_ty t = (Memo.get t).ty +let get_integer_op t = (Memo.get t).op +let get_integer_op_of_predicate p = (type_predicate p).op + +(* {!typ_of_integer}, but handle the not-integer cases. *) +let extract_typ t ty = + try typ_of_number_ty ty + with Not_a_number -> + match t.term_type with + | Ctype _ as lty -> Logic_utils.logicCType lty + | Linteger | Lreal -> + Options.fatal "unexpected context NaN for term %a" Printer.pp_term t + | Ltype _ -> Error.not_yet "unsupported logic type: user-defined type" + | Lvar _ -> Error.not_yet "unsupported logic type: type variable" + | Larrow _ -> Error.not_yet "unsupported logic type: type arrow" + +let get_typ t = + let info = Memo.get t in + extract_typ t info.ty + +let get_op t = + let info = Memo.get t in + extract_typ t info.op + +let get_cast t = + let info = Memo.get t in + try Extlib.opt_map typ_of_number_ty info.cast + with Not_a_number -> None + +let get_cast_of_predicate p = + let info = type_predicate p in + try Extlib.opt_map typ_of_number_ty info.cast + with Not_a_number -> assert false + +let clear = Memo.clear + +module Datatype = D + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff --git a/src/plugins/e-acsl/src/analyses/typing.mli b/src/plugins/e-acsl/src/analyses/typing.mli new file mode 100644 index 0000000000000000000000000000000000000000..dfef352dee0b4fae1f774d4fa06c12b1195d2832 --- /dev/null +++ b/src/plugins/e-acsl/src/analyses/typing.mli @@ -0,0 +1,165 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C's E-ACSL plug-in. *) +(* *) +(* Copyright (C) 2012-2018 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(** Type system which computes the smallest C type that may contain all the + possible values of a given integer term or predicate. Also compute the + required casts. It is based on interval inference of module {!Interval}. + + It implement Figure 4 of J. Signoles' JFLA'15 paper "Rester statique pour + devenir plus rapide, plus précis et plus mince". + + Example: consider a variable [x] of type [int] and a variable [y] of type + char on a (strange) architecture in which values of type [int] belongs to + the interval [[-128;127]] and values of type [char] belongs to the interval + [[-32;31]], while there are no other integral types. Then here are some + information computed from the term [1+(x+1)/(y-64)] by the type system: + 1. [x+1] must be a GMP (because of the potential overflow) + 2. consequently [x], which is an [int], must be coerced into a GMP and the + same for the number 1 in this addition. + 3. [y-64] can be computed in an [int] (because the result belongs to the + interval [[-96;-33]]). + 4. [(x+1)/(y-64)] must be a GMP operation because the numerator is a + GMP (see 1.). Consequently [y-64] must be coerced into a GMP too. However, + the result belongs to the interval [[-3;3]] and thus can be safely coerced + to an [int]. + 5. Consequently the addition of the toplevel term [1+(x+1)/(y-64)] can + safely be computed in [int]: its result belongs to [[-2;4]]. *) + +open Cil_types + +(******************************************************************************) +(** {2 Datatypes} *) +(******************************************************************************) + +(** Possible types infered by the system. *) + +type number_ty = private + | C_integer of ikind + | C_float of fkind + | Gmpz + | Rational + | Real + | Nan + +module Datatype: Datatype.S_with_collections with type t = number_ty + +(** {3 Smart constructors} *) + +val c_int: number_ty +val ikind: ikind -> number_ty +val fkind: fkind -> number_ty +val gmpz: number_ty +val rational: number_ty +val nan: number_ty + +(** {3 Useful operations over {!number_ty}} *) + +exception Not_a_number +val typ_of_number_ty: number_ty -> typ +(** @return the C type corresponding to an {!number_ty}. That is [Gmp.z_t ()] + for [Gmpz], [Real.t ()] for [Real] and [TInt(ik, [[]])] for [Ctype ik]. + @raise Not_a_number in case of [Nan]. *) + +val number_ty_of_typ: typ -> number_ty +(** Reverse of [typ_of_number_ty] *) + +val join: number_ty -> number_ty -> number_ty +(** {!number_ty} is a join-semi-lattice if you do not consider [Other]. If + there is no [Other] in argument, this function computes the join of this + semi-lattice. If one of the argument is {!Other}, the function assumes that + the other argument is also {!Other}. In this case, the result is [Other]. *) + +(******************************************************************************) +(** {2 Typing} *) +(******************************************************************************) + +val type_term: use_gmp_opt:bool -> ?ctx:number_ty -> term -> unit +(** Compute the type of each subterm of the given term in the given context. If + [use_gmp_opt] is false, then the conversion to the given context is done + even if -e-acsl-gmp-only is set. *) + +val type_named_predicate: ?must_clear:bool -> predicate -> unit +(** Compute the type of each term of the given predicate. + Set {!must_clear} to false in order to not reset the environment. *) + +val clear: unit -> unit +(** Remove all the previously computed types. *) + +(** {3 Getters} + + Below, the functions assume that either {!type_term} or + {!type_named_predicate} has been previously computed for the given term or + predicate. *) + +val get_number_ty: term -> number_ty +(** @return the infered type for the given term. *) + +val get_integer_op: term -> number_ty +(** @return the infered type for the top operation of the given term. + It is meaningless to call this function over a non-arithmetical/logical + operator. *) + +val get_integer_op_of_predicate: predicate -> number_ty +(** @return the infered type for the top operation of the given predicate. *) + +val get_typ: term -> typ +(** Get the type which the given term must be generated to. *) + +val get_op: term -> typ +(** Get the type which the operation on top of the given term must be generated + to. *) + +val get_cast: term -> typ option +(** Get the type which the given term must be converted to (if any). *) + +val get_cast_of_predicate: predicate -> typ option +(** Like {!get_cast}, but for predicates. *) + +val unsafe_set: term -> ?ctx:number_ty -> number_ty -> unit +(** Register that the given term has the given type in the given context (if + any). No verification is done. *) + +(*****************************************************************************) +(** {2 Typing/types-related utils} *) +(*****************************************************************************) + +val ty_of_interv: ?ctx:number_ty -> Interval.t -> number_ty +(* Compute the smallest type (bigger than [int]) which can contain the whole + interval. It is the \theta operator of the JFLA's paper. *) + +val typ_of_lty: logic_type -> typ +(** @return the C type that correponds to the given logic type. *) + +(******************************************************************************) +(** {2 Internal stuff} *) +(******************************************************************************) + +val compute_quantif_guards_ref + : (predicate -> logic_var list -> predicate -> + (term * relation * logic_var * relation * term) list) ref +(** Forward reference. *) + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff --git a/src/plugins/e-acsl/src/code_generator/at_with_lscope.ml b/src/plugins/e-acsl/src/code_generator/at_with_lscope.ml new file mode 100644 index 0000000000000000000000000000000000000000..d34af61bc0372dec96ea5ebeb3fef2d5eaf4b440 --- /dev/null +++ b/src/plugins/e-acsl/src/code_generator/at_with_lscope.ml @@ -0,0 +1,349 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C's E-ACSL plug-in. *) +(* *) +(* Copyright (C) 2012-2018 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +open Cil_types + +(**************************************************************************) +(********************** Forward references ********************************) +(**************************************************************************) + +let predicate_to_exp_ref + : (kernel_function -> Env.t -> predicate -> exp * Env.t) ref + = Extlib.mk_fun "named_predicate_to_exp_ref" + +let term_to_exp_ref + : (kernel_function -> Env.t -> term -> exp * Env.t) ref + = Extlib.mk_fun "term_to_exp_ref" + +(*****************************************************************************) +(**************************** Handling memory ********************************) +(*****************************************************************************) + +(* Remove all the bindings for [kf]. [Cil_datatype.Kf.Hashtbl] does not + provide the [remove_all] function. Thus we need to keep calling [remove] + until all entries are removed. *) +let rec remove_all tbl kf = + if Cil_datatype.Kf.Hashtbl.mem tbl kf then begin + Cil_datatype.Kf.Hashtbl.remove tbl kf; + remove_all tbl kf + end + +module Malloc = struct + let tbl = Cil_datatype.Kf.Hashtbl.create 7 + let add kf stmt = Cil_datatype.Kf.Hashtbl.add tbl kf stmt + let find_all kf = Cil_datatype.Kf.Hashtbl.find_all tbl kf + let remove_all kf = remove_all tbl kf +end + +module Free = struct + let tbl = Cil_datatype.Kf.Hashtbl.create 7 + let add kf stmt = Cil_datatype.Kf.Hashtbl.add tbl kf stmt + let find_all kf = Cil_datatype.Kf.Hashtbl.find_all tbl kf + let remove_all kf = remove_all tbl kf +end + +(**************************************************************************) +(*************************** Translation **********************************) +(**************************************************************************) + +(* Builds the terms [t_size] and [t_shifted] from each + [Lvs_quantif(tmin, lv, tmax)] from [lscope] + where [t_size = tmax - tmin + (-1|0|1)] depending on whether the + inequalities are strict or large + and [t_shifted = lv - tmin + (-1|0)] (so that we start indexing at 0) *) +let rec sizes_and_shifts_from_quantifs ~loc kf lscope sizes_and_shifts = + match lscope with + | [] -> + sizes_and_shifts + | Lscope.Lvs_quantif(tmin, _, _, _, tmax) ::_ + when Misc.term_has_lv_from_vi tmin || Misc.term_has_lv_from_vi tmax -> + Error.not_yet "\\at with logic variable linked to C variable" + | Lscope.Lvs_quantif(tmin, rel1, lv, rel2, tmax) :: lscope' -> + let t_size = Logic_const.term ~loc (TBinOp(MinusA, tmax, tmin)) Linteger in + let t_size = match rel1, rel2 with + | Rle, Rle -> + Logic_const.term + ~loc + (TBinOp(PlusA, t_size, Cil.lone ~loc ())) + Linteger + | Rlt, Rle | Rle, Rlt -> + t_size + | Rlt, Rlt -> + Logic_const.term + ~loc + (TBinOp(MinusA, t_size, Cil.lone ~loc ())) + Linteger + | _ -> + Options.fatal "Unexpected comparison operator" + in + let iv = Interval.(extract_ival (infer t_size)) in + (* The EXACT amount of memory that is needed can be known at runtime. This + is because the tightest bounds for the variables can be known at runtime. + Example: In the following predicate + [\exists integer u; 9 <= u <= 13 && + \forall integer v; -5 < v <= (u <= 11 ? u + 6 : u - 9) ==> + \at(u + v > 0, K)] + the upper bound [M] for [v] depends on [u]. + In chronological order, [M] equals to 15, 16, 17, 3 and 4. + Thus the tightest upper bound for [v] is [max(M)=17]. + HOWEVER, computing that exact information requires extra nested loops, + prior to the [malloc] stmts, that will try all the possible values of the + variables involved in the bounds. + Instead of sacrificing time over memory (by performing these extra + computations), we consider that sacrificing memory over time is more + beneficial. In particular, though we may allocate more memory than + needed, the number of reads/writes into it is the same in both cases. + Conclusion: over-approximate [t_size] *) + let t_size = match Ival.min_and_max iv with + | _, Some max -> + Logic_const.tint ~loc max + | _, None -> + Error.not_yet + "\\at on purely logic variables and with quantifier that uses \ + too complex bound (E-ACSL cannot infer a finite upper bound to it)" + in + (* Index *) + let t_lv = Logic_const.tvar ~loc lv in + let t_shifted = match rel1 with + | Rle -> + Logic_const.term ~loc (TBinOp(MinusA, t_lv, tmin)) Linteger + | Rlt -> + let t = Logic_const.term ~loc (TBinOp(MinusA, t_lv, tmin)) Linteger in + Logic_const.term ~loc (TBinOp(MinusA, t, Cil.lone ~loc())) Linteger + | _ -> + Options.fatal "Unexpected comparison operator" + in + (* Returning *) + let sizes_and_shifts = (t_size, t_shifted) :: sizes_and_shifts in + sizes_and_shifts_from_quantifs ~loc kf lscope' sizes_and_shifts + | (Lscope.Lvs_let(_, t) | Lscope.Lvs_global(_, t)) :: _ + when Misc.term_has_lv_from_vi t -> + Error.not_yet "\\at with logic variable linked to C variable" + | Lscope.Lvs_let _ :: lscope' -> + sizes_and_shifts_from_quantifs ~loc kf lscope' sizes_and_shifts + | Lscope.Lvs_formal _ :: _ -> + Error.not_yet "\\at using formal variable of a logic function" + | Lscope.Lvs_global _ :: _ -> + Error.not_yet "\\at using global logic variable" + +let size_from_sizes_and_shifts ~loc = function + | [] -> + (* No quantified variable. But still need to allocate [1*sizeof(_)] amount + of memory to store purely logic variables that are NOT quantified + (example: from \let). *) + Cil.lone ~loc () + | (size, _) :: sizes_and_shifts -> + List.fold_left + (fun t_size (t_s, _) -> + Logic_const.term ~loc (TBinOp(Mult, t_size, t_s)) Linteger) + size + sizes_and_shifts + +(* Build the left-value corresponding to [*(at + index)]. *) +let lval_at_index ~loc kf env (e_at, vi_at, t_index) = + Typing.type_term ~use_gmp_opt:false ~ctx:Typing.c_int t_index; + let term_to_exp = !term_to_exp_ref in + let e_index, env = term_to_exp kf env t_index in + let e_index = Cil.constFold false e_index in + let e_addr = + Cil.new_exp ~loc (BinOp(PlusPI, e_at, e_index, vi_at.vtype)) + in + let lval_at_index = Mem e_addr, NoOffset in + lval_at_index, env + +(* Associate to each possible tuple of quantifiers + a unique index from the set {n | 0 <= n < n_max}. + That index will serve to identify the memory location where the evaluation + of the term/predicate is stored for the given tuple of quantifier. + The following gives the smallest set of such indexes (hence we use the + smallest amount of memory in some respect): + To (t_shifted_n, t_shifted_n-1, ..., t_shifted_1) + where 0 <= t_shifted_i < beta_i + corresponds: \sum_{i=1}^n( t_shifted_i * \pi_{j=1}^{i-1}(beta_j) ) *) +let index_from_sizes_and_shifts ~loc sizes_and_shifts = + let product terms = List.fold_left + (fun product t -> + Logic_const.term ~loc (TBinOp(Mult, product, t)) Linteger) + (Cil.lone ~loc ()) + terms + in + let sum, _ = List.fold_left + (fun (index, sizes) (t_size, t_shifted) -> + let pi_beta_j = product sizes in + let bi_mult_pi_beta_j = + Logic_const.term ~loc (TBinOp(Mult, t_shifted, pi_beta_j)) Linteger + in + let sum = Logic_const.term + ~loc + (TBinOp(PlusA, bi_mult_pi_beta_j, index)) + Linteger + in + sum, t_size :: sizes) + (Cil.lzero ~loc (), []) + sizes_and_shifts + in + sum + +let put_block_at_label env block label = + let stmt = Label.get_stmt (Env.get_visitor env) label in + let env_ref = ref env in + let o = object + inherit Visitor.frama_c_inplace + method !vstmt_aux stmt = + assert (!env_ref == env); + env_ref := Env.extend_stmt_in_place env stmt ~label block; + Cil.ChangeTo stmt + end + in + let bhv = Env.get_behavior env in + ignore(Visitor.visitFramacStmt o (Visitor_behavior.Get.stmt bhv stmt)); + !env_ref + +let to_exp ~loc kf env pot label = + let term_to_exp = !term_to_exp_ref in + let lscope_vars = Lscope.get_all (Env.Logic_scope.get env) in + let sizes_and_shifts = + sizes_and_shifts_from_quantifs ~loc kf lscope_vars [] + in + (* Creating the pointer *) + let ty = match pot with + | Misc.PoT_pred _ -> + Cil.intType + | Misc.PoT_term t -> + begin match Typing.get_number_ty t with + | Typing.(C_integer _ | C_float _ | Nan) -> + Typing.get_typ t + | Typing.(Rational | Real) -> + Error.not_yet "\\at on purely logic variables and over real type" + | Typing.Gmpz -> + Error.not_yet "\\at on purely logic variables and over gmp type" + end + in + let ty_ptr = TPtr(ty, []) in + let vi_at, e_at, env = Env.new_var + ~loc + ~name:"at" + ~scope:Varname.Function + env + None + ty_ptr + (fun vi e -> + (* Handle [malloc] and [free] stmts *) + let lty_sizeof = Ctype Cil.(theMachine.typeOfSizeOf) in + let t_sizeof = Logic_const.term ~loc (TSizeOf ty) lty_sizeof in + let t_size = size_from_sizes_and_shifts ~loc sizes_and_shifts in + let t_size = + Logic_const.term ~loc (TBinOp(Mult, t_sizeof, t_size)) lty_sizeof + in + Typing.type_term ~use_gmp_opt:false t_size; + let malloc_stmt = match Typing.get_number_ty t_size with + | Typing.C_integer IInt -> + let e_size, _ = term_to_exp kf env t_size in + let e_size = Cil.constFold false e_size in + let malloc_stmt = + Misc.mk_call ~loc ~result:(Cil.var vi) "malloc" [e_size] + in + malloc_stmt + | Typing.(C_integer _ | C_float _ | Gmpz) -> + Error.not_yet + "\\at on purely logic variables that needs to allocate \ + too much memory (bigger than int_max bytes)" + | Typing.(Rational | Real | Nan) -> + Error.not_yet "quantification over non-integer type" + in + let free_stmt = Misc.mk_call ~loc "free" [e] in + (* The list of stmts returned by the current closure are inserted + LOCALLY to the block where the new var is FIRST used, whatever scope + is indicated to [Env.new_var]. + Thus we need to add [malloc] and [free] through dedicated functions. *) + Malloc.add kf malloc_stmt; + Free.add kf free_stmt; + []) + in + (* Index *) + let t_index = index_from_sizes_and_shifts ~loc sizes_and_shifts in + (* Innermost block *) + let mk_innermost_block env = + let term_to_exp = !term_to_exp_ref in + let named_predicate_to_exp = !predicate_to_exp_ref in + match pot with + | Misc.PoT_pred p -> + let env = Env.push env in + let lval, env = lval_at_index ~loc kf env (e_at, vi_at, t_index) in + let e, env = named_predicate_to_exp kf env p in + let e = Cil.constFold false e in + let storing_stmt = + Cil.mkStmtOneInstr ~valid_sid:true (Set(lval, e, loc)) + in + let block, env = + Env.pop_and_get env storing_stmt ~global_clear:false Env.After + in + (* We CANNOT return [block.bstmts] because it does NOT contain + variable declarations. *) + [ Cil.mkStmt ~valid_sid:true (Block block) ], env + | Misc.PoT_term t -> + begin match Typing.get_number_ty t with + | Typing.(C_integer _ | C_float _ | Nan) -> + let env = Env.push env in + let lval, env = lval_at_index ~loc kf env (e_at, vi_at, t_index) in + let e, env = term_to_exp kf env t in + let e = Cil.constFold false e in + let storing_stmt = + Cil.mkStmtOneInstr ~valid_sid:true (Set(lval, e, loc)) + in + let block, env = + Env.pop_and_get env storing_stmt ~global_clear:false Env.After + in + (* We CANNOT return [block.bstmts] because it does NOT contain + variable declarations. *) + [ Cil.mkStmt ~valid_sid:true (Block block) ], env + | Typing.(Rational | Real) -> + Error.not_yet "\\at on purely logic variables and over real type" + | Typing.Gmpz -> + Error.not_yet "\\at on purely logic variables and over gmp type" + end + in + (* Storing loops *) + let lscope_vars = Lscope.get_all (Env.Logic_scope.get env) in + let env = Env.push env in + let storing_loops_stmts, env = + Loops.mk_nested_loops ~loc mk_innermost_block kf env lscope_vars + in + let storing_loops_block = Cil.mkBlock storing_loops_stmts in + let storing_loops_block, env = Env.pop_and_get + env + (Cil.mkStmt ~valid_sid:true (Block storing_loops_block)) + ~global_clear:false + Env.After + in + (* Put at label *) + let env = put_block_at_label env storing_loops_block label in + (* Returning *) + let lval_at_index, env = lval_at_index ~loc kf env (e_at, vi_at, t_index) in + let e = Cil.new_exp ~loc (Lval lval_at_index) in + e, env + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff --git a/src/plugins/e-acsl/src/code_generator/at_with_lscope.mli b/src/plugins/e-acsl/src/code_generator/at_with_lscope.mli new file mode 100644 index 0000000000000000000000000000000000000000..70ad6f00677195183e37de6e6ba53f6926b2ce11 --- /dev/null +++ b/src/plugins/e-acsl/src/code_generator/at_with_lscope.mli @@ -0,0 +1,75 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C's E-ACSL plug-in. *) +(* *) +(* Copyright (C) 2012-2018 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +open Cil_types +open Cil_datatype + +(* Convert \at on terms or predicates in which we can find purely + logic variable. *) + +(**************************************************************************) +(*************************** Translation **********************************) +(**************************************************************************) + +val to_exp: + loc:Location.t -> kernel_function -> Env.t -> + Misc.pred_or_term -> logic_label -> exp * Env.t + +(*****************************************************************************) +(**************************** Handling memory ********************************) +(*****************************************************************************) + +(* The different possible evaluations of the [\at] under study are + stored in a memory location that needs to be alloted then freed. + This part is designed for that purpose. *) + +module Malloc: sig + val find_all: kernel_function -> stmt list + (* Return the list of [malloc] stmts that need to be inserted into [kf]. *) + + val remove_all: kernel_function -> unit + (* Remove all [malloc] stmts for [kf] from the internal table. *) +end + +module Free: sig + val find_all: kernel_function -> stmt list + (* Return the list of [free] stmts that need to be inserted into [kf]. *) + + val remove_all: kernel_function -> unit + (* Remove all [free] stmts for [kf] from the internal table. *) +end + +(**************************************************************************) +(********************** Forward references ********************************) +(**************************************************************************) + +val predicate_to_exp_ref: + (kernel_function -> Env.t -> predicate -> exp * Env.t) ref + +val term_to_exp_ref: + (kernel_function -> Env.t -> term -> exp * Env.t) ref + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff --git a/src/plugins/e-acsl/src/code_generator/env.ml b/src/plugins/e-acsl/src/code_generator/env.ml new file mode 100644 index 0000000000000000000000000000000000000000..c9d441ac976e8408b0b4ecaa311412537e9eab57 --- /dev/null +++ b/src/plugins/e-acsl/src/code_generator/env.ml @@ -0,0 +1,524 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C's E-ACSL plug-in. *) +(* *) +(* Copyright (C) 2012-2018 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +module E_acsl_label = Label +open Cil_types +open Cil_datatype + +type localized_scope = + | LGlobal + | LFunction of kernel_function + | LLocal_block of kernel_function + +type mp_tbl = { + new_exps: (varinfo * exp) Term.Map.t; + (* generated mp variables as exp from terms *) + clear_stmts: stmt list; + (* stmts freeing the memory before exiting the block *) +} + +type block_info = { + new_block_vars: varinfo list; + (* generated variables local to the block *) + new_stmts: stmt list; + (* generated stmts to put at the beginning of the block *) + pre_stmts: stmt list; + (* stmts already inserted into the current stmt, + but which should be before [new_stmts]. *) + post_stmts: stmt list; +} + +type local_env = { + block_info: block_info; + mp_tbl: mp_tbl; + rte: bool +} + +type t = { + visitor: Visitor.frama_c_visitor; + lscope: Lscope.t; + lscope_reset: bool; + annotation_kind: Misc.annotation_kind; + new_global_vars: (varinfo * localized_scope) list; + (* generated variables. The scope indicates the level where the variable + should be added. *) + global_mp_tbl: mp_tbl; + env_stack: local_env list; + var_mapping: Varinfo.t Stack.t Logic_var.Map.t; + (* records of C bindings for logic vars *) + loop_invariants: predicate list list; + (* list of loop invariants for each currently visited loops *) + cpt: int; + (* counter used when generating variables *) +} + +let empty_block = + { new_block_vars = []; + new_stmts = []; + pre_stmts = []; + post_stmts = [] } + +let empty_mp_tbl = + { new_exps = Term.Map.empty; + clear_stmts = [] } + +let empty_local_env = + { block_info = empty_block; + mp_tbl = empty_mp_tbl; + rte = true } + +let dummy = + { visitor = new Visitor.generic_frama_c_visitor (Visitor_behavior.inplace ()); + lscope = Lscope.empty; + lscope_reset = true; + annotation_kind = Misc.Assertion; + new_global_vars = []; + global_mp_tbl = empty_mp_tbl; + env_stack = []; + var_mapping = Logic_var.Map.empty; + loop_invariants = []; + cpt = 0; } + +let empty v = + { visitor = v; + lscope = Lscope.empty; + lscope_reset = true; + annotation_kind = Misc.Assertion; + new_global_vars = []; + global_mp_tbl = empty_mp_tbl; + env_stack = []; + var_mapping = Logic_var.Map.empty; + loop_invariants = []; + cpt = 0 } + +let top env = match env.env_stack with + | [] -> Options.fatal "Empty environment. That is unexpected." + | hd :: tl -> hd, tl + +let has_no_new_stmt env = + let local, _ = top env in + local.block_info = empty_block + +let current_kf env = + let v = env.visitor in + match v#current_kf with + | None -> None + | Some kf -> Some (Visitor_behavior.Get.kernel_function v#behavior kf) + +let set_current_kf env kf = + let v = env.visitor in + v#set_current_kf kf + +let get_visitor env = env.visitor +let get_behavior env = env.visitor#behavior + +(* ************************************************************************** *) +(** {2 Loop invariants} *) +(* ************************************************************************** *) + +let push_loop env = + { env with loop_invariants = [] :: env.loop_invariants } + +let add_loop_invariant env inv = match env.loop_invariants with + | [] -> assert false + | invs :: tl -> { env with loop_invariants = (inv :: invs) :: tl } + +let pop_loop env = match env.loop_invariants with + | [] -> assert false + | invs :: tl -> invs, { env with loop_invariants = tl } + +(* ************************************************************************** *) +(** {2 RTEs} *) +(* ************************************************************************** *) + +let rte env b = + let local_env, tl_env = top env in + { env with env_stack = { local_env with rte = b } :: tl_env } + +let generate_rte env = + let local_env, _ = top env in + local_env.rte + +(* ************************************************************************** *) + +(* eta-expansion required for typing generalisation *) +let acc_list_rev acc l = List.fold_left (fun acc x -> x :: acc) acc l + +let do_new_var ~loc ?(scope=Varname.Block) ?(name="") env t ty mk_stmts = + let local_env, tl_env = top env in + let local_block = local_env.block_info in + let is_z_t = Gmp_types.Z.is_t ty in + if is_z_t then Gmp_types.Z.is_now_referenced (); + let is_q_t = Gmp_types.Q.is_t ty in + if is_q_t then Gmp_types.Q.is_now_referenced (); + let n = succ env.cpt in + let v = + Cil.makeVarinfo + ~source:true + false (* is a global? *) + false (* is a formal? *) + ~referenced:true + (Varname.get ~scope (Functions.RTL.mk_gen_name name)) + ty + in + v.vreferenced <- true; + let lscope = match scope with + | Varname.Global -> LGlobal + | Varname.Function -> LFunction (Extlib.the (current_kf env)) + | Varname.Block -> LLocal_block (Extlib.the (current_kf env)) + in +(* Options.feedback "new variable %a (global? %b)" Varinfo.pretty v global;*) + let e = Cil.evar v in + let stmts = mk_stmts v e in + let new_stmts = acc_list_rev local_block.new_stmts stmts in + let new_block_vars = match scope with + | Varname.Global | Varname.Function -> local_block.new_block_vars + | Varname.Block -> v :: local_block.new_block_vars + in + let new_block = + { new_block_vars = new_block_vars; + new_stmts = new_stmts; + pre_stmts = local_block.pre_stmts; + post_stmts = local_block.post_stmts + } + in + v, + e, + if is_z_t || is_q_t then begin + let extend_tbl tbl = +(* Options.feedback "memoizing %a for term %a" + Varinfo.pretty v (fun fmt t -> match t with None -> Format.fprintf fmt + "NONE" | Some t -> Term.pretty fmt t) t;*) + { clear_stmts = Gmp.clear ~loc e :: tbl.clear_stmts; + new_exps = match t with + | None -> tbl.new_exps + | Some t -> Term.Map.add t (v, e) tbl.new_exps } + in + match scope with + | Varname.Global | Varname.Function -> + let local_env = { local_env with block_info = new_block } in + (* also memoize the new variable, but must never be used *) + { env with + cpt = n; + new_global_vars = (v, lscope) :: env.new_global_vars; + global_mp_tbl = extend_tbl env.global_mp_tbl; + env_stack = local_env :: tl_env } + | Varname.Block -> + let local_env = + { block_info = new_block; + mp_tbl = extend_tbl local_env.mp_tbl; + rte = false (* must be already checked by mk_stmts *) } + in + { env with + cpt = n; + env_stack = local_env :: tl_env; + new_global_vars = (v, lscope) :: env.new_global_vars } + end else + let new_global_vars = (v, lscope) :: env.new_global_vars in + let local_env = + { local_env with + block_info = new_block; + rte = false (* must be already checked by mk_stmts *) } + in + { env with + new_global_vars = new_global_vars; + cpt = n; + env_stack = local_env :: tl_env } + +exception No_term + +let new_var ~loc ?(scope=Varname.Block) ?name env t ty mk_stmts = + let local_env, _ = top env in + let memo tbl = + try + match t with + | None -> raise No_term + | Some t -> + let v, e = Term.Map.find t tbl.new_exps in + if Typ.equal ty v.vtype then v, e, env else raise No_term + with Not_found | No_term -> + do_new_var ~loc ~scope ?name env t ty mk_stmts + in + match scope with + | Varname.Global | Varname.Function -> memo env.global_mp_tbl + | Varname.Block -> memo local_env.mp_tbl + +let new_var_and_mpz_init ~loc ?scope ?name env t mk_stmts = + new_var + ~loc + ?scope + ?name + env + t + (Gmp_types.Z.t ()) + (fun v e -> Gmp.init ~loc e :: mk_stmts v e) + +module Logic_binding = struct + + let add_binding env logic_v vi = + try + let varinfos = Logic_var.Map.find logic_v env.var_mapping in + Stack.push vi varinfos; + env + with Not_found | Stack.Empty -> + let varinfos = Stack.create () in + Stack.push vi varinfos; + let var_mapping = Logic_var.Map.add logic_v varinfos env.var_mapping in + { env with var_mapping = var_mapping } + + let add ?ty env logic_v = + let ty = match ty with + | Some ty -> ty + | None -> match logic_v.lv_type with + | Ctype ty -> ty + | Linteger -> Gmp_types.Z.t () + | Ltype _ as ty when Logic_const.is_boolean_type ty -> Cil.charType + | Ltype _ | Lvar _ | Lreal | Larrow _ as lty -> + let msg = + Format.asprintf + "logic variable of type %a" Logic_type.pretty lty + in + Error.not_yet msg + in + let v, e, env = + new_var + ~loc:Location.unknown + env + ~name:logic_v.lv_name + None + ty + (fun _ _ -> []) + in + v, e, add_binding env logic_v v + + let get env logic_v = + try + let varinfos = Logic_var.Map.find logic_v env.var_mapping in + Stack.top varinfos + with Not_found | Stack.Empty -> + assert false + + let remove env logic_v = + try + let varinfos = Logic_var.Map.find logic_v env.var_mapping in + ignore (Stack.pop varinfos) + with Not_found | Stack.Empty -> + assert false + +end + +module Logic_scope = struct + let get env = env.lscope + let extend env lvs = { env with lscope = Lscope.add lvs env.lscope } + let set_reset env bool = { env with lscope_reset = bool } + let get_reset env = env.lscope_reset + let reset env = + if env.lscope_reset then { env with lscope = Lscope.empty } + else env +end + +let emitter = + Emitter.create + "E_ACSL" + [ Emitter.Code_annot ] + ~correctness:[ Options.Gmp_only.parameter ] + ~tuning:[] + +let add_assert env stmt annot = match current_kf env with + | None -> assert false + | Some kf -> + Queue.add + (fun () -> Annotations.add_assert emitter ~kf stmt annot) + env.visitor#get_filling_actions + +let add_stmt ?(post=false) ?before env stmt = + if not post then + Extlib.may (fun old -> E_acsl_label.move env.visitor ~old stmt) before; + let local_env, tl = top env in + let block = local_env.block_info in + let block = + if post then + { block with post_stmts = stmt :: block.post_stmts } + else + { block with new_stmts = stmt :: block.new_stmts } + in + let local_env = { local_env with block_info = block } in + { env with env_stack = local_env :: tl } + +let extend_stmt_in_place env stmt ~label block = + let new_stmt = Cil.mkStmt ~valid_sid:true (Block block) in + let sk = stmt.skind in + stmt.skind <- + Block (Cil.mkBlock [ new_stmt; Cil.mkStmt ~valid_sid:true sk ]); + let pre = match label with + | BuiltinLabel(Here | Post) -> true + | BuiltinLabel(Old | Pre | LoopEntry | LoopCurrent | Init) + | FormalLabel _ | StmtLabel _ -> false + in + if pre then + let local_env, tl_env = top env in + let b_info = local_env.block_info in + let b_info = { b_info with pre_stmts = new_stmt :: b_info.pre_stmts } in + { env with env_stack = { local_env with block_info = b_info } :: tl_env } + else + env + +let push env = +(* Options.feedback "push (was %d)" (List.length env.env_stack);*) + { env with env_stack = empty_local_env :: env.env_stack } + +let pop env = +(* Options.feedback "pop";*) + let _, tl = top env in + { env with env_stack = tl } + +let transfer ~from env = match from.env_stack, env.env_stack with + | { block_info = from_blk } :: _, ({ block_info = env_blk } as local) :: tl + -> + let new_blk = + { new_block_vars = from_blk.new_block_vars @ env_blk.new_block_vars; + new_stmts = from_blk.new_stmts @ env_blk.new_stmts; + pre_stmts = from_blk.pre_stmts @ env_blk.pre_stmts; + post_stmts = from_blk.post_stmts @ env_blk.post_stmts } + in + { env with env_stack = { local with block_info = new_blk } :: tl } + | _, _ -> + assert false + +type where = Before | Middle | After +let pop_and_get ?(split=false) env stmt ~global_clear where = + let split = split && stmt.labels = [] in +(* Options.feedback "pop_and_get from %a (%b)" Printer.pp_stmt stmt split;*) + let local_env, tl = top env in + let clear = + if global_clear then begin + Varname.clear_locals (); + env.global_mp_tbl.clear_stmts @ local_env.mp_tbl.clear_stmts + end else + local_env.mp_tbl.clear_stmts + in +(* Options.feedback "clearing %d mpz (global_clear: %b)" + (List.length clear) global_clear;*) + let block = local_env.block_info in + let b = + let pre_stmts, stmt = + let rec extract stmt acc = function + | [] -> acc, stmt + | _ :: tl -> + match stmt.skind with + | Block { bstmts = [ fst; snd ] } -> extract snd (fst :: acc) tl + | _ -> + Kernel.fatal + "experting a block containing 2 statements instead of %a" + Printer.pp_stmt stmt + in + extract stmt [] block.pre_stmts + in + let new_s = block.new_stmts in + let cat stmt l = match stmt.skind with + | Instr(Skip _) -> l + | _ -> stmt :: l + in + let stmts = + match where with + | Before -> cat stmt (acc_list_rev (List.rev clear) new_s) + | Middle -> acc_list_rev (cat stmt (List.rev clear)) new_s + | After -> + (* if [split], do not put the given [stmt] in the generated block *) + let stmts = if split then [] else cat stmt [] in + acc_list_rev (acc_list_rev stmts clear) new_s + in + Cil.mkBlock (acc_list_rev stmts pre_stmts) + in + b.blocals <- acc_list_rev b.blocals block.new_block_vars; + let b = + (* blocks with local cannot be transient (see doc in cil.ml), + while transient blocks prevent the E-ACSL labeling strategy from working + properly: no transient block in that cases. *) + if b.blocals = [] && stmt.labels = [] then Cil.transient_block b + else b + in + let final_blk = + (* if [split], put the generated code in a distinct sub-block and + add the given [stmt] afterwards. This way, we have the guarantee that + the final block does not contain any local, so may be transient. *) + if split then + match stmt.skind with + | Instr (Skip _) -> b + | _ -> + let sblock = Cil.mkStmt ~valid_sid:true (Block b) in + Cil.transient_block (Cil.mkBlock [ sblock; stmt ]) + else + b + in + (* remove superfluous brackets inside the generated block *) + let final_blk = Cil.flatten_transient_sub_blocks final_blk in + (* remove the non-scoping mark of the outermost block *) + let final_blk = Cil.block_of_transient final_blk in + (* add post-block statements *) + final_blk.bstmts <- final_blk.bstmts @ block.post_stmts; + final_blk, { env with env_stack = tl } + +let get_generated_variables env = List.rev env.new_global_vars + +let annotation_kind env = env.annotation_kind +let set_annotation_kind env k = { env with annotation_kind = k } + +module Context = struct + + let ctx = ref [] + let save env = ctx := env.new_global_vars + let restore env = + if !ctx <> [] then begin + let vars = env.new_global_vars in + let env = + { env with new_global_vars = + List.filter + (fun (v, scope) -> + (match scope with + | LGlobal | LFunction _ -> true + | LLocal_block _ -> false) + && List.for_all (fun (v', _) -> v != v') vars) + !ctx + @ vars } + in + ctx := []; + env + end else + env + +end + +(* debugging purpose *) +let pretty fmt env = + let local_env, _ = top env in + Format.fprintf fmt "local new_stmts %t" + (fun fmt -> + List.iter + (fun s -> Printer.pp_stmt fmt s) + local_env.block_info.new_stmts) + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff --git a/src/plugins/e-acsl/src/code_generator/env.mli b/src/plugins/e-acsl/src/code_generator/env.mli new file mode 100644 index 0000000000000000000000000000000000000000..6e81ceb739527d7ac738ef7626c29682451cb7d7 --- /dev/null +++ b/src/plugins/e-acsl/src/code_generator/env.mli @@ -0,0 +1,184 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C's E-ACSL plug-in. *) +(* *) +(* Copyright (C) 2012-2018 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +open Cil_types + +(** Environments. + + Environments handle all the new C constructs (variables, statements and + annotations. *) + +type t + +val dummy: t +val empty: Visitor.frama_c_visitor -> t + +val has_no_new_stmt: t -> bool +(** Assume that a local context has been previously pushed. + @return true iff the given env does not contain any new statement. *) + +type localized_scope = + | LGlobal + | LFunction of kernel_function + | LLocal_block of kernel_function + +val new_var: + loc:location -> ?scope:Varname.scope -> ?name:string -> + t -> term option -> typ -> + (varinfo -> exp (* the var as exp *) -> stmt list) -> + varinfo * exp * t +(** [new_var env t ty mk_stmts] extends [env] with a fresh variable of type + [ty] corresponding to [t]. [scope] is the scope of the new variable (default + is [Block]). + @return this variable as both a C variable and a C expression already + initialized by applying it to [mk_stmts]. *) + +val new_var_and_mpz_init: + loc:location -> ?scope:Varname.scope -> ?name:string -> + t -> term option -> + (varinfo -> exp (* the var as exp *) -> stmt list) -> + varinfo * exp * t +(** Same as [new_var], but dedicated to mpz_t variables initialized by + {!Mpz.init}. *) + +module Logic_binding: sig + val add: ?ty:typ -> t -> logic_var -> varinfo * exp * t + (* Add a new C binding to the list of bindings for the logic variable. *) + + val add_binding: t -> logic_var -> varinfo -> t + (* [add_binding env lv vi] defines [vi] as the latest C binding for + [lv]. *) + + val get: t -> logic_var -> varinfo + (* Return the latest C binding. *) + + val remove: t -> logic_var -> unit + (* Remove the latest C binding. *) + +end + +val add_assert: t -> stmt -> predicate -> unit +(** [add_assert env s p] associates the assertion [p] to the statement [s] in + the environment [env]. *) + +val add_stmt: ?post:bool -> ?before:stmt -> t -> stmt -> t +(** [add_stmt env s] extends [env] with the new statement [s]. + [before] may define which stmt the new one is included before. This is to + say that any labels attached to [before] are moved to [stmt]. [post] + indicates that [stmt] should be added after the target statement. *) + +val extend_stmt_in_place: t -> stmt -> label:logic_label -> block -> t +(** [extend_stmt_in_place env stmt ~label b] modifies [stmt] in place in + order to add the given [block]. If [label] is [Here] or [Post], + then this block is guaranteed to be at the first place of the resulting + [stmt] whatever modification will be done by the visitor later. *) + +val push: t -> t +(** Push a new local context in the environment *) + +type where = Before | Middle | After +val pop_and_get: + ?split:bool -> t -> stmt -> global_clear:bool -> where -> block * t +(** Pop the last local context and get back the corresponding new block + containing the given [stmt] at the given place ([Before] is before the code + corresponding to annotations, [After] is after this code and [Middle] is + between the stmt corresponding to annotations and the ones for freeing the + memory. When [where] is [After], set [split] to true in order to generate + one block which contains exactly 2 stmt: one for [stmt] and one sub-block + for the generated stmts. *) + +val pop: t -> t +(** Pop the last local context (ignore the corresponding new block if any *) + +val transfer: from:t -> t -> t +(** Pop the last local context of [from] and push it into the other env. *) + +val get_generated_variables: t -> (varinfo * localized_scope) list +(** All the new variables local to the visited function. *) + +val get_visitor: t -> Visitor.generic_frama_c_visitor +val get_behavior: t -> Visitor_behavior.t +val current_kf: t -> kernel_function option +(** Kernel function currently visited in the new project. *) + +module Logic_scope: sig + val get: t -> Lscope.t + (** Return the logic scope associated to the environment. *) + + val extend: t -> Lscope.lscope_var -> t + (** Add a new logic variable with its associated information in the + logic scope of the environment. *) + + val reset: t -> t + (** Return a new environment in which the logic scope is reset + iff [set_reset _ true] has been called beforehand. Do nothing otherwise. *) + + val set_reset: t -> bool -> t + (** Setter of the information indicating whether the logic scope should be + reset at next call to [reset]. *) + + val get_reset: t -> bool + (** Getter of the information indicating whether the logic scope should be + reset at next call to [reset]. *) +end + +val set_current_kf: t -> kernel_function -> unit +(* Set current kf of the environment *) + +(* ************************************************************************** *) +(** {2 Current annotation kind} *) +(* ************************************************************************** *) + +val annotation_kind: t -> Misc.annotation_kind +val set_annotation_kind: t -> Misc.annotation_kind -> t + +(* ************************************************************************** *) +(** {2 Loop invariants} *) +(* ************************************************************************** *) + +val push_loop: t -> t +val add_loop_invariant: t -> predicate -> t +val pop_loop: t -> predicate list * t + +(* ************************************************************************** *) +(** {2 RTEs} *) +(* ************************************************************************** *) + +val rte: t -> bool -> t +val generate_rte: t -> bool + +(* ************************************************************************** *) +(** {2 Context for error handling} *) +(* ************************************************************************** *) + +module Context: sig + val save: t -> unit + val restore: t -> t +end + +val pretty: Format.formatter -> t -> unit + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff --git a/src/plugins/e-acsl/src/code_generator/gmp.ml b/src/plugins/e-acsl/src/code_generator/gmp.ml new file mode 100644 index 0000000000000000000000000000000000000000..c2839c8a2cc66b77263810ecb086731c2228a976 --- /dev/null +++ b/src/plugins/e-acsl/src/code_generator/gmp.ml @@ -0,0 +1,127 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C's E-ACSL plug-in. *) +(* *) +(* Copyright (C) 2012-2018 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +open Cil_types + +(**************************************************************************) +(************************* Calls to builtins ******************************) +(**************************************************************************) + +let apply_on_var ~loc funname e = + let prefix = + let ty = Cil.typeOf e in + if Gmp_types.Z.is_t ty then "__gmpz_" + else if Gmp_types.Q.is_t ty then "__gmpq_" + else assert false + in + Misc.mk_call ~loc (prefix ^ funname) [ e ] + +let init ~loc e = apply_on_var "init" ~loc e +let clear ~loc e = apply_on_var "clear" ~loc e + +exception Longlong of ikind + +let get_set_suffix_and_arg e = + let ty = Cil.typeOf e in + if Gmp_types.Z.is_t ty || Gmp_types.Q.is_t ty then "", [ e ] + else + match Cil.unrollType ty with + | TInt(IChar, _) -> + (if Cil.theMachine.Cil.theMachine.char_is_unsigned then "_ui" + else "_si"), + [ e ] + | TInt((IBool | IUChar | IUInt | IUShort | IULong), _) -> + "_ui", [ e ] + | TInt((ISChar | IShort | IInt | ILong), _) -> "_si", [ e ] + | TInt((ILongLong | IULongLong as ikind), _) -> raise (Longlong ikind) + | TPtr(TInt(IChar, _), _) -> + "_str", + (* decimal base for the number given as string *) + [ e; Cil.integer ~loc:e.eloc 10 ] + | TFloat((FDouble | FFloat), _) -> + (* FFloat is a strict subset of FDouble (modulo exceptional numbers) + Hence, calling [set_d] for both of them is sound. + HOWEVER: the machdep MUST NOT be vulnerable to double rounding + [TODO] check the statement above *) + "_d", [ e ] + | TFloat(FLongDouble, _) -> + Error.not_yet "creating gmp from long double" + | _ -> + assert false + +let generic_affect ~loc fname lv ev e = + let ty = Cil.typeOf ev in + if Gmp_types.Z.is_t ty || Gmp_types.Q.is_t ty then begin + let suf, args = get_set_suffix_and_arg e in + Misc.mk_call ~loc (fname ^ suf) (ev :: args) + end else + Cil.mkStmtOneInstr ~valid_sid:true (Set(lv, e, e.eloc)) + +let init_set ~loc lv ev e = + let fname = + let ty = Cil.typeOf ev in + if Gmp_types.Z.is_t ty then + "__gmpz_init_set" + else if Gmp_types.Q.is_t ty then + Options.fatal "no __gmpq_init_set: init then set separately" + else + "" + in + try generic_affect ~loc fname lv ev e + with + | Longlong IULongLong -> + (match e.enode with + | Lval elv -> + assert (Gmp_types.Z.is_t (Cil.typeOf ev)); + let call = Misc.mk_call + ~loc + "__gmpz_import" + [ ev; + Cil.one ~loc; + Cil.one ~loc; + Cil.sizeOf ~loc (TInt(IULongLong, [])); + Cil.zero ~loc; + Cil.zero ~loc; + Cil.mkAddrOf ~loc elv ] + in + Cil.mkStmt ~valid_sid:true (Block (Cil.mkBlock [ init ~loc ev; call ])) + | _ -> + Error.not_yet "unsigned long long expression requiring GMP") + | Longlong ILongLong -> + Error.not_yet "long long requiring GMP" + +let affect ~loc lv ev e = + let fname = + let ty = Cil.typeOf ev in + if Gmp_types.Z.is_t ty then "__gmpz_set" + else if Gmp_types.Q.is_t ty then "__gmpq_set" + else "" + in + try generic_affect ~loc fname lv ev e + with Longlong _ -> + Error.not_yet "quantification over long long and requiring GMP" + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff --git a/src/plugins/e-acsl/src/code_generator/gmp.mli b/src/plugins/e-acsl/src/code_generator/gmp.mli new file mode 100644 index 0000000000000000000000000000000000000000..b526bda347d67b09a5a5e219d985e0e5ba29d511 --- /dev/null +++ b/src/plugins/e-acsl/src/code_generator/gmp.mli @@ -0,0 +1,47 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C's E-ACSL plug-in. *) +(* *) +(* Copyright (C) 2012-2018 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(** Calls to the GMP's API. *) + +open Cil_types + +val init: loc:location -> exp -> stmt +(** build stmt [mpz_init(v)] or [mpq_init(v)] depending on typ of [v] *) + +val init_set: loc:location -> lval -> exp -> exp -> stmt +(** [init_set x_as_lv x_as_exp e] builds stmt [x = e] or [mpz_init_set*(v, e)] + or [mpq_init_set*(v, e)] with the good function 'set' + according to the type of [e] *) + +val clear: loc:location -> exp -> stmt +(** build stmt [mpz_clear(v)] or [mpq_clear(v)] depending on typ of [v] *) + +val affect: loc:location -> lval -> exp -> exp -> stmt +(** [affect x_as_lv x_as_exp e] builds stmt [x = e] or [mpz_set*(e)] + or [mpq_set*(e)] with the good function 'set' + according to the type of [e] *) + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff --git a/src/plugins/e-acsl/src/code_generator/label.ml b/src/plugins/e-acsl/src/code_generator/label.ml new file mode 100644 index 0000000000000000000000000000000000000000..c0b457e923a2d74c12b5264b7abcc014f13750e7 --- /dev/null +++ b/src/plugins/e-acsl/src/code_generator/label.ml @@ -0,0 +1,90 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C's E-ACSL plug-in. *) +(* *) +(* Copyright (C) 2012-2018 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +open Cil_types + +(* The keys are the stmts which were previously labeled, whereas the associated + values are the new stmts containing the same labels. *) +module Labeled_stmts = + Cil_state_builder.Stmt_hashtbl + (Cil_datatype.Stmt) + (struct + let size = 7 + let dependencies = [] (* delayed *) + let name = "E-ACSL.Labels" + end) + +let self = Labeled_stmts.self + +let new_labeled_stmt stmt = try Labeled_stmts.find stmt with Not_found -> stmt + +let move (vis:Visitor.generic_frama_c_visitor) ~old new_stmt = + let labels = old.labels in + match labels with + | [] -> () + | _ :: _ -> + old.labels <- []; + new_stmt.labels <- labels @ new_stmt.labels; + let old = Visitor_behavior.Get_orig.stmt vis#behavior old in + Labeled_stmts.add old new_stmt; + (* update the gotos of the function jumping to one of the labels *) + let o orig_stmt = object + inherit Visitor.frama_c_inplace + (* invariant of this method: [s = Visitor_behavior.Memo.stmt vis#behavior orig_stmt] *) + method !vstmt_aux s = match s.skind, orig_stmt.skind with + | Goto(s_ref, _), Goto(orig_ref, _) -> + if Cil_datatype.Stmt.equal !orig_ref old && s_ref != orig_ref then + (* Forward goto: it has already been visited. + We must update the reference. *) + s_ref := new_stmt; + Cil.SkipChildren + | _ -> Cil.DoChildren + (* improve efficiency: skip children which cannot contain any label *) + method !vinst _ = Cil.SkipChildren + method !vexpr _ = Cil.SkipChildren + method !vlval _ = Cil.SkipChildren + end in + let f = Extlib.the vis#current_func in + let mv_labels s = + ignore (Visitor.visitFramacStmt (o s) (Visitor_behavior.Memo.stmt vis#behavior s)) + in + List.iter mv_labels f.sallstmts + +let get_stmt vis = function + | StmtLabel { contents = stmt } -> stmt + | BuiltinLabel Here -> + (match vis#current_stmt with + | None -> Error.not_yet "label \"Here\" in function contract" + | Some s -> s) + | BuiltinLabel(Old | Pre) -> + (try Kernel_function.find_first_stmt (Extlib.the vis#current_kf) + with Kernel_function.No_Statement -> assert false) + | BuiltinLabel(Post) -> + (try Kernel_function.find_return (Extlib.the vis#current_kf) + with Kernel_function.No_Statement -> assert false) + | BuiltinLabel _ | FormalLabel _ -> assert false + +(* +Local Variables: +compile-command: "make" +End: +*) diff --git a/src/plugins/e-acsl/src/code_generator/label.mli b/src/plugins/e-acsl/src/code_generator/label.mli new file mode 100644 index 0000000000000000000000000000000000000000..3db8fa96dd9b275410fb0cfa3468ecd1b4694a11 --- /dev/null +++ b/src/plugins/e-acsl/src/code_generator/label.mli @@ -0,0 +1,43 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C's E-ACSL plug-in. *) +(* *) +(* Copyright (C) 2012-2018 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +open Cil_types + +val move: Visitor.generic_frama_c_visitor -> old:stmt -> stmt -> unit +(** Move all labels of the [old] stmt onto the new [stmt]. + Both stmts must be in the new project. *) + +val get_stmt: Visitor.generic_frama_c_visitor -> logic_label -> stmt +(** @return the statement where the logic label points to. *) + +val new_labeled_stmt: stmt -> stmt +(** @return the labeled stmt to use instead of the given one (which + previously contained a label *) + +val self: State.t +(** Internal state *) + +(* +Local Variables: +compile-command: "make" +End: +*) diff --git a/src/plugins/e-acsl/src/code_generator/logic_functions.ml b/src/plugins/e-acsl/src/code_generator/logic_functions.ml new file mode 100644 index 0000000000000000000000000000000000000000..74ce5b5f95fd7ffcd5a1c061404bb0542f8c1ab1 --- /dev/null +++ b/src/plugins/e-acsl/src/code_generator/logic_functions.ml @@ -0,0 +1,351 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C's E-ACSL plug-in. *) +(* *) +(* Copyright (C) 2012-2018 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +open Cil_types +open Cil_datatype + +(**************************************************************************) +(********************** Forward references ********************************) +(**************************************************************************) + +let named_predicate_to_exp_ref + : (kernel_function -> Env.t -> predicate -> exp * Env.t) ref + = Extlib.mk_fun "named_predicate_to_exp_ref" + +let term_to_exp_ref + : (kernel_function -> Env.t -> term -> exp * Env.t) ref + = Extlib.mk_fun "term_to_exp_ref" + +(*****************************************************************************) +(************************** Auxiliary functions* ****************************) +(*****************************************************************************) + +(* @return true iff the result of the function is provided by reference as the + first extra argument at each call *) +let result_as_extra_argument = Gmp_types.Z.is_t +(* TODO: to be extended to any compound type? E.g. returning a struct is not + good practice... *) + +(*****************************************************************************) +(****************** Generation of function bodies ****************************) +(*****************************************************************************) + +(* Generate the block of code containing the statement assigning [e] to [ret_vi] + (the result). *) +let generate_return_block ~loc env ret_vi e = match e.enode with + | Lval (Var _, NoOffset) -> + (* the returned value is a variable: Cil invariant preserved; + no need of [ret_vi] *) + let return_retres = Cil.mkStmt ~valid_sid:true (Return (Some e, loc)) in + let b, env = + Env.pop_and_get env return_retres ~global_clear:false Env.After + in + b.blocals <- b.blocals; + b.bscoping <- true; + b, env + | _ -> + (* the returned value is _not_ a variable: restore the invariant *) + let init = AssignInit (SingleInit e) in + let set = + Cil.mkStmtOneInstr ~valid_sid:true (Local_init (ret_vi, init, loc)) + in + let return = + Cil.mkStmt ~valid_sid:true (Return (Some (Cil.evar ~loc ret_vi), loc)) + in + let b, env = Env.pop_and_get env set ~global_clear:false Env.Middle in + ret_vi.vdefined <- true; + b.blocals <- ret_vi :: b.blocals; + b.bstmts <- b.bstmts @ [ return ]; + b.bscoping <- true; + b, env + +(* Generate the function's body for predicates. *) +let pred_to_block ~loc kf env ret_vi p = + Typing.type_named_predicate ~must_clear:false p; + let e, env = !named_predicate_to_exp_ref kf env p in + (* for predicate, since the result is either 0 or 1, return it directly (it + cannot be provided as extra argument *) + generate_return_block ~loc env ret_vi e + +(* Generate the function's body for terms. *) +let term_to_block ~loc kf env ret_ty ret_vi t = + Typing.type_term ~use_gmp_opt:false ~ctx:(Typing.number_ty_of_typ ret_ty) t; + let e, env = !term_to_exp_ref kf env t in + if Cil.isVoidType ret_ty then + (* if the function's result is a GMP, it is the first parameter of the + function (by reference). *) + let set = + let lv_star_ret = Cil.mkMem ~addr:(Cil.evar ~loc ret_vi) ~off:NoOffset in + let star_ret = Cil.new_exp ~loc (Lval lv_star_ret) in + Gmp.init_set ~loc lv_star_ret star_ret e + in + let return_void = Cil.mkStmt ~valid_sid:true (Return (None, loc)) in + let b, env = Env.pop_and_get env set ~global_clear:false Env.Middle in + b.bstmts <- b.bstmts @ [ return_void ]; + b.bscoping <- true; + b, env + else + generate_return_block ~loc env ret_vi e + +let generate_body ~loc kf env ret_ty ret_vi = function + | LBnone | LBreads _ -> + Options.abort + "logic function or predicate without explicit definition are not part of \ + E-ACSL" + | LBterm t -> term_to_block ~loc kf env ret_ty ret_vi t + | LBpred p -> pred_to_block ~loc kf env ret_vi p + | LBinductive _ -> Error.not_yet "inductive definition" + +(* Generate a kernel function from a given logic info [li] *) +let generate_kf ~loc fname env ret_ty params_ty li = + (* build the formal parameters *) + let params, params_ty = + List.fold_right2 + (fun lvi pty (params, params_ty) -> + let ty = match pty with + | Typing.Gmpz -> + (* GMP's integer are arrays: consider them as pointers in function's + parameters *) + Gmp_types.Z.t_as_ptr () + | Typing.C_integer ik -> TInt(ik, []) + | Typing.C_float ik -> TFloat(ik, []) + (* for the time being, no reals but rationals instead *) + | Typing.Rational -> Gmp_types.Q.t () + | Typing.Real -> Error.not_yet "real number" + | Typing.Nan -> Typing.typ_of_lty lvi.lv_type + in + (* build the formals: cannot use [Cil.makeFormal] since the function + does not yet exist *) + let vi = Cil.makeVarinfo false true lvi.lv_name ty in + vi :: params, (lvi.lv_name, ty, []) :: params_ty) + li.l_profile + params_ty + ([], []) + in + (* build the varinfo storing the result *) + let ret_vi, ret_ty, params_with_ret, params_ty_with_ret = + let vname = "__retres" in + if result_as_extra_argument ret_ty then + let ret_ty_ptr = TPtr(ret_ty, []) (* call by reference *) in + let vname = vname ^ "_arg" in + let vi = Cil.makeVarinfo false true vname ret_ty_ptr in + vi, Cil.voidType, vi :: params, (vname, ret_ty_ptr, []) :: params_ty + else + Cil.makeVarinfo false false vname ret_ty, ret_ty, params, params_ty + in + (* build the function's varinfo *) + let vi = + Cil.makeGlobalVar + fname + (TFun + (ret_ty, + Some params_ty_with_ret, + false, + li.l_var_info.lv_attr)) + in + vi.vdefined <- true; + (* create the fundec *) + let fundec = + { svar = vi; + sformals = params_with_ret; + slocals = []; (* filled later to break mutual dependencies between + creating this list and creating the kf *) + smaxid = 0; + sbody = Cil.mkBlock []; (* filled later; same as above *) + smaxstmtid = None; + sallstmts = []; + sspec = Cil.empty_funspec () } + in + Cil.setMaxId fundec; + let spec = Cil.empty_funspec () in + Queue.add + (fun () -> Globals.Functions.replace_by_definition spec fundec loc) + (Env.get_visitor env)#get_filling_actions; + (* create the kernel function itself *) + let kf = { fundec = Definition(fundec, loc); spec } in + (* closure generating the function's body. + Delay its generation after filling the memoisation table (for termination + of recursive function calls) *) + let gen_body () = + let env = Env.push env in + let old_kf = Extlib.the (Env.current_kf env) in + Env.set_current_kf env kf; + (* fill the typing environment with the function's parameters + before generating the code (code generation invokes typing) *) + let env = + let add env lvi vi = + let i = Interval.interv_of_typ vi.vtype in + Interval.Env.add lvi i; + Env.Logic_binding.add_binding env lvi vi + in + List.fold_left2 add env li.l_profile params + in + let b, env = generate_body ~loc kf env ret_ty ret_vi li.l_body in + fundec.sbody <- b; + (* add the generated variables in the necessary lists *) + (* TODO: factorized the code below that add the generated vars with method + [add_generated_variables_in_function] in the main visitor *) + let vars = + let l = Env.get_generated_variables env in + if ret_vi.vdefined then (ret_vi, Env.LFunction kf) :: l else l + in + let locals, blocks = + List.fold_left + (fun (local_vars, block_vars as acc) (v, scope) -> match scope with + | Env.LFunction kf' when Kernel_function.equal kf kf' -> + v :: local_vars, block_vars + | Env.LLocal_block kf' when Kernel_function.equal kf kf' -> + v :: local_vars, block_vars + | _ -> acc) + (fundec.slocals, fundec.sbody.blocals) + vars + in + fundec.slocals <- locals; + fundec.sbody.blocals <- blocks; + List.iter + (fun lvi -> + Interval.Env.remove lvi; + ignore (Env.Logic_binding.remove env lvi)) + li.l_profile; + Env.set_current_kf + env + (Visitor_behavior.Get_orig.kernel_function (Env.get_behavior env) old_kf) + in + vi, kf, gen_body + +(**************************************************************************) +(***************************** Memoization ********************************) +(**************************************************************************) + +module Params_ty = + Datatype.List_with_collections + (Typing.Datatype) + (struct let module_name = "E_ACSL.Logic_functions.Params_ty" end) + +(* for each logic_info, associate its possible profiles, i.e. the types of its + parameters + the generated varinfo for the function *) +let memo_tbl: + kernel_function Params_ty.Hashtbl.t Logic_info.Hashtbl.t + = Logic_info.Hashtbl.create 7 + +let reset () = Logic_info.Hashtbl.clear memo_tbl + +let add_generated_functions globals = + let rec aux acc = function + | [] -> + acc + | GAnnot(Dfun_or_pred(li, loc), _) as g :: l -> + let acc = g :: acc in + (try + (* add the declarations close to its corresponding logic function or + predicate *) + let params = Logic_info.Hashtbl.find memo_tbl li in + let add_fundecl kf acc = + GFunDecl(Cil.empty_funspec (), Kernel_function.get_vi kf, loc) + :: acc + in + aux (Params_ty.Hashtbl.fold (fun _ -> add_fundecl) params acc) l + with Not_found -> + aux acc l) + | g :: l -> + aux (g :: acc) l + in + let rev_globals = aux [] globals in + (* add the definitions at the end of [globals] *) + let add_fundec kf globals = + let fundec = + try Kernel_function.get_definition kf + with Kernel_function.No_Definition -> assert false + in + GFun(fundec, Location.unknown) :: globals + in + let rev_globals = + Logic_info.Hashtbl.fold + (fun _ -> Params_ty.Hashtbl.fold (fun _ -> add_fundec)) + memo_tbl + rev_globals + in + List.rev rev_globals + +let tapp_to_exp ~loc fname env t li params_ty args = + let ret_ty = Typing.get_typ t in + let gen tbl = + let vi, kf, gen_body = generate_kf fname ~loc env ret_ty params_ty li in + Params_ty.Hashtbl.add tbl params_ty kf; + vi, gen_body + in + (* memoise the function's varinfo *) + let fvi, gen_body = + try + let h = Logic_info.Hashtbl.find memo_tbl li in + try + let kf = Params_ty.Hashtbl.find h params_ty in + Kernel_function.get_vi kf, + (fun () -> ()) (* body generation already planified *) + with Not_found -> gen h + with Not_found -> + let h = Params_ty.Hashtbl.create 7 in + Logic_info.Hashtbl.add memo_tbl li h; + gen h + in + (* the generation of the function body must be performed after memoizing the + kernel function in order to handle recursive calls in finite time :-) *) + gen_body (); + (* create the function call for the tapp *) + let mkcall vi = + let mk_args types args = + match types (* generated by E-ACSL: no need to unroll *) with + | TFun(_, Some params, _, _) -> + (* additional casts are necessary whenever the argument is GMP and the + parameter is a (small) integralType: after handling the context in + [Translate] through [add_cast], the GMP has been translated into a + [long] (that is what provided the GMP API). This [long] must now be + translated to the parameter's type. It cannot be done before since + the exact type of the parameter is only computed when the function is + generated *) + List.map2 + (fun (_, newt, _) e -> Cil.mkCast ~force:false ~newt ~e) + params + args + | _ -> assert false + in + if result_as_extra_argument ret_ty then + let args = mk_args fvi.vtype (Cil.mkAddrOf ~loc (Cil.var vi) :: args) in + Call(None, Cil.evar fvi, args, loc) + else + let args = mk_args fvi.vtype args in + Call(Some (Cil.var vi), Cil.evar fvi, args, loc) + in + (* generate the varinfo storing the result of the call *) + Env.new_var + ~loc + ~name:li.l_var_info.lv_name + env + (Some t) + ret_ty + (fun vi _ -> [ Cil.mkStmtOneInstr ~valid_sid:true (mkcall vi) ]) + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff --git a/src/plugins/e-acsl/src/code_generator/logic_functions.mli b/src/plugins/e-acsl/src/code_generator/logic_functions.mli new file mode 100644 index 0000000000000000000000000000000000000000..160170331fbb52fa20efe9e0df46c889a552de9f --- /dev/null +++ b/src/plugins/e-acsl/src/code_generator/logic_functions.mli @@ -0,0 +1,62 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C's E-ACSL plug-in. *) +(* *) +(* Copyright (C) 2012-2018 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +open Cil_types + +(** Generate C implementations of user-defined logic functions. + A logic function can have multiple C implementations depending on + the types computed for its arguments. + Eg: Consider the following definition: [integer g(integer x) = x] + with the following calls: [g(5)] and [g(10*INT_MAX)] + They will respectively generate the C prototypes [int g_1(int)] + and [long g_2(long)] *) + +(**************************************************************************) +(************** Logic functions without labels ****************************) +(**************************************************************************) + +val reset: unit -> unit + +val tapp_to_exp: + loc:location -> + string -> Env.t -> term -> logic_info -> Typing.number_ty list -> exp list -> + varinfo * exp * Env.t + +val add_generated_functions: global list -> global list +(* @return the input list of globals in which the generated functions have been + inserted at the right places (both their declaration and their definition) *) + +(**************************************************************************) +(********************** Forward references ********************************) +(**************************************************************************) + +val named_predicate_to_exp_ref: + (kernel_function -> Env.t -> predicate -> exp * Env.t) ref + +val term_to_exp_ref: + (kernel_function -> Env.t -> term -> exp * Env.t) ref + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff --git a/src/plugins/e-acsl/src/code_generator/loops.ml b/src/plugins/e-acsl/src/code_generator/loops.ml new file mode 100644 index 0000000000000000000000000000000000000000..005b6b8edfd06e12e3997d08616b591453c19557 --- /dev/null +++ b/src/plugins/e-acsl/src/code_generator/loops.ml @@ -0,0 +1,329 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C's E-ACSL plug-in. *) +(* *) +(* Copyright (C) 2012-2018 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +open Cil +open Cil_types + +(**************************************************************************) +(********************** Forward references ********************************) +(**************************************************************************) + +let translate_named_predicate_ref + : (kernel_function -> Env.t -> predicate -> Env.t) ref + = Extlib.mk_fun "translate_named_predicate_ref" + +let named_predicate_ref + : (kernel_function -> Env.t -> predicate -> exp * Env.t) ref + = Extlib.mk_fun "named_predicate_ref" + +let term_to_exp_ref + : (kernel_function -> Env.t -> term -> exp * Env.t) ref + = Extlib.mk_fun "term_to_exp_ref" + +(**************************************************************************) +(************************* Loop invariants ********************************) +(**************************************************************************) + +module Loop_invariants_actions = Hook.Make(struct end) + +let apply_after_transformation prj = + Project.on prj Loop_invariants_actions.apply () + +let mv_invariants env ~old stmt = + Options.feedback ~current:true ~level:3 + "keep loop invariants attached to its loop"; + match Env.current_kf env with + | None -> assert false + | Some kf -> + let filter _ ca = match ca.annot_content with + | AInvariant(_, b, _) -> b + | _ -> false + in + let l = Annotations.code_annot_emitter ~filter stmt in + if l != [] then + Loop_invariants_actions.extend + (fun () -> + List.iter + (fun (ca, e) -> + Annotations.remove_code_annot e ~kf old ca; + Annotations.add_code_annot e ~kf stmt ca) + l) + +let preserve_invariant prj env kf stmt = match stmt.skind with + | Loop(_, ({ bstmts = stmts } as blk), loc, cont, break) -> + let rec handle_invariants (stmts, env, _ as acc) = function + | [] -> + (* empty loop body: no need to verify the invariant twice *) + acc + | [ last ] -> + let invariants, env = Env.pop_loop env in + let env = Env.push env in + let env = + let translate_named_predicate = !translate_named_predicate_ref in + Project.on + prj + (List.fold_left (translate_named_predicate kf) env) + invariants + in + let blk, env = + Env.pop_and_get env last ~global_clear:false Env.Before + in + Misc.mk_block prj last blk :: stmts, env, invariants != [] + | s :: tl -> handle_invariants (s :: stmts, env, false) tl + in + let env = Env.set_annotation_kind env Misc.Invariant in + let stmts, env, has_loop = handle_invariants ([], env, false) stmts in + let new_blk = { blk with bstmts = List.rev stmts } in + { stmt with skind = Loop([], new_blk, loc, cont, break) }, + env, + has_loop + | _ -> stmt, env, false + +(**************************************************************************) +(**************************** Nested loops ********************************) +(**************************************************************************) + +(* It could happen that the bounds provided for a quantifier [lv] are bigger + than its type. [bounds_for_small_type] handles such cases + and provides smaller bounds whenever possible. + Let B be the inferred interval and R the range of [lv.typ] + - Case 1: B \subseteq R + Example: [\forall unsigned char c; 4 <= c <= 100 ==> 0 <= c <= 255] + Return: B + - Case 2: B \not\subseteq R and the bounds of B are inferred exactly + Example: [\forall unsigned char c; 4 <= c <= 300 ==> 0 <= c <= 255] + Return: B \intersect R + - Case 3: B \not\subseteq R and the bounds of B are NOT inferred exactly + Example: [\let m = n > 0 ? 4 : 341; \forall char u; 1 < u < m ==> u > 0] + Return: R with a guard guaranteeing that [lv] does not overflow *) +let bounds_for_small_type ~loc (t1, lv, t2) = + match lv.lv_type with + | Ltype _ | Lvar _ | Lreal | Larrow _ -> + Options.abort "quantification over non-integer type is not part of E-ACSL" + + | Linteger -> + t1, t2, None + + | Ctype ty -> + let iv1 = Interval.(extract_ival (infer t1)) in + let iv2 = Interval.(extract_ival (infer t2)) in + (* Ival.join is NOT correct here: + Eg: (Ival.join [-3..-3] [300..300]) gives {-3, 300} + but NOT [-3..300] *) + let iv = Ival.inject_range (Ival.min_int iv1) (Ival.max_int iv2) in + let ity = Interval.extract_ival (Interval.interv_of_typ ty) in + if Ival.is_included iv ity then + (* case 1 *) + t1, t2, None + else if Ival.is_singleton_int iv1 && Ival.is_singleton_int iv2 then begin + (* case 2 *) + let i = Ival.meet iv ity in + (* now we potentially have a better interval for [lv] + ==> update the binding *) + Interval.Env.replace lv (Interval.Ival i); + (* the smaller bounds *) + let min, max = Misc.finite_min_and_max i in + let t1 = Logic_const.tint ~loc min in + let t2 = Logic_const.tint ~loc max in + let ctx = Typing.number_ty_of_typ ty in + (* we are assured that we will not have a GMP, + once again because we intersected with [ity] *) + Typing.type_term ~use_gmp_opt:false ~ctx t1; + Typing.type_term ~use_gmp_opt:false ~ctx t2; + t1, t2, None + end else + (* case 3 *) + let min, max = Misc.finite_min_and_max ity in + let guard_lower = Logic_const.tint ~loc min in + let guard_upper = Logic_const.tint ~loc max in + let lv_term = Logic_const.tvar ~loc lv in + let guard_lower = Logic_const.prel ~loc (Rle, guard_lower, lv_term) in + let guard_upper = Logic_const.prel ~loc (Rle, lv_term, guard_upper) in + let guard = Logic_const.pand ~loc (guard_lower, guard_upper) in + t1, t2, Some guard + +let rec mk_nested_loops ~loc mk_innermost_block kf env lscope_vars = + let term_to_exp = !term_to_exp_ref in + match lscope_vars with + | [] -> + mk_innermost_block env + | Lscope.Lvs_quantif(t1, rel1, logic_x, rel2, t2) :: lscope_vars' -> + let t1, t2, guard_for_small_type_opt = + bounds_for_small_type ~loc (t1, logic_x, t2) + in + let ctx = + let ty1 = Typing.get_number_ty t1 in + let ty2 = Typing.get_number_ty t2 in + Typing.join ty1 ty2 + in + let t_plus_one ?ty t = + (* whenever provided, [ty] is known to be the type of the result *) + let tone = Cil.lone ~loc () in + let res = Logic_const.term ~loc (TBinOp(PlusA, t, tone)) Linteger in + Extlib.may + (fun ty -> + Typing.unsafe_set tone ~ctx:ty ctx; + Typing.unsafe_set t ~ctx:ty ctx; + Typing.unsafe_set res ty) + ty; + res + in + let t1 = match rel1 with + | Rlt -> + let t = t_plus_one t1 in + Typing.type_term ~use_gmp_opt:false ~ctx t; + t + | Rle -> + t1 + | Rgt | Rge | Req | Rneq -> + assert false + in + let t2_one, bop2 = match rel2 with + | Rlt -> + t2, Lt + | Rle -> + (* we increment the loop counter one more time (at the end of the + loop). Thus to prevent overflow, check the type of [t2+1] + instead of [t2]. *) + t_plus_one t2, Le + | Rgt | Rge | Req | Rneq -> + assert false + in + Typing.type_term ~use_gmp_opt:false ~ctx t2_one; + let ctx_one = + let ty1 = Typing.get_number_ty t1 in + let ty2 = Typing.get_number_ty t2_one in + Typing.join ty1 ty2 + in + let ty = + try Typing.typ_of_number_ty ctx_one + with Typing.Not_a_number -> assert false + in + (* loop counter corresponding to the quantified variable *) + let var_x, x, env = Env.Logic_binding.add ~ty env logic_x in + let lv_x = var var_x in + let env = match ctx_one with + | Typing.C_integer _ -> env + | Typing.Gmpz -> Env.add_stmt env (Gmp.init ~loc x) + | Typing.(C_float _ | Rational | Real | Nan) -> assert false + in + (* build the inner loops and loop body *) + let body, env = + mk_nested_loops ~loc mk_innermost_block kf env lscope_vars' + in + (* initialize the loop counter to [t1] *) + let e1, env = term_to_exp kf (Env.push env) t1 in + let init_blk, env = Env.pop_and_get + env + (Gmp.affect ~loc:e1.eloc lv_x x e1) + ~global_clear:false + Env.Middle + in + (* generate the guard [x bop t2] *) + let block_to_stmt b = mkStmt ~valid_sid:true (Block b) in + let tlv = Logic_const.tvar ~loc logic_x in + let guard = + (* must copy [t2] to force being typed again *) + Logic_const.term ~loc + (TBinOp(bop2, tlv, { t2 with term_node = t2.term_node } )) Linteger + in + Typing.type_term ~use_gmp_opt:false ~ctx:Typing.c_int guard; + let guard_exp, env = term_to_exp kf (Env.push env) guard in + let break_stmt = mkStmt ~valid_sid:true (Break guard_exp.eloc) in + let guard_blk, env = Env.pop_and_get + env + (mkStmt + ~valid_sid:true + (If( + guard_exp, + mkBlock [ mkEmptyStmt ~loc () ], + mkBlock [ break_stmt ], + guard_exp.eloc))) + ~global_clear:false + Env.Middle + in + let guard = block_to_stmt guard_blk in + (* increment the loop counter [x++]; + previous typing ensures that [x++] fits type [ty] *) + let tlv_one = t_plus_one ~ty:ctx_one tlv in + let incr, env = term_to_exp kf (Env.push env) tlv_one in + let next_blk, env = Env.pop_and_get + env + (Gmp.affect ~loc:incr.eloc lv_x x incr) + ~global_clear:false + Env.Middle + in + (* generate the whole loop *) + let next = block_to_stmt next_blk in + let stmts, env = match guard_for_small_type_opt with + | None -> + guard :: body @ [ next ], env + | Some p -> + let e, env = !named_predicate_ref kf (Env.push env) p in + let stmt, env = + Misc.mk_e_acsl_guard ~reverse:true Misc.RTE kf e p, env + in + let b, env = Env.pop_and_get env stmt ~global_clear:false Env.After in + let guard_for_small_type = Cil.mkStmt ~valid_sid:true (Block b) in + guard_for_small_type :: guard :: body @ [ next ], env + in + let start = block_to_stmt init_blk in + let stmt = mkStmt + ~valid_sid:true + (Loop( + [], + mkBlock stmts, + loc, + None, + Some break_stmt)) + in + (* remove logic binding before returning *) + Env.Logic_binding.remove env logic_x; + [ start ; stmt ], env + | Lscope.Lvs_let(lv, t) :: lscope_vars' -> + let ty = Typing.get_typ t in + let vi_of_lv, exp_of_lv, env = Env.Logic_binding.add ~ty env lv in + let e, env = term_to_exp kf env t in + let ty = Cil.typeOf e in + let init_set = + if Gmp_types.Q.is_t ty then Rational.init_set else Gmp.init_set + in + let let_stmt = init_set ~loc (Cil.var vi_of_lv) exp_of_lv e in + let stmts, env = + mk_nested_loops ~loc mk_innermost_block kf env lscope_vars' + in + (* remove the logic binding now that the block is constructed *) + Env.Logic_binding.remove env lv; + (* return *) + let_stmt :: stmts, env + | Lscope.Lvs_formal _ :: _ -> + Error.not_yet + "creating nested loops from formal variable of a logic function" + | Lscope.Lvs_global _ :: _ -> + Error.not_yet + "creating nested loops from global logic variable" + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff --git a/src/plugins/e-acsl/src/code_generator/loops.mli b/src/plugins/e-acsl/src/code_generator/loops.mli new file mode 100644 index 0000000000000000000000000000000000000000..f2e9fc3fa0fc8a7e7d2c071b7e40d8d4130e000a --- /dev/null +++ b/src/plugins/e-acsl/src/code_generator/loops.mli @@ -0,0 +1,75 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C's E-ACSL plug-in. *) +(* *) +(* Copyright (C) 2012-2018 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(** Loop specific actions. *) + +open Cil_types + +(**************************************************************************) +(************************* Loop invariants ********************************) +(**************************************************************************) + +val apply_after_transformation: Project.t -> unit + +val mv_invariants: Env.t -> old:stmt -> stmt -> unit +(** Transfer the loop invariants from the [old] loop to the new one. + Both statements must be loops. *) + +val preserve_invariant: + Project.t -> Env.t -> Kernel_function.t -> stmt -> stmt * Env.t * bool +(** modify the given stmt loop to insert the code which preserves its loop + invariants. Also return the modify environment and a boolean which + indicates whether the annotations corresponding to the loop invariant must + be moved from the new statement to the old one. *) + +(**************************************************************************) +(**************************** Nested loops ********************************) +(**************************************************************************) + +val mk_nested_loops: + loc:location -> (Env.t -> stmt list * Env.t) -> kernel_function -> Env.t -> + Lscope.lscope_var list -> stmt list * Env.t +(** [mk_nested_loops ~loc mk_innermost_block kf env lvars] creates nested + loops (with the proper statements for initializing the loop counters) + from the list of logic variables [lvars]. Quantified variables create + loops while let-bindings simply create new variables. + The [mk_innermost_block] closure creates the statements of the innermost + block. *) + +(**************************************************************************) +(********************** Forward references ********************************) +(**************************************************************************) + +val translate_named_predicate_ref: + (kernel_function -> Env.t -> predicate -> Env.t) ref + +val named_predicate_ref: + (kernel_function -> Env.t -> predicate -> exp * Env.t) ref + +val term_to_exp_ref: + (kernel_function -> Env.t -> term -> exp * Env.t) ref + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff --git a/src/plugins/e-acsl/src/code_generator/mmodel_translate.ml b/src/plugins/e-acsl/src/code_generator/mmodel_translate.ml new file mode 100644 index 0000000000000000000000000000000000000000..51ba54b1c98e1ad1727df64da2fcc40907e1a352 --- /dev/null +++ b/src/plugins/e-acsl/src/code_generator/mmodel_translate.ml @@ -0,0 +1,396 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C's E-ACSL plug-in. *) +(* *) +(* Copyright (C) 2012-2018 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +open Cil_types + +(**************************************************************************) +(********************** Forward references ********************************) +(**************************************************************************) + +let predicate_to_exp_ref + : (kernel_function -> Env.t -> predicate -> exp * Env.t) ref + = Extlib.mk_fun "named_predicate_to_exp_ref" + +let term_to_exp_ref + : (kernel_function -> Env.t -> term -> exp * Env.t) ref + = Extlib.mk_fun "term_to_exp_ref" + +(*****************************************************************************) +(****************************** Ranges Elimination ***************************) +(*****************************************************************************) + +(* We call Range Elimination the operation through which ranges are + substituted by universally quantified logic variables. + Example: + [\valid(&t[(n-1)..(n+2)][1][0..1])] can be soundly transformed into + [\forall integer q1; n-1 <= q1 <= n+2 ==> + \forall integer q2; 0 <= q2 <= 1 ==> + \valid(&t[q1][1][q2])] + However, the substitution can be unsound, + in which case [Range_elimination_exception] must be raised. + Example: + [\valid(&t[(0..2)==(0..2) ? 0 : 1])] is equivalent to [\valid(&t[0])] + since [==] refers to set equality when applied on ranges. + But Range Elimination will give a predicate equivalent to [\valid(&t[1])] + since [\forall 0 <= q1,q2 <= 2: q1==q2] is false. + Hence [Range_elimination_exception] must be raised. *) +exception Range_elimination_exception + +(* Takes a [toffset] and checks whether it contains an index that is a set *) +let rec has_set_as_index = function + | TNoOffset -> + false + | TIndex(t, toffset) -> + Logic_const.is_set_type t.term_type || has_set_as_index toffset + | TModel(_, toffset) | TField(_, toffset) -> + has_set_as_index toffset + +(* Performs Range Elimination on index [TIndex(term, offset)]. Term part. + Raises [Range_elimination_exception] if whether the operation is unsound or + if we don't support the construction yet. *) +let eliminate_ranges_from_index_of_term ~loc t = + match t.term_node with + | Trange(Some n1, Some n2) -> + let name = Varname.get ~scope:Varname.Block "range" in + let lv = Cil_const.make_logic_var_kind name LVQuant Linteger in + let tlv = Logic_const.tvar ~loc lv in + tlv, (n1, lv, n2) + | _ -> + raise Range_elimination_exception + +(* Performs Range Elimination on index [TIndex(term, offset)]. Offset part. + Raises [Range_elimination_exception], through [eliminate_ranges_from_ + index_of_term], if whether the operation is unsound or + if we don't support the construction yet. *) +let rec eliminate_ranges_from_index_of_toffset ~loc toffset quantifiers = + match toffset with + | TIndex(t, toffset') -> + if Misc.is_range_free t then + let toffset', quantifiers' = + eliminate_ranges_from_index_of_toffset ~loc toffset' quantifiers + in + TIndex(t, toffset'), quantifiers' + else + (* Attempt Range Elimination on [t] *) + let t1, quantifiers1 = + eliminate_ranges_from_index_of_term ~loc t + in + let toffset2, quantifiers2 = + eliminate_ranges_from_index_of_toffset ~loc toffset' quantifiers + in + let toffset3 = TIndex(t1, toffset2) in + toffset3, quantifiers1 :: quantifiers2 + | TNoOffset -> + toffset, quantifiers + | TModel _ -> + Error.not_yet "range elimination on TModel" + | TField _ -> + Error.not_yet "range elimination on TField" + +(*****************************************************************************) +(********************** Calls without Range Elimination **********************) +(************** \base_addr, \block_length, \offset, \freeable ****************) +(*****************************************************************************) + +(* \base_addr, \block_length, \offset and \freeable *) +let call ~loc kf name ctx env t = + assert (name = "base_addr" || name = "block_length" + || name = "offset" || name ="freeable"); + let e, env = !term_to_exp_ref kf (Env.rte env true) t in + let _, res, env = + Env.new_var + ~loc + ~name + env + None + ctx + (fun v _ -> + let name = Functions.RTL.mk_api_name name in + [ Misc.mk_call ~loc ~result:(Cil.var v) name [ e ] ]) + in + res, env + +(*****************************************************************************) +(************************* Calls with Range Elimination **********************) +(********************** \initialized, \valid, \valid_read ********************) +(*****************************************************************************) + +(* Take the term [size] that has been typed into GMP + and return an expression of type [size_t]. + The case where [!(0 <= size < SIZE_MAX)] is an UB ==> guard against it. *) +let gmp_to_sizet ~loc kf env size p = + let sizet = Cil.(theMachine.typeOfSizeOf) in + (* The guard *) + let sizet_max = Logic_const.tint + ~loc (Cil.max_unsigned_number (Cil.bitsSizeOf sizet)) + in + let guard_upper = Logic_const.prel ~loc (Rlt, size, sizet_max) in + let guard_lower = Logic_const.prel ~loc (Rle, Cil.lzero ~loc (), size) in + let guard = Logic_const.pand ~loc (guard_lower, guard_upper) in + Typing.type_named_predicate ~must_clear:false guard; + let guard, env = !predicate_to_exp_ref kf env guard in + (* Translate term [size] into an exp of type [size_t] *) + let size, env = !term_to_exp_ref kf env size in + let _, e, env = Env.new_var + ~loc + ~name:"size" + env + None + sizet + (fun vi _ -> + [ Misc.mk_e_acsl_guard ~reverse:true Misc.RTE kf guard p; + Misc.mk_call ~loc ~result:(Cil.var vi) "__gmpz_get_ui" [ size ] ]) + in + e, env + +(* Call to [__e_acsl_<name>] for terms of the form [ptr + r] + when [<name> = valid or initialized or valid_read] and + where [ptr] is an address and [r] a range offset *) +let call_memory_block ~loc kf name ctx env ptr r p = + let n1, n2 = match r.term_node with + | Trange(Some n1, Some n2) -> + n1, n2 + | Trange(None, _) | Trange(_, None) -> + Options.abort "unbounded ranges are not part of E-ACSL" + | _ -> + assert false + in + (* s *) + let ty = match Cil.unrollType (Misc.cty ptr.term_type) with + | TPtr(ty, _) | TArray(ty, _, _, _) -> ty + | _ -> assert false + in + let s = Logic_const.term ~loc (TSizeOf ty) Linteger in + (* ptr *) + let typ_charptr = Cil.charPtrType in + let ptr = Logic_const.term + ~loc + (TBinOp( + PlusPI, + Logic_utils.mk_cast ~loc ~force:false typ_charptr ptr, + Logic_const.term ~loc (TBinOp(Mult, s, n1)) Linteger)) + (Ctype typ_charptr) + in + Typing.type_term ~use_gmp_opt:false ~ctx:Typing.nan ptr; + let term_to_exp = !term_to_exp_ref in + let ptr, env = term_to_exp kf (Env.rte env true) ptr in + (* size *) + let size_term = + (* Since [s] and [n1] have been typed through [ptr], + we need to clone them in order to force retyping *) + let s = { s with term_node = s.term_node } in + let n1 = { n1 with term_node = n1.term_node } in + Logic_const.term + ~loc + (TBinOp( + Mult, + s, + Logic_const.term ~loc (TBinOp(MinusA, n2, n1)) Linteger)) + Linteger + in + Typing.type_term ~use_gmp_opt:false size_term; + let size, env = match Typing.get_number_ty size_term with + | Typing.Gmpz -> + gmp_to_sizet ~loc kf env size_term p + | Typing.(C_integer _ | C_float _) -> + let size, env = term_to_exp kf env size_term in + Cil.constFold false size, env + | Typing.(Rational | Real | Nan) -> + assert false + in + (* base and base_addr *) + let base, _ = Misc.ptr_index ~loc ptr in + let base_addr = match base.enode with + | AddrOf _ | Const _ -> Cil.zero ~loc + | Lval lv | StartOf lv -> Cil.mkAddrOrStartOf ~loc lv + | _ -> assert false + in + (* generating env *) + let _, e, env = + Env.new_var + ~loc + ~name + env + None + ctx + (fun v _ -> + let fname = Functions.RTL.mk_api_name name in + let args = match name with + | "valid" | "valid_read" -> [ ptr; size; base; base_addr ] + | "initialized" -> [ ptr; size ] + | _ -> Error.not_yet ("builtin " ^ name) + in + [ Misc.mk_call ~loc ~result:(Cil.var v) fname args ]) + in + e, env + +(* [call_with_ranges] handles ranges in [t] when calling builtin [name]. + It only supports the following cases for the time being: + A: [\builtin(ptr+r)] where [ptr] is an address and [r] a range or + [\builtin(t[r])] or + [\builtin(t[i_1]...[i_n])] where [t] is dynamically allocated + and all the indexes are integers, + except the last one which is a range + The generated code is a SINGLE call to the corresponding E-ACSL builtin + B: [\builtin(t[i_1]...[i_n])] where [t] is NOT dynamically allocated + and the indexes are integers or ranges + The generated code is a SET OF calls to the corresponding E-ACSL builtin + C: Any other use of ranges/No range + Call [call_default] which performs the translation for + range free terms, and raises Not_yet if it ever encounters a range. + Example for case: + A: [\valid(&t[3..5])] + Contiguous locations -> a single call to [__e_acsl_valid] + B: [\valid(&t[4][3..5][2])] + NON-contiguous locations -> multiple calls (3) to [__e_acsl_valid] *) +let call_with_ranges ~loc kf name ctx env t p call_default = + if Misc.is_bitfield_pointers t.term_type then + Error.not_yet "bitfield pointer"; + match t.term_node with + | TBinOp((PlusPI | IndexPI), ptr, ({ term_node = Trange _ } as r)) -> + if Misc.is_set_of_ptr_or_array ptr.term_type then + Error.not_yet "arithmetic over set of pointers or arrays" + else + (* Case A *) + call_memory_block ~loc kf name ctx env ptr r p + | TAddrOf(TVar lv, TIndex({ term_node = Trange _ } as r, TNoOffset)) -> + (* Case A *) + assert (Logic_const.is_set_type t.term_type); + let lty_noset = Logic_const.type_of_element t.term_type in + let ptr = Logic_const.taddrof ~loc (TVar lv, TNoOffset) lty_noset in + call_memory_block ~loc kf name ctx env ptr r p + | TAddrOf(TVar ({ lv_type = Ctype (TArray _) } as lv), toffset) -> + if has_set_as_index toffset then + (* Case B *) + try + let toffset', quantifiers = + eliminate_ranges_from_index_of_toffset ~loc toffset [] + in + let lty_noset = + if Logic_const.is_set_type t.term_type then + Logic_const.type_of_element t.term_type + else + t.term_type + in + let t' = Logic_const.taddrof ~loc (TVar lv, toffset') lty_noset in + let p_quantified = + (* [loc] prevents a type error with eta-expansion and label *) + let loc = Some loc in + let call f = f ?loc (Logic_const.here_label, t') in + match name with + | "valid" -> call Logic_const.pvalid + | "initialized" -> call Logic_const.pinitialized + | "valid_read" -> call Logic_const.pvalid_read + | _ -> Options.fatal "[call_with_ranges] unexpected builtin" + in + let p_quantified = List.fold_left + (fun p (tmin, lv, tmax) -> + (* \forall integer tlv; tmin <= tlv <= tmax ==> p *) + let tlv = Logic_const.tvar ~loc lv in + let lower_bound = Logic_const.prel ~loc (Rle, tmin, tlv) in + let upper_bound = Logic_const.prel ~loc (Rle, tlv, tmax) in + let bound = Logic_const.pand ~loc (lower_bound, upper_bound) in + let bound_imp_p = Logic_const.pimplies ~loc (bound, p) in + Logic_const.pforall ~loc ([lv], bound_imp_p)) + p_quantified + quantifiers + in + Typing.type_named_predicate ~must_clear:true p_quantified; + !predicate_to_exp_ref kf env p_quantified + with Range_elimination_exception -> + (* Case C *) + call_default ~loc kf name ctx env t + else + (* Case C *) + call_default ~loc kf name ctx env t + | _ -> + (* Case C *) + call_default ~loc kf name ctx env t + +(* \initialized *) +let call_with_size ~loc kf name ctx env t p = + assert (name = "initialized"); + let call_for_unsupported_constructs ~loc kf name ctx env t = + let term_to_exp = !term_to_exp_ref in + let e, env = term_to_exp kf (Env.rte env true) t in + let _, res, env = + Env.new_var + ~loc + ~name + env + None + ctx + (fun v _ -> + let ty = Misc.cty t.term_type in + let sizeof = Misc.mk_ptr_sizeof ty loc in + let fname = Functions.RTL.mk_api_name name in + [ Misc.mk_call ~loc ~result:(Cil.var v) fname [ e; sizeof ] ]) + in + res, env + in + call_with_ranges + ~loc + kf + name + ctx + env + t + p + call_for_unsupported_constructs + +(* \valid and \valid_read *) +let call_valid ~loc kf name ctx env t p = + assert (name = "valid" || name = "valid_read"); + let call_for_unsupported_constructs ~loc kf name ctx env t = + let term_to_exp = !term_to_exp_ref in + let e, env = term_to_exp kf (Env.rte env true) t in + let base, _ = Misc.ptr_index ~loc e in + let base_addr = match base.enode with + | AddrOf _ | Const _ -> Cil.zero ~loc + | Lval lv | StartOf lv -> Cil.mkAddrOrStartOf ~loc lv + | _ -> assert false + in + let _, res, env = + Env.new_var + ~loc + ~name + env + None + ctx + (fun v _ -> + let ty = Misc.cty t.term_type in + let sizeof = Misc.mk_ptr_sizeof ty loc in + let fname = Functions.RTL.mk_api_name name in + let args = [ e; sizeof; base; base_addr ] in + [ Misc.mk_call ~loc ~result:(Cil.var v) fname args ]) + in + res, env + in + call_with_ranges + ~loc + kf + name + ctx + env + t + p + call_for_unsupported_constructs diff --git a/src/plugins/e-acsl/src/code_generator/mmodel_translate.mli b/src/plugins/e-acsl/src/code_generator/mmodel_translate.mli new file mode 100644 index 0000000000000000000000000000000000000000..eb9170e2b17239d5b41c8e6676251acb680bba66 --- /dev/null +++ b/src/plugins/e-acsl/src/code_generator/mmodel_translate.mli @@ -0,0 +1,62 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C's E-ACSL plug-in. *) +(* *) +(* Copyright (C) 2012-2018 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +open Cil_types + +(* Create calls to a few memory builtins. + Partial support for ranges is provided. *) + +val call: + loc:location -> kernel_function -> string -> typ -> Env.t -> term -> + exp * Env.t +(* [call ~loc kf name ctx env t] creates a call to the E-ACSL memory builtin + identified by [name] which only requires a single argument, namely the + pointer under study. The supported builtins are: + [base_addr], [block_length], [offset] and [freeable]. *) + +val call_with_size: + loc:location -> kernel_function -> string -> typ -> Env.t -> term -> + predicate -> exp * Env.t +(* [call_with_size ~loc kf name ctx env t p] creates a call to the E-ACSL + memory builtin identified by [name] which requires two arguments, namely + the pointer under study and a size in bytes. + The only supported builtin is: [initialized]. + [t] can denote ranges of memory locations. + [p] is the predicate under testing. *) + +val call_valid: + loc:location -> kernel_function -> string -> typ -> Env.t -> term -> + predicate -> exp * Env.t +(* [call_valid ~loc kf name ctx env t p] creates a call to the E-ACSL memory + builtin [valid] or [valid_read] according to [name]. + [t] can denote ranges of memory locations. + [p] is the predicate under testing. *) + +(**************************************************************************) +(********************** Forward references ********************************) +(**************************************************************************) + +val predicate_to_exp_ref: + (kernel_function -> Env.t -> predicate -> exp * Env.t) ref + +val term_to_exp_ref: + (kernel_function -> Env.t -> term -> exp * Env.t) ref \ No newline at end of file diff --git a/src/plugins/e-acsl/src/code_generator/quantif.ml b/src/plugins/e-acsl/src/code_generator/quantif.ml new file mode 100644 index 0000000000000000000000000000000000000000..58dad26a6507d6b4025b464c686275835153f8c3 --- /dev/null +++ b/src/plugins/e-acsl/src/code_generator/quantif.ml @@ -0,0 +1,234 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C's E-ACSL plug-in. *) +(* *) +(* Copyright (C) 2012-2018 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +open Cil_types +open Cil +open Cil_datatype + +let predicate_to_exp_ref + : (kernel_function -> Env.t -> predicate -> exp * Env.t) ref + = Extlib.mk_fun "named_predicate_to_exp_ref" + +let compute_quantif_guards quantif bounded_vars hyps = + let error msg pp x = + let msg1 = Format.asprintf msg pp x in + let msg2 = + Format.asprintf "@[ in quantification@ %a@]" + Printer.pp_predicate quantif + in + Error.untypable (msg1 ^ msg2) + in + let rec left_term acc vars left_bound t = match t.term_node with + | TLogic_coerce(_, t) -> left_term acc vars left_bound t + | TLval(TVar x, TNoOffset) -> + (* check if [x] is the correct variable *) + let v, vars = match vars with + | [] -> error "@[too much constraint(s)%a@]" (fun _ () -> ()) () + | v :: tl -> match v.lv_type with + | Ctype ty when isIntegralType ty -> v, tl + | Linteger -> v, tl + | Ltype _ as ty when Logic_const.is_boolean_type ty -> v, tl + | Ctype _ | Ltype _ | Lvar _ | Lreal | Larrow _ -> + error "@[non integer variable %a@]" Printer.pp_logic_var v + in + if Logic_var.equal x v then acc, Some (left_bound, x), vars + else error "@[invalid binder %a@]" Printer.pp_term t + | _ -> error "@[invalid binder %a@]" Printer.pp_term t + in + let rec parse acc vars p = match p.pred_content with + | Pand(p, { pred_content = Prel((Rlt | Rle) as r, t1, t2) }) -> + (* && is left-associative in the AST *) + let acc, partial, vars = parse acc vars p in + (match partial with + | None -> + (* left part of a new constraint: the searched variable is [t2] *) + left_term acc vars (t1, r) t2 + | Some ((t_left, r_left), v) -> + (* right part of an existing constraint: the variable is [t1] *) + let rec right_term t = match t.term_node with + | TLogic_coerce(_, t) -> right_term t + | TLval(TVar x, TNoOffset) -> + if Logic_var.equal x v then + (* new full constraint found *) + (t_left, r_left, x, r, t2) :: acc, None, vars + else + error "@[invalid binder %a@]" Printer.pp_term t + | _ -> error "@[invalid binder %a@]" Printer.pp_term t + in + right_term t1) + | Prel((Rlt | Rle) as r, t1, t2) -> + (* left-most predicate: the searched variable is [t2] *) + left_term acc vars (t1, r) t2 + | _ -> error "@[invalid guard %a@]" Printer.pp_predicate p + in + let acc, partial, vars = parse [] bounded_vars hyps in + (match partial with + | None -> () + | Some(_, x) -> + error "@[missing upper-bound for variable %a@]" Printer.pp_logic_var x); + (match vars with + | [] -> () + | _ :: _ -> + let msg = + Format.asprintf + "@[unguarded variable%s %tin quantification@ %a@]" + (if List.length vars = 1 then "" else "s") + (fun fmt -> + List.iter + (fun v -> Format.fprintf fmt "@[%a @]" Printer.pp_logic_var v) + vars) + Printer.pp_predicate quantif + in + Error.untypable msg); + List.rev acc + +(* It could happen that the bounds provided for a quantified [lv] are empty + in the sense that [min <= lv <= max] but [min > max]. In such cases, \true + (or \false depending on the quantification) should be generated instead of + nested loops. + [has_empty_quantif_with_false_negative] partially detects such cases: + Case 1: an empty quantification was detected for sure, return true. + Case 2: we don't know, return false. *) +let rec has_empty_quantif_with_false_negative = function + | [] -> + (* case 2 *) + false + | (t1, rel1, _, rel2, t2) :: guards -> + let iv1 = Interval.(extract_ival (infer t1)) in + let iv2 = Interval.(extract_ival (infer t2)) in + let lower_bound, _ = Ival.min_and_max iv1 in + let _, upper_bound = Ival.min_and_max iv2 in + match lower_bound, upper_bound with + | Some lower_bound, Some upper_bound -> + let res = match rel1, rel2 with + | Rle, Rle -> lower_bound > upper_bound + | Rle, Rlt | Rlt, Rle -> lower_bound >= upper_bound + | Rlt, Rlt -> lower_bound >= Z.sub upper_bound Z.one + | _ -> assert false + in + res (* case 1 *) || has_empty_quantif_with_false_negative guards + | None, _ | _, None -> + has_empty_quantif_with_false_negative guards + +let () = Typing.compute_quantif_guards_ref := compute_quantif_guards + +module Label_ids = + State_builder.Counter(struct let name = "E_ACSL.Label_ids" end) + +let convert kf env loc is_forall p bounded_vars hyps goal = + (* part depending on the kind of quantifications + (either universal or existential) *) + let init_val, found_val, mk_guard = + let z = zero ~loc in + let o = one ~loc in + if is_forall then o, z, (fun x -> x) + else z, o, (fun e -> new_exp ~loc:e.eloc (UnOp(LNot, e, intType))) + in + (* universal quantification over integers (or a subtype of integer) *) + let guards = compute_quantif_guards p bounded_vars hyps in + match has_empty_quantif_with_false_negative guards, is_forall with + | true, true -> + Cil.one ~loc, env + | true, false -> + Cil.zero ~loc, env + | false, _ -> + begin + (* transform [guards] into [lscope_var list], + and update logic scope in the process *) + let lvs_guards, env = List.fold_right + (fun (t1, rel1, lv, rel2, t2) (lvs_guards, env) -> + let lvs = Lscope.Lvs_quantif(t1, rel1, lv, rel2, t2) in + let env = Env.Logic_scope.extend env lvs in + lvs :: lvs_guards, env) + guards + ([], env) + in + let var_res, res, env = + (* variable storing the result of the quantifier *) + let name = if is_forall then "forall" else "exists" in + Env.new_var + ~loc + ~name + env + None + intType + (fun v _ -> + let lv = var v in + [ mkStmtOneInstr ~valid_sid:true (Set(lv, init_val, loc)) ]) + in + let end_loop_ref = ref dummyStmt in + (* innermost block *) + let mk_innermost_block env = + (* innermost loop body: store the result in [res] and go out according + to evaluation of the goal *) + let named_predicate_to_exp = !predicate_to_exp_ref in + let test, env = named_predicate_to_exp kf (Env.push env) goal in + let then_block = mkBlock [ mkEmptyStmt ~loc () ] in + let else_block = + (* use a 'goto', not a simple 'break' in order to handle 'forall' with + multiple binders (leading to imbricated loops) *) + mkBlock + [ mkStmtOneInstr ~valid_sid:true (Set(var var_res, found_val, loc)); + mkStmt ~valid_sid:true (Goto(end_loop_ref, loc)) ] + in + let blk, env = Env.pop_and_get + env + (mkStmt ~valid_sid:true + (If(mk_guard test, then_block, else_block, loc))) + ~global_clear:false + Env.After + in + let blk = Cil.flatten_transient_sub_blocks blk in + [ mkStmt ~valid_sid:true (Block blk) ], env + in + let stmts, env = + Loops.mk_nested_loops ~loc mk_innermost_block kf env lvs_guards + in + let env = + Env.add_stmt env (mkStmt ~valid_sid:true (Block (mkBlock stmts))) + in + (* where to jump to go out of the loop *) + let end_loop = mkEmptyStmt ~loc () in + let label_name = "e_acsl_end_loop" ^ string_of_int (Label_ids.next ()) in + let label = Label(label_name, loc, false) in + end_loop.labels <- label :: end_loop.labels; + end_loop_ref := end_loop; + let env = Env.add_stmt env end_loop in + res, env + end + +let quantif_to_exp kf env p = + let loc = p.pred_loc in + match p.pred_content with + | Pforall(bounded_vars, { pred_content = Pimplies(hyps, goal) }) -> + convert kf env loc true p bounded_vars hyps goal + | Pforall _ -> Error.not_yet "unguarded \\forall quantification" + | Pexists(bounded_vars, { pred_content = Pand(hyps, goal) }) -> + convert kf env loc false p bounded_vars hyps goal + | Pexists _ -> Error.not_yet "unguarded \\exists quantification" + | _ -> assert false + +(* +Local Variables: +compile-command: "make" +End: +*) diff --git a/src/plugins/e-acsl/src/code_generator/quantif.mli b/src/plugins/e-acsl/src/code_generator/quantif.mli new file mode 100644 index 0000000000000000000000000000000000000000..099a6a4c7431d7a16c2587f5d2093264aac114a1 --- /dev/null +++ b/src/plugins/e-acsl/src/code_generator/quantif.mli @@ -0,0 +1,42 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C's E-ACSL plug-in. *) +(* *) +(* Copyright (C) 2012-2018 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(** Convert quantifiers. *) + +open Cil_types + +val quantif_to_exp: + kernel_function -> Env.t -> predicate -> exp * Env.t +(** The given predicate must be a quantification. *) + +(* ***********************************************************************) +(** {2 Forward references} *) +(* ***********************************************************************) + +val predicate_to_exp_ref: + (kernel_function -> Env.t -> predicate -> exp * Env.t) ref + +(* +Local Variables: +compile-command: "make" +End: +*) diff --git a/src/plugins/e-acsl/src/code_generator/rational.ml b/src/plugins/e-acsl/src/code_generator/rational.ml new file mode 100644 index 0000000000000000000000000000000000000000..815c755da228d1aac5dec3aa3ceaa4455c036268 --- /dev/null +++ b/src/plugins/e-acsl/src/code_generator/rational.ml @@ -0,0 +1,232 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C's E-ACSL plug-in. *) +(* *) +(* Copyright (C) 2012-2018 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +open Cil_types + +(* No init_set for GMPQ: init then set separately *) +let init_set ~loc lval vi_e e = + Cil.mkStmt + ~valid_sid:true + (Block (Cil.mkBlock + [ Gmp.init ~loc vi_e ; + Gmp.affect ~loc lval vi_e e ])) + +let create ~loc ?name e env t_opt = + let ty = Cil.typeOf e in + if Gmp_types.Z.is_t ty then + (* GMPQ has no builtin for creating Q from Z. Hence: + 1) Get the MPZ as a string: gmZ_get_str + 2) Set the MPQ with that string: gmpQ_set_str *) + Error.not_yet "reals: creating Q from Z" + else if Gmp_types.Q.is_t ty then + e, env + else + let _, e, env = + Env.new_var + ~loc + ?name + env + t_opt + (Gmp_types.Q.t ()) + (fun vi vi_e -> + [ Gmp.init ~loc vi_e ; + Gmp.affect ~loc (Cil.var vi) vi_e e ]) + in + e, env + +exception Not_a_decimal of string +exception Is_a_float + +(* The possible float suffixes (ISO C 6.4.4.2) are lLfF. + dD is a GNU extension accepted by Frama-C (only!) in the logic *) +let float_suffixes = [ 'f'; 'F'; 'l'; 'L'; 'd'; 'D' ] + +(* Computes the fractional representation of a decimal number. + Does NOT perform reduction. + Example: [dec_to_frac "43.567"] evaluates to ["43567/1000"] + Complexity: Linear + Original Author: Frédéric Recoules + + It iterates **once** over [str] during which three cases are distinguished, + example for "43.567": + Case1: pre: no '.' has been found yet ==> copy current char into buf + buf: | 4 | | | | | | | | | | | | + | 4 | 3 | | | | | | | | | | | + Case2: mid: current char is '.' ==> put "/1" into buf at [(length str) - 1] + buf: | 4 | 3 | | | | / | 1 | | | | | | + Case3: post: a '.' was found ==> put current char in numerator AND '0' in den + buf: | 4 | 3 | 5 | | | / | 1 | 0 | | | | | + | 4 | 3 | 5 | 6 | | / | 1 | 0 | 0 | | | | + | 4 | 3 | 5 | 6 | 7 | / | 1 | 0 | 0 | 0 | | | *) +let decimal_to_fractional str = + let rec post str len buf len' i = + if i = len then + Bytes.sub_string buf 0 len' + else + match String.unsafe_get str i with + | c when '0' <= c && c <= '9' -> + Bytes.unsafe_set buf (i - 1) c; + Bytes.unsafe_set buf len' '0'; + post str len buf (len' + 1) (i + 1) + | c when List.mem c float_suffixes -> + (* [JS] a suffix denoting a C type is possible *) + assert (i = len - 1); + raise Is_a_float + | _ -> + raise (Not_a_decimal str) + in + let mid buf len = + Bytes.unsafe_set buf (len - 1) '/'; + Bytes.unsafe_set buf len '1' + in + let rec pre str len buf i = + if i = len then + str + else + match String.unsafe_get str i with + | '.' -> + mid buf len; + post str len buf (len + 1) (i + 1) + | c when '0' <= c && c <= '9' -> + Bytes.unsafe_set buf i c; + pre str len buf (i + 1) + | c when List.mem c float_suffixes -> + (* [JS] a suffix denoting a C type is possible *) + assert (i = len - 1); + raise Is_a_float + | _ -> + raise (Not_a_decimal str) + in + let strlen = String.length str in + let buflen = + (* The fractional representation is at most twice as lengthy + as the decimal one. *) + 2 * strlen + in + try pre str strlen (Bytes.create buflen) 0 + with Is_a_float -> str (* just left it unchanged *) + +(* ACSL considers strings written in decimal expansion to be reals. + Yet GMPQ considers them to be double: + they MUST be converted into fractional representation. *) +let normalize_str str = + try + decimal_to_fractional str + with Invalid_argument _ -> + Error.not_yet "number not written in decimal expansion" + +let cast_to_z ~loc:_ ?name:_ e _env = + assert (Gmp_types.Q.is_t (Cil.typeOf e)); + Error.not_yet "reals: cast from R to Z" + +let add_cast ~loc ?name e env ty = + (* TODO: The best solution would actually be to directly write all the needed + functions as C builtins then just call them here depending on the situation + at hand. *) + assert (Gmp_types.Q.is_t (Cil.typeOf e)); + let get_double e env = + let _, e, env = + Env.new_var + ~loc + ?name + env + None + Cil.doubleType + (fun v _ -> + [ Misc.mk_call ~loc ~result:(Cil.var v) "__gmpq_get_d" [ e ] ]) + in + e, env + in + match Cil.unrollType ty with + | TFloat(FLongDouble, _) -> + (* The biggest floating-point type we can extract from GMPQ is double *) + Error.not_yet "R to long double" + | TFloat(FDouble, _) -> + get_double e env + | TFloat(FFloat, _) -> + (* No "get_float" in GMPQ, but fortunately, [float] \subset [double]. + HOWEVER: going through double as intermediate step might be unsound since + it could cause double rounding. See: [Boldo2013, Sec 2.2] + https://hal.inria.fr/hal-00777639/document *) + let e, env = get_double e env in + Options.warning + ~once:true "R to float: double rounding might cause unsoundness"; + Cil.mkCastT ~force:false ~e ~oldt:Cil.doubleType ~newt:ty, env + | TInt(IULongLong, _) -> + (* The biggest C integer type we can extract from GMP is ulong *) + Error.not_yet "R to unsigned long long" + | TInt _ -> + (* 1) Cast R to Z using cast_to_z + 2) Extract ulong from Z + 3) Potentially cast ulong to ty *) + Error.not_yet "R to Int" + | _ -> + Error.not_yet "R to <typ>" + +let cmp ~loc bop e1 e2 env t_opt = + let fname = "__gmpq_cmp" in + let name = Misc.name_of_binop bop in + let e1, env = create ~loc e1 env None (* TODO: t1_opt could be provided *) in + let e2, env = create ~loc e2 env None (* TODO: t2_opt could be provided *) in + let _, e, env = + Env.new_var + ~loc + env + t_opt + ~name + Cil.intType + (fun v _ -> [ Misc.mk_call ~loc ~result:(Cil.var v) fname [ e1; e2 ] ]) + in + Cil.new_exp ~loc (BinOp(bop, e, Cil.zero ~loc, Cil.intType)), env + +let new_var_and_init ~loc ?scope ?name env t_opt mk_stmts = + Env.new_var + ~loc + ?scope + ?name + env + t_opt + (Gmp_types.Q.t ()) + (fun v e -> Gmp.init ~loc e :: mk_stmts v e) + +let name_arith_bop = function + | PlusA -> "__gmpq_add" + | MinusA -> "__gmpq_sub" + | Mult -> "__gmpq_mul" + | Div -> "__gmpq_div" + | Mod | Lt | Gt | Le | Ge | Eq | Ne | BAnd | BXor | BOr | LAnd | LOr + | Shiftlt | Shiftrt | PlusPI | IndexPI | MinusPI | MinusPP -> assert false + +let binop ~loc bop e1 e2 env t_opt = + let name = name_arith_bop bop in + let e1, env = create ~loc e1 env None (* TODO: t1_opt could be provided *) in + let e2, env = create ~loc e2 env None (* TODO: t2_opt could be provided *) in + let mk_stmts _ e = [ Misc.mk_call ~loc name [ e; e1; e2 ] ] in + let name = Misc.name_of_binop bop in + let _, e, env = new_var_and_init ~loc ~name env t_opt mk_stmts in + e, env + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff --git a/src/plugins/e-acsl/src/code_generator/rational.mli b/src/plugins/e-acsl/src/code_generator/rational.mli new file mode 100644 index 0000000000000000000000000000000000000000..94d676097f42f83901223e536da0397196fd883a --- /dev/null +++ b/src/plugins/e-acsl/src/code_generator/rational.mli @@ -0,0 +1,64 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C's E-ACSL plug-in. *) +(* *) +(* Copyright (C) 2012-2018 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(** Generation of rational numbers. *) + +open Cil_types + +val create: loc:location -> ?name:string -> exp -> Env.t -> term option -> + exp * Env.t +(** Create a real *) + +val init_set: loc:location -> lval -> exp -> exp -> stmt +(** [init_set lval lval_as_exp exp] sets [lval] to [exp] while guranteeing that + [lval] is properly initialized wrt the underlying real library. *) + +val normalize_str: string -> string +(** Normalize the string so that it fits the representation used by the + underlying real library. For example, "0.1" is a real number in ACSL + whereas it is considered as a double by `libgmp` because it is written in + decimal expansion. In order to make `libgmp` consider it to be a rational, + it must be converted into "1/10". *) + +val cast_to_z: loc:location -> ?name:string -> exp -> Env.t -> exp * Env.t +(** Assumes that the given exp is of real type and casts it into Z *) + +val add_cast: loc:location -> ?name:string -> exp -> Env.t -> typ -> + exp * Env.t +(** Assumes that the given exp is of real type and casts it into + the given typ *) + +val binop: loc:location -> binop -> exp -> exp -> Env.t -> term option -> + exp * Env.t +(** Applies [binop] to the given expressions. The optional term + indicates whether the comparison has a correspondance in the logic. *) + +val cmp: loc:location -> binop -> exp -> exp -> Env.t -> term option -> + exp * Env.t +(** Compares two expressions according to the given [binop]. The optional term + indicates whether the comparison has a correspondance in the logic. *) + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff --git a/src/plugins/e-acsl/src/code_generator/temporal.ml b/src/plugins/e-acsl/src/code_generator/temporal.ml new file mode 100644 index 0000000000000000000000000000000000000000..7abd090bfb7f8104bde9b77820c015b9286c1730 --- /dev/null +++ b/src/plugins/e-acsl/src/code_generator/temporal.ml @@ -0,0 +1,535 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C's E-ACSL plug-in. *) +(* *) +(* Copyright (C) 2012-2018 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* Detailed description of transformations implemented in this file is + presented in Sections 2 and 3 of the RV'17 paper "Runtime Detection of + Temporal Memory Errors" by K. Vorobyov, N. Kosmatov, J Signoles and + A. Jakobsson. *) + +module RTL = Functions.RTL +module Libc = Functions.Libc +open Cil_types +open Cil_datatype + +let generate = ref false +let enable param = generate := param +let is_enabled () = !generate + +(* ************************************************************************** *) +(* Types {{{ *) +(* ************************************************************************** *) + +(* Type of identifier tracked by a LHS referent number *) +type flow = + | Direct (* take origin number of RHS *) + | Indirect (* take referent number of RHS *) + | Copy (* Copy shadow from RHS to LHS *) +(* }}} *) + +(* ************************************************************************** *) +(* Miscellaneous {{{ *) +(* ************************************************************************** *) + +(* Shortcuts for SA in Mmodel_analysis *) +let must_model_exp exp env = + let kf, bhv = Extlib.the (Env.current_kf env), Env.get_behavior env in + Mmodel_analysis.must_model_exp ~bhv ~kf exp + +let must_model_lval lv env = + let kf, bhv = Extlib.the (Env.current_kf env), Env.get_behavior env in + Mmodel_analysis.must_model_lval ~bhv ~kf lv + +let must_model_vi vi env = + let kf, bhv = Extlib.the (Env.current_kf env), Env.get_behavior env in + Mmodel_analysis.must_model_vi ~bhv ~kf vi + +(* }}} *) + +(* ************************************************************************* *) +(* Generate analysis function calls {{{ *) +(* ************************************************************************** *) + +module Mk: sig + (* Generate either + - [store_nblock(lhs, rhs)], or + - [store_nreferent(lhs, rhs)] + function call based on the value of [flow] *) + val store_reference: loc:location -> flow -> lval -> exp -> stmt + + (* Generate a [save_*_parameter] call *) + val save_param: loc:location -> flow -> exp -> int -> stmt + + (* Generate [pull_parameter] call *) + val pull_param: loc:location -> varinfo -> int -> stmt + + (* Generate [(save|pull)_return(lhs, param_no)] call *) + val handle_return_referent: save:bool -> loc:location -> exp -> stmt + + (* Generate [reset_return()] call *) + val reset_return_referent: loc:location -> stmt + + (* Generate [memcpy(lhs, rhs, size)] function call assuming that [lhs = rhs] + represents an assignment of struct to a struct, that is, both sides are + left values and we need to use addressof for both sides *) + val temporal_memcpy_struct: loc:location -> lval -> exp -> stmt +end = struct + + let store_reference ~loc flow lhs rhs = + let fname = match flow with + | Direct -> "store_nblock" + | Indirect -> "store_nreferent" + | Copy -> Options.fatal "Copy flow type in store_reference" + in + let fname = RTL.mk_temporal_name fname in + Misc.mk_call ~loc fname [ Cil.mkAddrOf ~loc lhs; rhs ] + + let save_param ~loc flow lhs pos = + let infix = match flow with + | Direct -> "nblock" + | Indirect -> "nreferent" + | Copy -> "copy" + in + let fname = "save_" ^ infix ^ "_parameter" in + let fname = RTL.mk_temporal_name fname in + Misc.mk_call ~loc fname [ lhs ; Cil.integer ~loc pos ] + + let pull_param ~loc vi pos = + let exp = Cil.mkAddrOfVi vi in + let fname = RTL.mk_temporal_name "pull_parameter" in + let sz = Cil.kinteger ~loc IULong (Cil.bytesSizeOf vi.vtype) in + Misc.mk_call ~loc fname [ exp ; Cil.integer ~loc pos ; sz ] + + let handle_return_referent ~save ~loc lhs = + let fname = match save with + | true -> "save_return" + | false -> "pull_return" + in + (* TODO: Returning structs is unsupported so far *) + (match (Cil.typeOf lhs) with + | TPtr _ -> () + | _ -> Error.not_yet "Struct in return"); + Misc.mk_call ~loc (RTL.mk_temporal_name fname) [ lhs ] + + let reset_return_referent ~loc = + Misc.mk_call ~loc (RTL.mk_temporal_name "reset_return") [] + + let temporal_memcpy_struct ~loc lhs rhs = + let fname = RTL.mk_temporal_name "memcpy" in + let size = Cil.sizeOf ~loc (Cil.typeOfLval lhs) in + Misc.mk_call ~loc fname [ Cil.mkAddrOf ~loc lhs; rhs; size ] +end +(* }}} *) + +(* ************************************************************************** *) +(* Handle assignments {{{ *) +(* ************************************************************************** *) + +(* Given an lvalue [lhs] representing LHS of an assignment, and an expression + [rhs] representing its RHS compute triple (l,r,f), such that: + - lval [l] and exp [r] are addresses of a pointer and a memory block, and + - flow [f] indicates how to update the meta-data of [l] using information + stored by [r]. The values of [f] indicate the following + + Direct - referent number of [l] is assigned the referent number of [r] + + Indirect - referent number of [l] is assigned the origin number of [r] + + Copy - metadata of [r] is copied to metadata of [l] *) +let assign ?(ltype) lhs rhs loc = + (* Do not use [Extlib.opt_conv] here, application of the [None] part should + not be evaluated at this point, as otherwise it will lead to an exception + via [Cil.typeOfLval] later *) + let ltype = match ltype with + | Some l -> l + | None -> (Cil.typeOfLval lhs) + in + match Cil.unrollType ltype with + | TPtr _ -> + let base, _ = Misc.ptr_index rhs in + let rhs, flow = + (match base.enode with + | AddrOf _ + | StartOf _ -> rhs, Direct + (* Unary operator describes !, ~ or -: treat it same as Const since + it implies integer or logical operations. This case is rare but + happens: for instance in Gap SPEC CPU benchmark the returned pointer + is assigned -1 (for whatever bizarre reason) *) + | Const _ | UnOp _ -> base, Direct + (* Special case for literal strings which E-ACSL rewrites into + global variables: take the origin number of a string *) + | Lval(Var vi, _) when RTL.is_generated_name vi.vname -> + base, Direct + (* Lvalue of a pointer type can be a cast of an integral type, for + instance for the case when address is taken by value (shown via the + following example). + uintptr_t addr = ...; + char *p = (char* )addr; + If this is the case then the analysis takes the value of a variable. *) + | Lval lv -> + if Cil.isPointerType (Cil.unrollType (Cil.typeOfLval lv)) then + Cil.mkAddrOf ~loc lv, Indirect + else + rhs, Direct + (* Binary operation which yields an integer (or FP) type. + Since LHS is of pointer type we assume that the whole integer + expression computes to an address for which there is no + outer container, so the only thing to do is to take origin number *) + | BinOp(op, _, _, _) -> + (* At this point [ptr_index] should have split pointer arithmetic into + base pointer and index so there should be no pointer arithmetic + operations there. The following bit is to make sure of it. *) + (match op with + | MinusPI | PlusPI | IndexPI -> assert false + | _ -> ()); + base, Direct + | _ -> assert false) + in Some (lhs, rhs, flow) + | TNamed _ -> assert false + | TInt _ | TFloat _ | TEnum _ -> None + | TComp _ -> + let rhs = match rhs.enode with + | AddrOf _ -> rhs + | Lval lv -> Cil.mkAddrOf ~loc lv + | Const _ | SizeOf _ | SizeOfE _ | SizeOfStr _ | AlignOf _ | AlignOfE _ + | UnOp _ | BinOp _ | CastE _ | StartOf _ | Info _ -> + Options.abort "unsupported RHS %a" Printer.pp_exp rhs + in Some (lhs, rhs, Copy) + (* va_list is a builtin type, we assume it has no pointers here and treat + it as a "big" integer rather than a struct *) + | TBuiltin_va_list _ -> None + | TArray _ -> Some (lhs, rhs, Direct) + (* void type should not happen as we are dealing with assignments *) + | TVoid _ -> Options.fatal "Void type in assignment" + | TFun _ -> Options.fatal "TFun type in assignment" + +(* Generate a statement tracking temporal metadata associated with assignment + [lhs] = [rhs], where lhs is a left value and [rhs] is an expression. *) +let mk_stmt_from_assign loc lhs rhs = + let fn (lhs, rhs, flow) = match flow with + | Direct | Indirect -> Mk.store_reference ~loc flow lhs rhs + | Copy -> Mk.temporal_memcpy_struct ~loc lhs rhs + in + Extlib.opt_map fn (assign lhs rhs loc) +(* }}} *) + +(* ************************************************************************** *) +(* Handle Set instructions {{{ *) +(* ************************************************************************** *) + +(* Top-level handler for Set instructions *) +let set_instr ?(post=false) current_stmt loc lhs rhs env = + if must_model_lval lhs env then + Extlib.may_map + (fun stmt -> Env.add_stmt ~before:current_stmt ~post env stmt) + ~dft:env + (mk_stmt_from_assign loc lhs rhs) + else + env +(* }}} *) + +(* ************************************************************************** *) +(* Handle Call instructions {{{ *) +(* ************************************************************************** *) + +module Function_call: sig + (* Top-level handler for Call instructions *) + val instr: stmt -> lval option -> exp -> exp list -> location -> Env.t -> Env.t +end = struct + + (* Track function arguments: export referents of arguments to a global + structure so they can be retrieved once that function is called *) + let save_params current_stmt loc args env = + let (env, _) = List.fold_left + (fun (env, index) param -> + let lv = Mem(param), NoOffset in + let ltype = Cil.typeOf param in + let vals = assign ~ltype lv param loc in + Extlib.may_map + (fun (_, rhs, flow) -> + let env = + if must_model_exp param env then + let stmt = Mk.save_param ~loc flow rhs index in + Env.add_stmt ~before:current_stmt ~post:false env stmt + else env + in + (env, index+1)) + ~dft:(env, index+1) + vals) + (env, 0) + args + in env + + (* Update local environment with a statement tracking temporal metadata + associated with assignment [ret] = [func(args)]. *) + let call_with_ret ?(alloc=false) current_stmt loc ret env = + let rhs = Cil.new_exp ~loc (Lval ret) in + let vals = assign ret rhs loc in + (* Track referent numbers of assignments via function calls. + Library functions (i.e., with no source code available) that return + values are considered to be functions that allocate memory. They are + considered so because they need to be handled exactly as memory + allocating functions, that is, the referent of the returned pointer is + assigned the origin number associated with the return value. For + instance, for some [p = call();] [store_nblock( *p,..)] is appended. + Note that for this we need [Direct] flow and also dereference the + pointer to get its number. This is done in the following statement + (where variable [alloc] indicates whether a function is a + memory-allocating function or not). + + Alternatively, if a function does not allocate memory and its body has + been instrumented, then information about referent numbers should be + stored in the internal data structure and it is retrieved using + [pull_return] added via a call to [Mk.handle_return_referent] *) + Extlib.may_map + (fun (lhs, rhs, flow) -> + let flow, rhs = match flow with + | Indirect when alloc -> Direct, (Misc.mk_deref ~loc rhs) + | _ -> flow, rhs + in + let stmt = + if alloc then + Mk.store_reference ~loc flow lhs rhs + else + Mk.handle_return_referent ~save:false ~loc (Cil.mkAddrOf ~loc lhs) + in + Env.add_stmt ~before:current_stmt ~post:true env stmt) + ~dft:env + vals + + (* Update local environment with a statement tracking temporal metadata + associated with memcpy/memset call *) + let call_memxxx current_stmt loc args fexp env = + if Libc.is_memcpy fexp || Libc.is_memset fexp then + let name = match fexp.enode with + | Lval(Var vi, _) -> vi.vname + | _ -> Options.fatal "[Temporal.call_memxxx] not a left-value" + in + let stmt = Misc.mk_call ~loc (RTL.mk_temporal_name name) args in + Env.add_stmt ~before:current_stmt ~post:false env stmt + else + env + + let instr current_stmt ret fexp args loc env = + (* Add function calls to reset_parameters and reset_return before each + function call regardless. They are not really required, as if the + instrumentation is correct then the right parameters will be saved + and the right parameter will be pulled at runtime. In practice, however, + it makes sense to make this somewhat-debug-level-call. In production mode + the implementation of the function should be empty and compiler should + be able to optimize that code out. *) + let name = (RTL.mk_temporal_name "reset_parameters") in + let stmt = Misc.mk_call ~loc name [] in + let env = Env.add_stmt ~before:current_stmt ~post:false env stmt in + let stmt = Mk.reset_return_referent ~loc in + let env = Env.add_stmt ~before:current_stmt ~post:false env stmt in + (* Push parameters with either a call to a function pointer or a function + definition otherwise there is no point. *) + let has_def = Functions.has_fundef fexp in + let env = + if Cil.isFunctionType (Cil.typeOf fexp) || has_def then + save_params current_stmt loc args env + else + env + in + (* Handle special cases of memcpy/memset *) + let env = call_memxxx current_stmt loc args fexp env in + (* Memory allocating functions have no definitions so below expression + should capture them *) + let alloc = not has_def in + Extlib.may_map + (fun lhs -> + if must_model_lval lhs env then + call_with_ret ~alloc current_stmt loc lhs env + else env) + ~dft:env + ret +end +(* }}} *) + +(* ************************************************************************** *) +(* Handle Local_init instructions {{{ *) +(* ************************************************************************** *) +module Local_init: sig + (* Top-level handler for Local_init instructions *) + val instr: stmt -> varinfo -> local_init -> location -> Env.t -> Env.t +end = struct + + let rec handle_init current_stmt offset loc vi init env = + match init with + | SingleInit exp -> + set_instr ~post:true current_stmt loc (Var vi, offset) exp env + | CompoundInit(_, inits) -> + List.fold_left + (fun acc (off, init) -> + handle_init current_stmt (Cil.addOffset off offset) loc vi init acc) + env + inits + + let instr current_stmt vi li loc env = + if must_model_vi vi env then + match li with + | AssignInit init -> + handle_init current_stmt NoOffset loc vi init env + | ConsInit(fexp, args, _) -> + let ret = Some (Cil.var vi) in + let fexp = Cil.evar ~loc fexp in + Function_call.instr current_stmt ret fexp args loc env + else env +end +(* }}} *) + +(* ************************************************************************** *) +(* Track function arguments {{{ *) +(* ************************************************************************** *) + +(* Update local environment with a statement tracking temporal metadata + associated with adding a function argument to a stack frame *) +let track_argument ?(typ) param index env = + let typ = Extlib.opt_conv param.vtype typ in + match Cil.unrollType typ with + | TPtr _ + | TComp _ -> + let stmt = Mk.pull_param ~loc:Location.unknown param index in + Env.add_stmt ~post:false env stmt + | TInt _ | TFloat _ | TEnum _ | TBuiltin_va_list _ -> env + | TNamed _ -> assert false + | TVoid _ |TArray _ | TFun _ -> + Options.fatal "Failed to handle function parameter" +(* }}} *) + +(* ************************************************************************** *) +(* Handle return statements {{{ *) +(* ************************************************************************** *) + +(* Update local environment [env] with statements tracking return value + of a function. *) +let handle_return_stmt loc ret env = + match ret.enode with + | Lval lv -> + if Cil.isPointerType (Cil.typeOfLval lv) then + let exp = Cil.mkAddrOf ~loc lv in + let stmt = Mk.handle_return_referent ~loc ~save:true exp in + Env.add_stmt ~post:false env stmt + else + env + | _ -> Options.fatal "Something other than Lval in return" + +let handle_return_stmt loc ret env = + if must_model_exp ret env then + handle_return_stmt loc ret env + else + env +(* }}} *) + +(* ************************************************************************** *) +(* Handle instructions {{{ *) +(* ************************************************************************** *) + +(* Update local environment [env] with statements tracking + instruction [instr] *) +let handle_instruction current_stmt instr env = + match instr with + | Set(lv, exp, loc) -> set_instr current_stmt loc lv exp env + | Call(ret, fexp, args, loc) -> + Function_call.instr current_stmt ret fexp args loc env + | Local_init(vi, li, loc) -> Local_init.instr current_stmt vi li loc env + | Asm _ -> Options.warning ~once:true ~current:true "@[Analysis is\ +potentially incorrect in presence of assembly code.@]"; env + | Skip _ | Code_annot _ -> env +(* }}} *) + +(* ************************************************************************** *) +(* Initialization of globals {{{ *) +(* ************************************************************************** *) + +(* Provided that [vi] is a global variable initialized by the initializer [init] + at offset [off] return [Some stmt], where [stmt] is a statement + tracking that initialization. If [init] does not need to be tracked than + the return value is [None] *) +let mk_global_init ~loc vi off init env = + let exp = match init with + | SingleInit e -> e + (* Compound initializers should have been thrown away at this point *) + | _ -> Options.fatal "Unexpected ComppoundInit in global initializer" + in + (* Initializer expression can be a literal string, so look up the + corresponding variable which that literal string has been converted to *) + let exp = + try let rec get_string e = match e.enode with + | Const(CStr str) -> str + | CastE(_, exp) -> get_string exp + | _ -> raise Not_found + in + let str = get_string exp in + Cil.evar ~loc (Literal_strings.find str) + with + (* Not a literal string: just use the expression at hand *) + Not_found -> exp + in + (* The input [vi] is from the old project, so get the corresponding variable + from the new one, otherwise AST integrity is violated *) + let vi = Visitor_behavior.Get.varinfo (Env.get_behavior env) vi in + let lv = Var vi, off in + mk_stmt_from_assign loc lv exp +(* }}} *) + +(* ************************************************************************** *) +(* Public API {{{ *) +(* ************************************************************************** *) + +let handle_function_parameters kf env = + if is_enabled () then + let env, _ = List.fold_left + (fun (env, index) param -> + let param = Visitor_behavior.Get.varinfo (Env.get_behavior env) param in + let env = + if Mmodel_analysis.must_model_vi ~kf param then + track_argument param index env + else env + in env, index + 1) + (env, 0) + (Kernel_function.get_formals kf) + in env + else + env + +let handle_stmt stmt env = + if is_enabled () then begin + match stmt.skind with + | Instr instr -> handle_instruction stmt instr env + | Return(ret, loc) -> Extlib.may_map + (fun ret -> handle_return_stmt loc ret env) ~dft:env ret + | Goto _ | Break _ | Continue _ | If _ | Switch _ | Loop _ | Block _ + | UnspecifiedSequence _ | Throw _ | TryCatch _ | TryFinally _ + | TryExcept _ -> env + end else + env + +let generate_global_init vi off init env = + if is_enabled () then + mk_global_init ~loc:vi.vdecl vi off init env + else + None +(* }}} *) + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff --git a/src/plugins/e-acsl/src/code_generator/temporal.mli b/src/plugins/e-acsl/src/code_generator/temporal.mli new file mode 100644 index 0000000000000000000000000000000000000000..aea63e01f9ec22780acfa8bd226d51025d4b900d --- /dev/null +++ b/src/plugins/e-acsl/src/code_generator/temporal.mli @@ -0,0 +1,50 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C's E-ACSL plug-in. *) +(* *) +(* Copyright (C) 2012-2018 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(** Transformations to detect temporal memory errors (e.g., dereference of + stale pointers). *) + +val enable: bool -> unit +(** Enable/disable temporal transformations *) + +val is_enabled: unit -> bool +(** Return a boolean value indicating whether temporal analysis is enabled *) + +val handle_function_parameters: Cil_types.kernel_function -> Env.t -> Env.t +(** [handle_function_parameters kf env] updates the local environment [env], + according to the parameters of [kf], with statements allowing to track + referent numbers across function calls. *) + +val handle_stmt: Cil_types.stmt -> Env.t -> Env.t +(** Update local environment ([Env.t]) with statements tracking temporal + properties of memory blocks *) + +val generate_global_init: Cil_types.varinfo -> Cil_types.offset -> + Cil_types.init -> Env.t -> Cil_types.stmt option + (** Generate [Some s], where [s] is a statement tracking global initializer + or [None] if there is no need to track it *) + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff --git a/src/plugins/e-acsl/src/code_generator/translate.ml b/src/plugins/e-acsl/src/code_generator/translate.ml new file mode 100644 index 0000000000000000000000000000000000000000..e5775d34faf11d196f415dc74563970eab8b25ca --- /dev/null +++ b/src/plugins/e-acsl/src/code_generator/translate.ml @@ -0,0 +1,1131 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C's E-ACSL plug-in. *) +(* *) +(* Copyright (C) 2012-2018 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +module E_acsl_label = Label +open Cil_types +open Cil_datatype + +let dkey = Options.dkey_translation + +let not_yet env s = + Env.Context.save env; + Error.not_yet s + +let handle_error f env = + let env = Error.handle f env in + Env.Context.restore env + +(* internal to [named_predicate_to_exp] but put it outside in order to not add + extra tedious parameter. + It is [true] iff we are currently visiting \valid. *) +let is_visiting_valid = ref false + +(* ************************************************************************** *) +(* Transforming terms and predicates into C expressions (if any) *) +(* ************************************************************************** *) + +let relation_to_binop = function + | Rlt -> Lt + | Rgt -> Gt + | Rle -> Le + | Rge -> Ge + | Req -> Eq + | Rneq -> Ne + +let name_of_mpz_arith_bop = function + | PlusA -> "__gmpz_add" + | MinusA -> "__gmpz_sub" + | Mult -> "__gmpz_mul" + | Div -> "__gmpz_tdiv_q" + | Mod -> "__gmpz_tdiv_r" + | Lt | Gt | Le | Ge | Eq | Ne | BAnd | BXor | BOr | LAnd | LOr + | Shiftlt | Shiftrt | PlusPI | IndexPI | MinusPI | MinusPP -> assert false + +(* Type of a string that represents a number. + Used when a string is required to encode a constant number because it is not + representable in any C type *) +type strnum = + | Str_Z (* integers *) + | Str_R (* reals *) + | C_number (* integers and floats included *) + +(* convert [e] in a way that it is compatible with the given typing context. *) +let add_cast ~loc ?name env ctx strnum t_opt e = + let mk_mpz e = + let _, e, env = + Env.new_var + ~loc + ?name + env + t_opt + (Gmp_types.Z.t ()) + (fun lv v -> [ Gmp.init_set ~loc (Cil.var lv) v e ]) + in + e, env + in + let e, env = match strnum with + | Str_Z -> mk_mpz e + | Str_R -> Rational.create ~loc ?name e env t_opt + | C_number -> e, env + in + match ctx with + | None -> + e, env + | Some ctx -> + let ty = Cil.typeOf e in + match Gmp_types.Z.is_t ty, Gmp_types.Z.is_t ctx with + | true, true -> + (* Z --> Z *) + e, env + | false, true -> + if Gmp_types.Q.is_t ty then + (* R --> Z *) + Rational.cast_to_z ~loc ?name e env + else + (* C integer --> Z *) + let e = + if not (Cil.isIntegralType ty) && strnum = C_number then + (* special case for \null that must be casted to long: it is the + only non integral value that can be seen as an integer, while the + type system infers that it is C-representable (see + tests/runtime/null.i) *) + Cil.mkCast e Cil.longType (* \null *) + else + e + in + mk_mpz e + | _, false -> + if Gmp_types.Q.is_t ctx then + if Gmp_types.Q.is_t (Cil.typeOf e) then (* R --> R *) e, env + else (* C integer or Z --> R *) Rational.create ~loc ?name e env t_opt + else if Gmp_types.Z.is_t ty || strnum = Str_Z then + (* Z --> C type or the integer is represented by a string: + anyway, it fits into a C integer: convert it *) + let fname, new_ty = + if Cil.isSignedInteger ctx then "__gmpz_get_si", Cil.longType + else "__gmpz_get_ui", Cil.ulongType + in + let _, e, env = + Env.new_var + ~loc + ?name + env + None + new_ty + (fun v _ -> [ Misc.mk_call ~loc ~result:(Cil.var v) fname [ e ] ]) + in + e, env + else if Gmp_types.Q.is_t ty || strnum = Str_R then + (* R --> C type or the real is represented by a string *) + Rational.add_cast ~loc ?name e env ctx + else + (* C type --> another C type *) + Cil.mkCastT ~force:false ~e ~oldt:ty ~newt:ctx, env + +let constant_to_exp ~loc t c = + let mk_real s = + let s = Rational.normalize_str s in + Cil.mkString ~loc s, Str_R + in + match c with + | Integer(n, _repr) -> + let ity = Typing.get_number_ty t in + (match ity with + | Typing.Nan -> assert false + | Typing.Real -> Error.not_yet "real number constant" + | Typing.Rational -> mk_real (Integer.to_string n) + | Typing.Gmpz -> + (* too large integer *) + Cil.mkString ~loc (Integer.to_string n), Str_Z + | Typing.C_float fkind -> + Cil.kfloat ~loc fkind (Int64.to_float (Integer.to_int64 n)), C_number + | Typing.C_integer kind -> + let cast = Typing.get_cast t in + match cast, kind with + | Some ty, (ILongLong | IULongLong) when Gmp_types.Z.is_t ty -> + (* too large integer *) + Cil.mkString ~loc (Integer.to_string n), Str_Z + | Some ty, _ when Gmp_types.Q.is_t ty -> + mk_real (Integer.to_string n) + | (None | Some _), _ -> + (* do not keep the initial string representation because the generated + constant must reflect its type computed by the type system. For + instance, when translating [INT_MAX+1], we must generate a [long + long] addition and so [1LL]. If we keep the initial string + representation, the kind would be ignored in the generated code and + so [1] would be generated. *) + Cil.kinteger64 ~loc ~kind n, C_number) + | LStr s -> Cil.new_exp ~loc (Const (CStr s)), C_number + | LWStr s -> Cil.new_exp ~loc (Const (CWStr s)), C_number + | LChr c -> Cil.new_exp ~loc (Const (CChr c)), C_number + | LReal lr -> + if lr.r_lower = lr.r_upper + then Cil.kfloat ~loc FDouble lr.r_nearest, C_number + else mk_real lr.r_literal + | LEnum e -> Cil.new_exp ~loc (Const (CEnum e)), C_number + +let conditional_to_exp ?(name="if") loc t_opt e1 (e2, env2) (e3, env3) = + let env = Env.pop (Env.pop env3) in + match e1.enode with + | Const(CInt64(n, _, _)) when Integer.is_zero n -> + e3, Env.transfer ~from:env3 env + | Const(CInt64(n, _, _)) when Integer.is_one n -> + e2, Env.transfer ~from:env2 env + | _ -> + let ty = match t_opt with + | None (* predicate *) -> Cil.intType + | Some t -> Typing.get_typ t + in + let _, e, env = + Env.new_var + ~loc + ~name + env + t_opt + ty + (fun v ev -> + let lv = Cil.var v in + let ty = Cil.typeOf ev in + let init_set = + assert (not (Gmp_types.Q.is_t ty)); + Gmp.init_set + in + let affect e = init_set ~loc lv ev e in + let then_block, _ = + let s = affect e2 in + Env.pop_and_get env2 s ~global_clear:false Env.Middle + in + let else_block, _ = + let s = affect e3 in + Env.pop_and_get env3 s ~global_clear:false Env.Middle + in + [ Cil.mkStmt ~valid_sid:true (If(e1, then_block, else_block, loc)) ]) + in + e, env + +let rec thost_to_host kf env th = match th with + | TVar { lv_origin = Some v } -> + let v' = Visitor_behavior.Get.varinfo (Env.get_behavior env) v in + Var v', env, v.vname + | TVar ({ lv_origin = None } as logic_v) -> + let v' = Env.Logic_binding.get env logic_v in + Var v', env, logic_v.lv_name + | TResult _typ -> + let vis = Env.get_visitor env in + let kf = Extlib.the vis#current_kf in + let lhost = Misc.result_lhost kf in + (match lhost with + | Var v -> + let v' = Visitor_behavior.Get.varinfo (Env.get_behavior env) v in + Var v', env, "result" + | _ -> assert false) + | TMem t -> + let e, env = term_to_exp kf env t in + Mem e, env, "" + +and toffset_to_offset ?loc kf env = function + | TNoOffset -> NoOffset, env + | TField(f, offset) -> + let offset, env = toffset_to_offset ?loc kf env offset in + Field(f, offset), env + | TIndex(t, offset) -> + let e, env = term_to_exp kf env t in + let offset, env = toffset_to_offset kf env offset in + Index(e, offset), env + | TModel _ -> not_yet env "model" + +and tlval_to_lval kf env (host, offset) = + let host, env, name = thost_to_host kf env host in + let offset, env = toffset_to_offset kf env offset in + let name = match offset with NoOffset -> name | Field _ | Index _ -> "" in + (host, offset), env, name + +(* the returned boolean says that the expression is an mpz_string; + the returned string is the name of the generated variable corresponding to + the term. *) +and context_insensitive_term_to_exp kf env t = + let loc = t.term_loc in + match t.term_node with + | TConst c -> + let c, strnum = constant_to_exp ~loc t c in + c, env, strnum, "" + | TLval lv -> + let lv, env, name = tlval_to_lval kf env lv in + Cil.new_exp ~loc (Lval lv), env, C_number, name + | TSizeOf ty -> Cil.sizeOf ~loc ty, env, C_number, "sizeof" + | TSizeOfE t -> + let e, env = term_to_exp kf env t in + Cil.sizeOf ~loc (Cil.typeOf e), env, C_number, "sizeof" + | TSizeOfStr s -> + Cil.new_exp ~loc (SizeOfStr s), env, C_number, "sizeofstr" + | TAlignOf ty -> Cil.new_exp ~loc (AlignOf ty), env, C_number, "alignof" + | TAlignOfE t -> + let e, env = term_to_exp kf env t in + Cil.new_exp ~loc (AlignOfE e), env, C_number, "alignof" + | TUnOp(Neg | BNot as op, t') -> + let ty = Typing.get_typ t in + let e, env = term_to_exp kf env t' in + if Gmp_types.Z.is_t ty then + let name, vname = match op with + | Neg -> "__gmpz_neg", "neg" + | BNot -> "__gmpz_com", "bnot" + | LNot -> assert false + in + let _, e, env = + Env.new_var_and_mpz_init + ~loc + env + ~name:vname + (Some t) + (fun _ ev -> [ Misc.mk_call ~loc name [ ev; e ] ]) + in + e, env, C_number, "" + else if Gmp_types.Q.is_t ty then + not_yet env "reals: Neg | BNot" + else + Cil.new_exp ~loc (UnOp(op, e, ty)), env, C_number, "" + | TUnOp(LNot, t) -> + let ty = Typing.get_op t in + if Gmp_types.Z.is_t ty then + (* [!t] is converted into [t == 0] *) + let zero = Logic_const.tinteger 0 in + let ctx = Typing.get_number_ty t in + Typing.type_term ~use_gmp_opt:true ~ctx zero; + let e, env = + comparison_to_exp kf ~loc ~name:"not" env Typing.gmpz Eq t zero (Some t) + in + e, env, C_number, "" + else begin + assert (Cil.isIntegralType ty); + let e, env = term_to_exp kf env t in + Cil.new_exp ~loc (UnOp(LNot, e, Cil.intType)), env, C_number, "" + end + | TBinOp(PlusA | MinusA | Mult as bop, t1, t2) -> + let ty = Typing.get_typ t in + let e1, env = term_to_exp kf env t1 in + let e2, env = term_to_exp kf env t2 in + if Gmp_types.Z.is_t ty then + let name = name_of_mpz_arith_bop bop in + let mk_stmts _ e = [ Misc.mk_call ~loc name [ e; e1; e2 ] ] in + let name = Misc.name_of_binop bop in + let _, e, env = + Env.new_var_and_mpz_init ~loc ~name env (Some t) mk_stmts + in + e, env, C_number, "" + else if Gmp_types.Q.is_t ty then + let e, env = Rational.binop ~loc bop e1 e2 env (Some t) in + e, env, C_number, "" + else begin + assert (Logic_typing.is_integral_type t.term_type); + Cil.new_exp ~loc (BinOp(bop, e1, e2, ty)), env, C_number, "" + end + | TBinOp(Div | Mod as bop, t1, t2) -> + let ty = Typing.get_typ t in + let e1, env = term_to_exp kf env t1 in + let e2, env = term_to_exp kf env t2 in + if Gmp_types.Z.is_t ty then + (* TODO: preventing division by zero should not be required anymore. + RTE should do this automatically. *) + let ctx = Typing.get_number_ty t in + let t = Some t in + let name = name_of_mpz_arith_bop bop in + (* [TODO] can now do better since the type system got some info about + possible values of [t2] *) + (* guarding divisions and modulos *) + let zero = Logic_const.tinteger 0 in + Typing.type_term ~use_gmp_opt:true ~ctx zero; + (* do not generate [e2] from [t2] twice *) + let guard, env = + let name = Misc.name_of_binop bop ^ "_guard" in + comparison_to_exp + ~loc kf env Typing.gmpz ~e1:e2 ~name Eq t2 zero t + in + let mk_stmts _v e = + assert (Gmp_types.Z.is_t ty); + let vis = Env.get_visitor env in + let kf = Extlib.the vis#current_kf in + let cond = + Misc.mk_e_acsl_guard + (Env.annotation_kind env) + kf + guard + (Logic_const.prel ~loc (Req, t2, zero)) + in + Env.add_assert env cond (Logic_const.prel (Rneq, t2, zero)); + let instr = Misc.mk_call ~loc name [ e; e1; e2 ] in + [ cond; instr ] + in + let name = Misc.name_of_binop bop in + let _, e, env = Env.new_var_and_mpz_init ~loc ~name env t mk_stmts in + e, env, C_number, "" + else if Gmp_types.Q.is_t ty then + let e, env = Rational.binop ~loc bop e1 e2 env (Some t) in + e, env, C_number, "" + else begin + assert (Logic_typing.is_integral_type t.term_type); + (* no guard required since RTEs are generated separately *) + Cil.new_exp ~loc (BinOp(bop, e1, e2, ty)), env, C_number, "" + end + | TBinOp(Lt | Gt | Le | Ge | Eq | Ne as bop, t1, t2) -> + (* comparison operators *) + let ity = Typing.get_integer_op t in + let e, env = comparison_to_exp ~loc kf env ity bop t1 t2 (Some t) in + e, env, C_number, "" + | TBinOp((Shiftlt | Shiftrt), _, _) -> + (* left/right shift *) + not_yet env "left/right shift" + | TBinOp(LOr, t1, t2) -> + (* t1 || t2 <==> if t1 then true else t2 *) + let e1, env1 = term_to_exp kf (Env.rte env true) t1 in + let env' = Env.push env1 in + let res2 = term_to_exp kf (Env.push env') t2 in + let e, env = + conditional_to_exp ~name:"or" loc (Some t) e1 (Cil.one loc, env') res2 + in + e, env, C_number, "" + | TBinOp(LAnd, t1, t2) -> + (* t1 && t2 <==> if t1 then t2 else false *) + let e1, env1 = term_to_exp kf (Env.rte env true) t1 in + let _, env2 as res2 = term_to_exp kf (Env.push env1) t2 in + let env3 = Env.push env2 in + let e, env = + conditional_to_exp ~name:"and" loc (Some t) e1 res2 (Cil.zero loc, env3) + in + e, env, C_number, "" + | TBinOp((BOr | BXor | BAnd), _, _) -> + (* other logic/arith operators *) + not_yet env "missing binary bitwise operator" + | TBinOp(PlusPI | IndexPI | MinusPI as bop, t1, t2) -> + if Misc.is_set_of_ptr_or_array t1.term_type || + Misc.is_set_of_ptr_or_array t2.term_type then + (* case of arithmetic over set of pointers (due to use of ranges) + should have already been handled in [mmodel_call_with_ranges] *) + assert false; + (* binary operation over pointers *) + let ty = match t1.term_type with + | Ctype ty -> ty + | _ -> assert false + in + let e1, env = term_to_exp kf env t1 in + let e2, env = term_to_exp kf env t2 in + Cil.new_exp ~loc (BinOp(bop, e1, e2, ty)), env, C_number, "" + | TBinOp(MinusPP, t1, t2) -> + begin match Typing.get_number_ty t with + | Typing.C_integer _ -> + let e1, env = term_to_exp kf env t1 in + let e2, env = term_to_exp kf env t2 in + let ty = Typing.get_typ t in + Cil.new_exp ~loc (BinOp(MinusPP, e1, e2, ty)), env, C_number, "" + | Typing.Gmpz -> + not_yet env "pointer subtraction resulting in gmp" + | Typing.(C_float _ | Rational | Real | Nan) -> + assert false + end + | TCastE(ty, t') -> + let e, env = term_to_exp kf env t' in + let e, env = + add_cast ~loc ~name:"cast" env (Some ty) C_number (Some t) e + in + e, env, C_number, "" + | TLogic_coerce _ -> assert false (* handle in [term_to_exp] *) + | TAddrOf lv -> + let lv, env, _ = tlval_to_lval kf env lv in + Cil.mkAddrOf ~loc lv, env, C_number, "addrof" + | TStartOf lv -> + let lv, env, _ = tlval_to_lval kf env lv in + Cil.mkAddrOrStartOf ~loc lv, env, C_number, "startof" + | Tapp(li, [], targs) -> + let fname = li.l_var_info.lv_name in + (* build the varinfo (as an expression) which stores the result of the + function call. *) + let _, e, env = + if Builtins.mem li.l_var_info.lv_name then + (* E-ACSL built-in function call *) + let args, env = + try + List.fold_right + (fun targ (l, env) -> + let e, env = term_to_exp kf env targ in + e :: l, env) + targs + ([], env) + with Invalid_argument _ -> + Options.fatal + "[Tapp] unexpected number of arguments when calling %s" + fname + in + Env.new_var + ~loc + ~name:(fname ^ "_app") + env + (Some t) + (Misc.cty (Extlib.the li.l_type)) + (fun vi _ -> + [ Misc.mk_call ~loc ~result:(Cil.var vi) fname args ]) + else + (* build the arguments and compute the integer_ty of the parameters *) + let params_ty, args, env = + List.fold_right + (fun targ (params_ty, args, env) -> + let e, env = term_to_exp kf env targ in + let param_ty = Typing.get_number_ty targ in + let e, env = + try + let ty = Typing.typ_of_number_ty param_ty in + add_cast loc env (Some ty) C_number (Some targ) e + with Typing.Not_a_number -> + e, env + in + param_ty :: params_ty, e :: args, env) + targs + ([], [], env) + in + let gen_fname = + Varname.get ~scope:Varname.Global (Functions.RTL.mk_gen_name fname) + in + Logic_functions.tapp_to_exp ~loc gen_fname env t li params_ty args + in + e, env, C_number, "app" + | Tapp(_, _ :: _, _) -> + not_yet env "logic functions with labels" + | Tlambda _ -> not_yet env "functional" + | TDataCons _ -> not_yet env "constructor" + | Tif(t1, t2, t3) -> + let e1, env1 = term_to_exp kf (Env.rte env true) t1 in + let (_, env2 as res2) = term_to_exp kf (Env.push env1) t2 in + let res3 = term_to_exp kf (Env.push env2) t3 in + let e, env = conditional_to_exp loc (Some t) e1 res2 res3 in + e, env, C_number, "" + | Tat(t, BuiltinLabel Here) -> + let e, env = term_to_exp kf env t in + e, env, C_number, "" + | Tat(t', label) -> + let lscope = Env.Logic_scope.get env in + let pot = Misc.PoT_term t' in + if Lscope.is_used lscope pot then + let e, env = At_with_lscope.to_exp ~loc kf env pot label in + e, env, C_number, "" + else + let e, env = term_to_exp kf (Env.push env) t' in + let e, env, sty = at_to_exp_no_lscope env (Some t) label e in + e, env, sty, "" + | Tbase_addr(BuiltinLabel Here, t) -> + let name = "base_addr" in + let e, env = Mmodel_translate.call ~loc kf name Cil.voidPtrType env t in + e, env, C_number, name + | Tbase_addr _ -> not_yet env "labeled \\base_addr" + | Toffset(BuiltinLabel Here, t) -> + let size_t = Cil.theMachine.Cil.typeOfSizeOf in + let name = "offset" in + let e, env = Mmodel_translate.call ~loc kf name size_t env t in + e, env, C_number, name + | Toffset _ -> not_yet env "labeled \\offset" + | Tblock_length(BuiltinLabel Here, t) -> + let size_t = Cil.theMachine.Cil.typeOfSizeOf in + let name = "block_length" in + let e, env = Mmodel_translate.call ~loc kf name size_t env t in + e, env, C_number, name + | Tblock_length _ -> not_yet env "labeled \\block_length" + | Tnull -> + Cil.mkCast (Cil.zero ~loc) (TPtr(TVoid [], [])), env, C_number, "null" + | TUpdate _ -> not_yet env "functional update" + | Ttypeof _ -> not_yet env "typeof" + | Ttype _ -> not_yet env "C type" + | Tempty_set -> not_yet env "empty tset" + | Tunion _ -> not_yet env "union of tsets" + | Tinter _ -> not_yet env "intersection of tsets" + | Tcomprehension _ -> not_yet env "tset comprehension" + | Trange _ -> not_yet env "range" + | Tlet(li, t) -> + let lvs = Lscope.Lvs_let(li.l_var_info, Misc.term_of_li li) in + let env = Env.Logic_scope.extend env lvs in + let env = env_of_li li kf env loc in + let e, env = term_to_exp kf env t in + Interval.Env.remove li.l_var_info; + e, env, C_number, "" + +(* Convert an ACSL term into a corresponding C expression (if any) in the given + environment. Also extend this environment in order to include the generating + constructs. *) +and term_to_exp kf env t = + let generate_rte = Env.generate_rte env in + Options.feedback ~dkey ~level:4 "translating term %a (rte? %b)" + Printer.pp_term t generate_rte; + let env = Env.rte env false in + let t = match t.term_node with TLogic_coerce(_, t) -> t | _ -> t in + let e, env, sty, name = context_insensitive_term_to_exp kf env t in + let env = if generate_rte then translate_rte kf env e else env in + let cast = Typing.get_cast t in + let name = if name = "" then None else Some name in + add_cast + ~loc:t.term_loc + ?name + env + cast + sty + (Some t) + e + +(* generate the C code equivalent to [t1 bop t2]. *) +and comparison_to_exp + ~loc ?e1 kf env ity bop ?(name = Misc.name_of_binop bop) t1 t2 t_opt = + let e1, env = match e1 with + | None -> + let e1, env = term_to_exp kf env t1 in + e1, env + | Some e1 -> + e1, env + in + let e2, env = term_to_exp kf env t2 in + match ity with + | Typing.C_integer _ | Typing.C_float _ | Typing.Nan -> + Cil.mkBinOp ~loc bop e1 e2, env + | Typing.Gmpz -> + let _, e, env = Env.new_var + ~loc + env + t_opt + ~name + Cil.intType + (fun v _ -> + [ Misc.mk_call ~loc ~result:(Cil.var v) "__gmpz_cmp" [ e1; e2 ] ]) + in + Cil.new_exp ~loc (BinOp(bop, e, Cil.zero ~loc, Cil.intType)), env + | Typing.Rational -> + Rational.cmp ~loc bop e1 e2 env t_opt + | Typing.Real -> + Error.not_yet "comparison involving real numbers" + +and at_to_exp_no_lscope env t_opt label e = + let stmt = E_acsl_label.get_stmt (Env.get_visitor env) label in + (* generate a new variable denoting [\at(t',label)]. + That is this variable which is the resulting expression. + ACSL typing rule ensures that the type of this variable is the same as + the one of [e]. *) + let loc = Stmt.loc stmt in + let res_v, res, new_env = + Env.new_var + ~loc + ~name:"at" + ~scope:Varname.Function + env + t_opt + (Cil.typeOf e) + (fun _ _ -> []) + in + let env_ref = ref new_env in + (* visitor modifying in place the labeled statement in order to store [e] + in the resulting variable at this location (which is the only correct + one). *) + let o = object + inherit Visitor.frama_c_inplace + method !vstmt_aux stmt = + (* either a standard C affectation or a call to an initializer according + to the type of [e] *) + let ty = Cil.typeOf e in + let init_set = + if Gmp_types.Q.is_t ty then Rational.init_set else Gmp.init_set + in + let new_stmt = init_set ~loc (Cil.var res_v) res e in + assert (!env_ref == new_env); + (* generate the new block of code for the labeled statement and the + corresponding environment *) + let block, new_env = + Env.pop_and_get new_env new_stmt ~global_clear:false Env.Middle + in + env_ref := Env.extend_stmt_in_place new_env stmt ~label block; + Cil.ChangeTo stmt + end + in + let bhv = Env.get_behavior new_env in + let new_stmt = + Visitor.visitFramacStmt o (Visitor_behavior.Get.stmt bhv stmt) + in + Visitor_behavior.Set.stmt bhv stmt new_stmt; + res, !env_ref, C_number + +and env_of_li li kf env loc = + let t = Misc.term_of_li li in + let ty = Typing.get_typ t in + let vi, vi_e, env = Env.Logic_binding.add ~ty env li.l_var_info in + let e, env = term_to_exp kf env t in + let stmt = match Typing.get_number_ty t with + | Typing.(C_integer _ | C_float _ | Nan) -> + Cil.mkStmtOneInstr (Set (Cil.var vi, e, loc)) + | Typing.Gmpz -> + Gmp.init_set ~loc (Cil.var vi) vi_e e + | Typing.Rational -> + Rational.init_set ~loc (Cil.var vi) vi_e e + | Typing.Real -> + Error.not_yet "real number" + in + Env.add_stmt env stmt + +(* Convert an ACSL named predicate into a corresponding C expression (if + any) in the given environment. Also extend this environment which includes + the generating constructs. *) +and named_predicate_content_to_exp ?name kf env p = + let loc = p.pred_loc in + match p.pred_content with + | Pfalse -> Cil.zero ~loc, env + | Ptrue -> Cil.one ~loc, env + | Papp(li, labels, args) -> + (* Simply use the implementation of Tapp(li, labels, args). + To achieve this, we create a clone of [li] for which the type is + transformed from [None] (type of predicates) to + [Some int] (type as a term). *) + let prj = Project.current () in + let o = object inherit Visitor.frama_c_copy prj end in + let li = Visitor.visitFramacLogicInfo o li in + let lty = Ctype Cil.intType in + li.l_type <- Some lty; + let tapp = Logic_const.term ~loc (Tapp(li, labels, args)) lty in + Typing.type_term ~use_gmp_opt:false ~ctx:Typing.c_int tapp; + let e, env = term_to_exp kf env tapp in + e, env + | Pseparated _ -> not_yet env "\\separated" + | Pdangling _ -> not_yet env "\\dangling" + | Pvalid_function _ -> not_yet env "\\valid_function" + | Prel(rel, t1, t2) -> + let ity = Typing.get_integer_op_of_predicate p in + comparison_to_exp ~loc kf env ity (relation_to_binop rel) t1 t2 None + | Pand(p1, p2) -> + (* p1 && p2 <==> if p1 then p2 else false *) + let e1, env1 = named_predicate_to_exp kf (Env.rte env true) p1 in + let _, env2 as res2 = + named_predicate_to_exp kf (Env.push env1) p2 in + let env3 = Env.push env2 in + let name = match name with None -> "and" | Some n -> n in + conditional_to_exp ~name loc None e1 res2 (Cil.zero loc, env3) + | Por(p1, p2) -> + (* p1 || p2 <==> if p1 then true else p2 *) + let e1, env1 = named_predicate_to_exp kf (Env.rte env true) p1 in + let env' = Env.push env1 in + let res2 = named_predicate_to_exp kf (Env.push env') p2 in + let name = match name with None -> "or" | Some n -> n in + conditional_to_exp ~name loc None e1 (Cil.one loc, env') res2 + | Pxor _ -> not_yet env "xor" + | Pimplies(p1, p2) -> + (* (p1 ==> p2) <==> !p1 || p2 *) + named_predicate_to_exp + ~name:"implies" + kf + env + (Logic_const.por ~loc ((Logic_const.pnot ~loc p1), p2)) + | Piff(p1, p2) -> + (* (p1 <==> p2) <==> (p1 ==> p2 && p2 ==> p1) *) + named_predicate_to_exp + ~name:"equiv" + kf + env + (Logic_const.pand ~loc + (Logic_const.pimplies ~loc (p1, p2), + Logic_const.pimplies ~loc (p2, p1))) + | Pnot p -> + let e, env = named_predicate_to_exp kf env p in + Cil.new_exp ~loc (UnOp(LNot, e, Cil.intType)), env + | Pif(t, p2, p3) -> + let e1, env1 = term_to_exp kf (Env.rte env true) t in + let (_, env2 as res2) = + named_predicate_to_exp kf (Env.push env1) p2 in + let res3 = named_predicate_to_exp kf (Env.push env2) p3 in + conditional_to_exp loc None e1 res2 res3 + | Plet(li, p) -> + let lvs = Lscope.Lvs_let(li.l_var_info, Misc.term_of_li li) in + let env = Env.Logic_scope.extend env lvs in + let env = env_of_li li kf env loc in + let e, env = named_predicate_to_exp kf env p in + Interval.Env.remove li.l_var_info; + e, env + | Pforall _ | Pexists _ -> Quantif.quantif_to_exp kf env p + | Pat(p, BuiltinLabel Here) -> + named_predicate_to_exp kf env p + | Pat(p', label) -> + let lscope = Env.Logic_scope.get env in + let pot = Misc.PoT_pred p' in + if Lscope.is_used lscope pot then + At_with_lscope.to_exp ~loc kf env pot label + else begin + (* convert [t'] to [e] in a separated local env *) + let e, env = named_predicate_to_exp kf (Env.push env) p' in + let e, env, sty = at_to_exp_no_lscope env None label e in + assert (sty = C_number); + e, env + end + | Pvalid_read(BuiltinLabel Here as llabel, t) as pc + | (Pvalid(BuiltinLabel Here as llabel, t) as pc) -> + let call_valid t = + let name = match pc with + | Pvalid _ -> "valid" + | Pvalid_read _ -> "valid_read" + | _ -> assert false + in + Mmodel_translate.call_valid ~loc kf name Cil.intType env t + in + if !is_visiting_valid then begin + (* we already transformed \valid(t) into \initialized(&t) && \valid(t): + now convert this right-most valid. *) + is_visiting_valid := false; + call_valid t p + end else begin + match t.term_node, t.term_type with + | TLval tlv, Ctype ty -> + let init = + Logic_const.pinitialized ~loc (llabel, Misc.term_addr_of ~loc tlv ty) + in + Typing.type_named_predicate ~must_clear:false init; + let p = Logic_const.pand ~loc (init, p) in + is_visiting_valid := true; + named_predicate_to_exp kf env p + | _ -> + call_valid t p + end + | Pvalid _ -> not_yet env "labeled \\valid" + | Pvalid_read _ -> not_yet env "labeled \\valid_read" + | Pinitialized(BuiltinLabel Here, t) -> + (match t.term_node with + (* optimisation when we know that the initialisation is ok *) + | TAddrOf (TResult _, TNoOffset) -> Cil.one ~loc, env + | TAddrOf (TVar { lv_origin = Some vi }, TNoOffset) + when + vi.vformal || vi.vglob || Functions.RTL.is_generated_name vi.vname -> + Cil.one ~loc, env + | _ -> + Mmodel_translate.call_with_size + ~loc + kf + "initialized" + Cil.intType + env + t + p) + | Pinitialized _ -> not_yet env "labeled \\initialized" + | Pallocable _ -> not_yet env "\\allocate" + | Pfreeable(BuiltinLabel Here, t) -> + Mmodel_translate.call ~loc kf "freeable" Cil.intType env t + | Pfreeable _ -> not_yet env "labeled \\freeable" + | Pfresh _ -> not_yet env "\\fresh" + +and named_predicate_to_exp ?name kf ?rte env p = + let rte = match rte with None -> Env.generate_rte env | Some b -> b in + let env = Env.rte env false in + let e, env = named_predicate_content_to_exp ?name kf env p in + let env = if rte then translate_rte kf env e else env in + let cast = Typing.get_cast_of_predicate p in + add_cast + ~loc:p.pred_loc + ?name + env + cast + C_number + None + e + +and translate_rte_annots: + 'a. (Format.formatter -> 'a -> unit) -> 'a -> + kernel_function -> Env.t -> code_annotation list -> Env.t = + fun pp elt kf env l -> + let old_valid = !is_visiting_valid in + let old_kind = Env.annotation_kind env in + let env = Env.set_annotation_kind env Misc.RTE in + let env = + List.fold_left + (fun env a -> match a.annot_content with + | AAssert(_, _, p) -> + handle_error + (fun env -> + Options.feedback ~dkey ~level:4 "prevent RTE from %a" pp elt; + (* The logic scope MUST NOT be reset here since we still might + be in the middle of the translation of the original + predicate. *) + let lscope_reset_old = Env.Logic_scope.get_reset env in + let env = Env.Logic_scope.set_reset env false in + let env = translate_named_predicate kf (Env.rte env false) p in + let env = Env.Logic_scope.set_reset env lscope_reset_old in + env) + env + | _ -> assert false) + env + l + in + is_visiting_valid := old_valid; + Env.set_annotation_kind env old_kind + +and translate_rte kf env e = + let stmt = Cil.mkStmtOneInstr ~valid_sid:true (Skip e.eloc) in + let l = Rte.exp kf stmt e in + translate_rte_annots Printer.pp_exp e kf env l + +and translate_named_predicate kf env p = + Options.feedback ~dkey ~level:3 "translating predicate %a" + Printer.pp_predicate p; + let rte = Env.generate_rte env in + Typing.type_named_predicate ~must_clear:rte p; + let e, env = named_predicate_to_exp kf ~rte env p in + assert (Typ.equal (Cil.typeOf e) Cil.intType); + let env = Env.Logic_scope.reset env in + Env.add_stmt + env + (Misc.mk_e_acsl_guard ~reverse:true (Env.annotation_kind env) kf e p) + +let named_predicate_to_exp ?name kf env p = + named_predicate_to_exp ?name kf env p (* forget optional argument ?rte *) + +let () = + Loops.term_to_exp_ref := term_to_exp; + Loops.translate_named_predicate_ref := translate_named_predicate; + Loops.named_predicate_ref := named_predicate_to_exp; + Quantif.predicate_to_exp_ref := named_predicate_to_exp; + At_with_lscope.term_to_exp_ref := term_to_exp; + At_with_lscope.predicate_to_exp_ref := named_predicate_to_exp; + Mmodel_translate.term_to_exp_ref := term_to_exp; + Mmodel_translate.predicate_to_exp_ref := named_predicate_to_exp; + Logic_functions.term_to_exp_ref := term_to_exp; + Logic_functions.named_predicate_to_exp_ref := named_predicate_to_exp + +(* This function is used by Guillaume. + However, it is correct to use it only in specific contexts. *) +let predicate_to_exp kf p = + Typing.type_named_predicate ~must_clear:true p; + let empty_env = Env.empty (new Visitor.frama_c_copy Project_skeleton.dummy) in + let e, _ = named_predicate_to_exp kf empty_env p in + assert (Typ.equal (Cil.typeOf e) Cil.intType); + e + +exception No_simple_translation of term + +(* This function is used by plug-in [Cfp]. *) +let term_to_exp typ t = + (* infer a context from the given [typ] whenever possible *) + let ctx_of_typ ty = + if Gmp_types.Z.is_t ty then Typing.gmpz + else if Gmp_types.Q.is_t ty then Typing.rational + else + match ty with + | TInt(ik, _) -> Typing.ikind ik + | TFloat(fk, _) -> Typing.fkind fk + | _ -> Typing.nan + in + let ctx = Extlib.opt_map ctx_of_typ typ in + Typing.type_term ~use_gmp_opt:true ?ctx t; + let env = Env.empty (new Visitor.frama_c_copy Project_skeleton.dummy) in + let env = Env.push env in + let env = Env.rte env false in + let e, env = + try term_to_exp (Kernel_function.dummy ()) env t + with Misc.Unregistered_library_function _ -> raise (No_simple_translation t) + in + if not (Env.has_no_new_stmt env) then raise (No_simple_translation t); + e + +(* ************************************************************************** *) +(* [translate_*] translates a given ACSL annotation into the corresponding C + statement (if any) for runtime assertion checking. + + IMPORTANT: the order of translation of pre-/post-spec must be consistent with + the pushes done in [Keep_status] *) +(* ************************************************************************** *) + +let assumes_predicate bhv = + List.fold_left + (fun acc p -> + let loc = p.ip_content.pred_loc in + Logic_const.pand ~loc (acc, + Logic_const.unamed ~loc p.ip_content.pred_content)) + Logic_const.ptrue + bhv.b_assumes + +let translate_preconditions kf env behaviors = + let env = Env.set_annotation_kind env Misc.Precondition in + let do_behavior env b = + let assumes_pred = assumes_predicate b in + List.fold_left + (fun env p -> + let do_it env = + if Keep_status.must_translate kf Keep_status.K_Requires then + let loc = p.ip_content.pred_loc in + let p = + Logic_const.pimplies + ~loc + (assumes_pred, + Logic_const.unamed ~loc p.ip_content.pred_content) + in + translate_named_predicate kf env p + else + env + in + handle_error do_it env) + env + b.b_requires + in + List.fold_left do_behavior env behaviors + +let translate_postconditions kf env behaviors = + let env = Env.set_annotation_kind env Misc.Postcondition in + (* generate one guard by postcondition of each behavior *) + let do_behavior env b = + let env = + handle_error + (fun env -> + (* test ordering does matter for keeping statuses consistent *) + if b.b_assigns <> WritesAny + && Keep_status.must_translate kf Keep_status.K_Assigns + then not_yet env "assigns clause in behavior"; + (* ignore b.b_extended since we never translate them *) + env) + env + in + let assumes_pred = assumes_predicate b in + List.fold_left + (fun env (t, p) -> + if Keep_status.must_translate kf Keep_status.K_Ensures then + let do_it env = + match t with + | Normal -> + let loc = p.ip_content.pred_loc in + let p = p.ip_content in + let p = + Logic_const.pimplies + ~loc + (Logic_const.pold ~loc assumes_pred, + Logic_const.unamed ~loc p.pred_content) + in + translate_named_predicate kf env p + | Exits | Breaks | Continues | Returns -> + not_yet env "abnormal termination case in behavior" + in + handle_error do_it env + else env) + env + b.b_post_cond + in + (* fix ordering of behaviors' iterations *) + let bhvs = + List.sort (fun b1 b2 -> String.compare b1.b_name b2.b_name) behaviors + in + List.fold_left do_behavior env bhvs + +let translate_pre_spec kf env spec = + let unsupported f x = ignore (handle_error (fun env -> f x; env) env) in + let convert_unsupported_clauses env = + unsupported + (Extlib.may + (fun _ -> + if Keep_status.must_translate kf Keep_status.K_Decreases then + not_yet env "variant clause")) + spec.spec_variant; + (* TODO: spec.spec_terminates is not part of the E-ACSL subset *) + unsupported + (Extlib.may + (fun _ -> + if Keep_status.must_translate kf Keep_status.K_Terminates then + not_yet env "terminates clause")) + spec.spec_terminates; + (match spec.spec_complete_behaviors with + | [] -> () + | l -> + unsupported + (List.iter + (fun _ -> + if Keep_status.must_translate kf Keep_status.K_Complete then + not_yet env "complete behaviors")) + l); + (match spec.spec_disjoint_behaviors with + | [] -> () + | l -> + unsupported + (List.iter + (fun _ -> + if Keep_status.must_translate kf Keep_status.K_Disjoint then + not_yet env "disjoint behaviors")) + l); + env + in + let env = convert_unsupported_clauses env in + handle_error + (fun env -> translate_preconditions kf env spec.spec_behavior) + env + +let translate_post_spec kf env spec = + handle_error + (fun env -> translate_postconditions kf env spec.spec_behavior) + env + +let translate_pre_code_annotation kf env annot = + let convert env = match annot.annot_content with + | AAssert(l, _, p) -> + if Keep_status.must_translate kf Keep_status.K_Assert then + let env = Env.set_annotation_kind env Misc.Assertion in + if l <> [] then + not_yet env "@[assertion applied only on some behaviors@]"; + translate_named_predicate kf env p + else + env + | AStmtSpec(l, spec) -> + if l <> [] then + not_yet env "@[statement contract applied only on some behaviors@]"; + translate_pre_spec kf env spec ; + | AInvariant(l, loop_invariant, p) -> + if Keep_status.must_translate kf Keep_status.K_Invariant then + let env = Env.set_annotation_kind env Misc.Invariant in + if l <> [] then + not_yet env "@[invariant applied only on some behaviors@]"; + let env = translate_named_predicate kf env p in + if loop_invariant then Env.add_loop_invariant env p else env + else + env + | AVariant _ -> + if Keep_status.must_translate kf Keep_status.K_Variant + then not_yet env "variant" + else env + | AAssigns _ -> + (* TODO: it is not a precondition *) + if Keep_status.must_translate kf Keep_status.K_Assigns + then not_yet env "assigns" + else env + | AAllocation _ -> + if Keep_status.must_translate kf Keep_status.K_Allocation + then not_yet env "allocation" + else env + | APragma _ -> not_yet env "pragma" + | AExtended _ -> env (* never translate extensions. *) + in + handle_error convert env + +let translate_post_code_annotation kf env annot = + let convert env = match annot.annot_content with + | AStmtSpec(_, spec) -> translate_post_spec kf env spec + | AAssert _ + | AInvariant _ + | AVariant _ + | AAssigns _ + | AAllocation _ + | APragma _ + | AExtended _ -> env + in + handle_error convert env + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff --git a/src/plugins/e-acsl/src/code_generator/translate.mli b/src/plugins/e-acsl/src/code_generator/translate.mli new file mode 100644 index 0000000000000000000000000000000000000000..a951a992f8a418b023a75d83a2568bfd96fbc3d7 --- /dev/null +++ b/src/plugins/e-acsl/src/code_generator/translate.mli @@ -0,0 +1,55 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C's E-ACSL plug-in. *) +(* *) +(* Copyright (C) 2012-2018 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +open Cil_types + +(** [translate_*] translates a given ACSL annotation into the corresponding C + statement (if any) for runtime assertion checking. This C statements are + part of the resulting environment. *) + +val translate_pre_spec: kernel_function -> Env.t -> funspec -> Env.t +val translate_post_spec: kernel_function -> Env.t -> funspec -> Env.t +val translate_pre_code_annotation: + kernel_function -> Env.t -> code_annotation -> Env.t +val translate_post_code_annotation: + kernel_function -> Env.t -> code_annotation -> Env.t +val translate_named_predicate: + kernel_function -> Env.t -> predicate -> Env.t + +val translate_rte_annots: + (Format.formatter -> 'a -> unit) -> + 'a -> + kernel_function -> + Env.t -> + code_annotation list -> + Env.t + +exception No_simple_translation of term +val term_to_exp: typ option -> term -> exp + +val predicate_to_exp: kernel_function -> predicate -> exp + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff --git a/src/plugins/e-acsl/src/code_generator/visit.ml b/src/plugins/e-acsl/src/code_generator/visit.ml new file mode 100644 index 0000000000000000000000000000000000000000..7737606971dfbd5075528d14a3171e3c75f011e2 --- /dev/null +++ b/src/plugins/e-acsl/src/code_generator/visit.ml @@ -0,0 +1,1059 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C's E-ACSL plug-in. *) +(* *) +(* Copyright (C) 2012-2018 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +module Libc = Functions.Libc +module RTL = Functions.RTL +module E_acsl_label = Label +open Cil_types +open Cil_datatype + +let dkey = Options.dkey_translation + +(* ************************************************************************** *) +(* Visitor *) +(* ************************************************************************** *) + +(* local references to the below visitor and to [do_visit] *) +let function_env = ref Env.dummy +let dft_funspec = Cil.empty_funspec () +let funspec = ref dft_funspec + +(* extend the environment with statements which allocate/deallocate memory + blocks *) +module Memory: sig + val store: ?before:stmt -> Env.t -> kernel_function -> varinfo list -> Env.t + val duplicate_store: + ?before:stmt -> Env.t -> kernel_function -> Varinfo.Set.t -> Env.t + val delete_from_list: + ?before:stmt -> Env.t -> kernel_function -> varinfo list -> Env.t + val delete_from_set: + ?before:stmt -> Env.t -> kernel_function -> Varinfo.Set.t -> Env.t +end = struct + + let tracking_stmt ?before fold mk_stmt env kf vars = + if Functions.instrument kf then + fold + (fun vi env -> + if Mmodel_analysis.must_model_vi ~kf vi then + let vi = Visitor_behavior.Get.varinfo (Env.get_behavior env) vi in + Env.add_stmt ?before env (mk_stmt vi) + else + env) + vars + env + else + env + + let store ?before env kf vars = + tracking_stmt + ?before + List.fold_right (* small list *) + Misc.mk_store_stmt + env + kf + vars + + let duplicate_store ?before env kf vars = + tracking_stmt + ?before + Varinfo.Set.fold + Misc.mk_duplicate_store_stmt + env + kf + vars + + let delete_from_list ?before env kf vars = + tracking_stmt + ?before + List.fold_right (* small list *) + Misc.mk_delete_stmt + env + kf + vars + + let delete_from_set ?before env kf vars = + tracking_stmt + ?before + Varinfo.Set.fold + Misc.mk_delete_stmt + env + kf + vars + +end + +(* Observation of literal strings in C expressions *) +module Literal_observer: sig + + val exp: Env.t -> exp -> exp * Env.t + (* replace the given exp by an observed variable if it is a literal string *) + + val exp_in_depth: Env.t -> exp -> exp * Env.t + (* replace any sub-expression of the given exp that is a literal string by an + observed variable *) + +end = +struct + + let literal loc env s = + try + let vi = Literal_strings.find s in + (* if the literal string was already created, just get it. *) + Cil.evar ~loc vi, env + with Not_found -> + (* never seen this string before: replace it by a new global var *) + let vi, exp, env = + Env.new_var + ~loc + ~scope:Varname.Global + ~name:"literal_string" + env + None + Cil.charPtrType + (fun _ _ -> [] (* done in the initializer, see {!vglob_aux} *)) + in + Literal_strings.add s vi; + exp, env + + let exp env e = match e.enode with + (* the guard below could be optimized: if no annotation **depends on this + string**, then it is not required to monitor it. + (currently, the guard says: "no annotation uses the memory model" *) + | Const (CStr s) when Mmodel_analysis.use_model () -> literal e.eloc env s + | _ -> e, env + + let exp_in_depth env e = + let env_ref = ref env in + let o = object + inherit Cil.genericCilVisitor (Visitor_behavior.copy (Project.current ())) + method !vexpr e = match e.enode with + (* the guard below could be optimized: if no annotation **depends on this + string**, then it is not required to monitor it. + (currently, the guard says: "no annotation uses the memory model" *) + | Const (CStr s) when Mmodel_analysis.use_model () -> + let e, env = literal e.eloc !env_ref s in + env_ref := env; + Cil.ChangeTo e + | _ -> + Cil.DoChildren + end in + let e = Cil.visitCilExpr o e in + e, !env_ref + +end + +(* Observation of global variables. *) +module Global_observer: sig + val function_name: string (* name of the function in which [mk_init] generates + the code *) + val reset: unit -> unit + val is_empty: unit -> bool + + val add: varinfo -> unit (* observes the given variable if necessary *) + val add_initializer: varinfo -> offset -> init -> unit + (* add the initializer for the given observed variable *) + + val mk_init: Visitor_behavior.t -> Env.t -> varinfo * fundec * Env.t + (* generates a new C function containing the observers for global variable + declaration and initialization *) + + val mk_delete: Visitor_behavior.t -> stmt list -> stmt list + (* generates the observers for global variable de-allocation *) + +end = struct + + let function_name = RTL.mk_api_name "globals_init" + + (* Hashtable mapping global variables (as Cil_type.varinfo) to their + initializers (if any). + + NOTE: here, varinfos as keys belong to the original project while values + belong to the new one *) + let tbl + : (offset (* compound initializers *) * init) list ref Varinfo.Hashtbl.t + = Varinfo.Hashtbl.create 7 + + let reset () = Varinfo.Hashtbl.reset tbl + + let is_empty () = Varinfo.Hashtbl.length tbl = 0 + + let add vi = + if Mmodel_analysis.must_model_vi vi then + Varinfo.Hashtbl.replace tbl vi (ref []) + + let add_initializer vi offset init = + if Mmodel_analysis.must_model_vi vi then + try + let l = Varinfo.Hashtbl.find tbl vi in + l := (offset, init) :: !l + with Not_found -> + assert false + + let rec literal_in_initializer env = function + | SingleInit exp -> snd (Literal_observer.exp_in_depth env exp) + | CompoundInit (_, l) -> + List.fold_left (fun env (_, i) -> literal_in_initializer env i) env l + + let mk_init bhv env = + (* Create [__e_acsl_globals_init] function with definition + for initialization of global variables *) + let vi = + Cil.makeGlobalVar ~source:true + function_name + (TFun(Cil.voidType, Some [], false, [])) + in + vi.vdefined <- true; + (* There is no contract associated with the function *) + let spec = Cil.empty_funspec () in + (* Create function definition which no stmt yet: they will be added + afterwards *) + let blk = Cil.mkBlock [] in + let fundec = + { svar = vi; + sformals = []; + slocals = []; + smaxid = 0; + sbody = blk; + smaxstmtid = None; + sallstmts = []; + sspec = spec } + in + let fct = Definition(fundec, Location.unknown) in + (* Create and register [__e_acsl_globals_init] as kernel + function *) + let kf = + { fundec = fct; spec = spec } + in + Globals.Functions.register kf; + Globals.Functions.replace_by_definition spec fundec Location.unknown; + (* Now generate the statements. The generation is done only now because it + depends on the local variable [already_run] whose generation required the + existence of [fundec] *) + let env = Env.push env in + (* 2-stage observation of initializers: temporal analysis must be performed + after generating observers of **all** globals *) + let env, stmts = + Varinfo.Hashtbl.fold_sorted + (fun old_vi l stmts -> + let new_vi = Visitor_behavior.Get.varinfo bhv old_vi in + List.fold_left + (fun (env, stmts) (off, init) -> + let env = literal_in_initializer env init in + let stmt = Temporal.generate_global_init new_vi off init env in + env, match stmt with None -> stmts | Some stmt -> stmt :: stmts) + stmts + !l) + tbl + (env, []) + in + (* allocation and initialization of globals *) + let stmts = + Varinfo.Hashtbl.fold_sorted + (fun old_vi _ stmts -> + let new_vi = Visitor_behavior.Get.varinfo bhv old_vi in + (* a global is both allocated and initialized *) + Misc.mk_store_stmt new_vi + :: Misc.mk_initialize ~loc:Location.unknown (Cil.var new_vi) + :: stmts) + tbl + stmts + in + (* literal strings allocations and initializations *) + let stmts = + Literal_strings.fold + (fun s vi stmts -> + let loc = Location.unknown in + let e = Cil.new_exp ~loc:loc (Const (CStr s)) in + let str_size = Cil.new_exp loc (SizeOfStr s) in + Cil.mkStmtOneInstr ~valid_sid:true (Set(Cil.var vi, e, loc)) + :: Misc.mk_store_stmt ~str_size vi + :: Misc.mk_full_init_stmt ~addr:false vi + :: Misc.mk_mark_readonly vi + :: stmts) + stmts + in + (* Create a new code block with generated statements *) + let (b, env), stmts = match stmts with + | [] -> assert false + | stmt :: stmts -> + Env.pop_and_get env stmt ~global_clear:true Env.Before, stmts + in + let stmts = Cil.mkStmt ~valid_sid:true (Block b) :: stmts in + (* Prevent multiple calls to globals_init *) + let loc = Location.unknown in + let vi_already_run = + Cil.makeLocalVar fundec (RTL.mk_api_name "already_run") (TInt(IChar, [])) + in + vi_already_run.vdefined <- true; + vi_already_run.vreferenced <- true; + vi_already_run.vstorage <- Static; + let init = AssignInit (SingleInit (Cil.zero ~loc)) in + let init_stmt = + Cil.mkStmtOneInstr ~valid_sid:true + (Local_init (vi_already_run, init, loc)) + in + let already_run = + Cil.mkStmtOneInstr ~valid_sid:true + (Set (Cil.var vi_already_run, Cil.one ~loc, loc)) + in + let stmts = already_run :: stmts in + let guard = + Cil.mkStmt + ~valid_sid:true + (If (Cil.evar vi_already_run, Cil.mkBlock [], Cil.mkBlock stmts, loc)) + in + let return = Cil.mkStmt ~valid_sid:true (Return (None, loc)) in + let stmts = [ init_stmt; guard; return ] in + blk.bstmts <- stmts; + vi, fundec, env + + let mk_delete bhv stmts = + Varinfo.Hashtbl.fold_sorted + (fun old_vi _l acc -> + let new_vi = Visitor_behavior.Get.varinfo bhv old_vi in + Misc.mk_delete_stmt new_vi :: acc) + tbl + stmts + +end + +(* the main visitor performing e-acsl checking and C code generator *) +class e_acsl_visitor prj generate = object (self) + + inherit Visitor.generic_frama_c_visitor + (if generate then Visitor_behavior.copy prj else Visitor_behavior.inplace ()) + + val mutable main_fct = None + (* fundec of the main entry point, in the new project [prj]. + [None] while the global corresponding to this fundec has not been + visited *) + + val mutable is_initializer = false + (* Global flag set to [true] if a currently visited node + belongs to a global initializer and set to [false] otherwise *) + + method private reset_env () = + function_env := Env.empty (self :> Visitor.frama_c_visitor) + + method !vfile _f = + (* copy the options used during the visit in the new project: it is the + right place to do this: it is still before visiting, but after + that the visitor internals reset all of them :-(. *) + let cur = Project.current () in + let selection = + State_selection.of_list + [ Options.Gmp_only.self; Options.Check.self; Options.Full_mmodel.self; + Kernel.SignedOverflow.self; Kernel.UnsignedOverflow.self; + Kernel.SignedDowncast.self; Kernel.UnsignedDowncast.self; + Kernel.Machdep.self ] + in + if generate then Project.copy ~selection ~src:cur prj; + Cil.DoChildrenPost + (fun f -> + (* extend [main] with forward initialization and put it at end *) + if generate then begin + if not (Global_observer.is_empty () && Literal_strings.is_empty ()) + then begin + let build_initializer () = + Options.feedback ~dkey ~level:2 "building global initializer."; + let vi, fundec, env = + Global_observer.mk_init self#behavior !function_env + in + function_env := env; + let cil_fct = GFun(fundec, Location.unknown) in + if Mmodel_analysis.use_model () then + match main_fct with + | Some main -> + let exp = Cil.evar ~loc:Location.unknown vi in + (* Create [__e_acsl_globals_init();] call *) + let stmt = + Cil.mkStmtOneInstr ~valid_sid:true + (Call(None, exp, [], Location.unknown)) + in + vi.vreferenced <- true; + (* insert [__e_acsl_globals_init ();] as first statement of + [main] *) + main.sbody.bstmts <- stmt :: main.sbody.bstmts; + let new_globals = + List.fold_right + (fun g acc -> match g with + | GFun({ svar = vi }, _) + when Varinfo.equal vi main.svar -> + acc + | _ -> g :: acc) + f.globals + [ cil_fct; GFun(main, Location.unknown) ] + in + (* add the literal string varinfos as the very first + globals *) + let new_globals = + Literal_strings.fold + (fun _ vi l -> + GVar(vi, { init = None }, Location.unknown) :: l) + new_globals + in + f.globals <- new_globals + | None -> + Kernel.warning "@[no entry point specified:@ \ +you must call function `%s' and `__e_acsl_memory_clean by yourself.@]" + Global_observer.function_name; + f.globals <- f.globals @ [ cil_fct ] + in + Project.on prj build_initializer () + end; (* must_init *) + (* Add a call to [__e_acsl_memory_init] that initializes memory + storage and potentially records program arguments. Parameters to + [__e_acsl_memory_init] are addresses of program arguments or + NULLs if [main] is declared without arguments. *) + let build_mmodel_initializer () = + let loc = Location.unknown in + let nulls = [ Cil.zero loc ; Cil.zero loc ] in + let handle_main main = + let args = + (* record arguments only if the second has a pointer type, so a + argument strings can be recorded. This is sufficient to + capture C99 compliant arguments and GCC extensions with + environ. *) + match main.sformals with + | [] -> + (* no arguments to main given *) + nulls + | _argc :: argv :: _ when Cil.isPointerType argv.vtype -> + (* grab addresses of arguments for a call to the main + initialization function, i.e., [__e_acsl_memory_init] *) + List.map Cil.mkAddrOfVi main.sformals; + | _ :: _ -> + (* some non-standard arguments. *) + nulls + in + let ptr_size = Cil.sizeOf loc Cil.voidPtrType in + let args = args @ [ ptr_size ] in + let name = RTL.mk_api_name "memory_init" in + let init = Misc.mk_call loc name args in + main.sbody.bstmts <- init :: main.sbody.bstmts + in + Extlib.may handle_main main_fct + in + Project.on + prj + (fun () -> + f.globals <- Logic_functions.add_generated_functions f.globals; + build_mmodel_initializer ()) + (); + (* reset copied states at the end to be observationally + equivalent to a standard visitor. *) + Project.clear ~selection ~project:prj (); + end; (* generate *) + f) + + method !vglob_aux = function + | GVarDecl(vi, _) | GVar(vi, _, _) + | GFunDecl(_, vi, _) | GFun({ svar = vi }, _) + when Misc.is_library_loc vi.vdecl || Builtins.mem vi.vname -> + if generate then + Cil.JustCopyPost + (fun l -> + let new_vi = Visitor_behavior.Get.varinfo self#behavior vi in + if Misc.is_library_loc vi.vdecl then + Misc.register_library_function new_vi; + if Builtins.mem vi.vname then Builtins.update vi.vname new_vi; + l) + else begin + Misc.register_library_function vi; + Cil.SkipChildren + end + | GVarDecl(vi, _) | GVar(vi, _, _) | GFun({ svar = vi }, _) + when Cil.is_builtin vi -> + if generate then Cil.JustCopy else Cil.SkipChildren + | g when Misc.is_library_loc (Global.loc g) -> + if generate then Cil.JustCopy else Cil.SkipChildren + | g -> + let do_it = function + | GVar(vi, _, _) -> + vi.vghost <- false + | GFun({ svar = vi } as fundec, _) -> + vi.vghost <- false; + Builtins.update vi.vname vi; + (* remember that we have to remove the main later (see method + [vfile]); do not use the [vorig_name] since both [main] and + [__e_acsl_main] have the same [vorig_name]. *) + if vi.vname = Kernel.MainFunction.get () then + main_fct <- Some fundec + | GVarDecl(vi, _) | GFunDecl(_, vi, _) -> + (* do not convert extern ghost variables, because they can't be linked, + see bts #1392 *) + if vi.vstorage <> Extern then + vi.vghost <- false + | _ -> + () + in + (match g with + | GVar(vi, _, _) | GVarDecl(vi, _) | GFun({ svar = vi }, _) + (* Track function addresses but the main function that is tracked + internally via RTL *) + when vi.vorig_name <> Kernel.MainFunction.get () -> + (* Make a unique mapping for each global variable omitting initializers. + Initializers (used to capture literal strings) are added to + [global_vars] via the [vinit] visitor method (see comments below). *) + Global_observer.add (Visitor_behavior.Get_orig.varinfo self#behavior vi) + | _ -> ()); + if generate then Cil.DoChildrenPost(fun g -> List.iter do_it g; g) + else Cil.DoChildren + + (* Add mappings from global variables to their initializers in [global_vars]. + Note that the below function captures only [SingleInit]s. All compound + initializers containing SingleInits (except for empty compound + initializers) are unrapped and thrown away. *) + method !vinit vi off _ = + if generate then + if Mmodel_analysis.must_model_vi vi then begin + is_initializer <- vi.vglob; + Cil.DoChildrenPost + (fun i -> + (match is_initializer with + | true -> + (match i with + | CompoundInit(_,[]) -> + (* Case of an empty CompoundInit, treat it as if there were + no initializer at all *) + () + | CompoundInit(_,_) | SingleInit _ -> + (* TODO: [off] should be the one of the new project while it is + from the old project *) + Global_observer.add_initializer vi off i) + | false-> ()); + is_initializer <- false; + i) + end else + Cil.JustCopy + else + Cil.SkipChildren + + method !vvdec vi = + (try + let old_vi = Visitor_behavior.Get_orig.varinfo self#behavior vi in + let old_kf = Globals.Functions.get old_vi in + funspec := + Cil.visitCilFunspec + (self :> Cil.cilVisitor) + (Annotations.funspec old_kf) + with Not_found -> + ()); + Cil.SkipChildren + + method private add_generated_variables_in_function f = + assert generate; + let vars = Env.get_generated_variables !function_env in + self#reset_env (); + let locals, blocks = + List.fold_left + (fun (local_vars, block_vars as acc) (v, scope) -> match scope with + (* TODO: [kf] assumed to be consistent. Should be asserted. *) + | Env.LFunction _kf -> v :: local_vars, v :: block_vars + | Env.LLocal_block _kf -> v :: local_vars, block_vars + | _ -> acc) + (f.slocals, f.sbody.blocals) + vars + in + f.slocals <- locals; + f.sbody.blocals <- blocks + + (* Memory management for \at on purely logic variables: + Put [malloc] stmts at proper locations *) + method private insert_malloc_and_free_stmts kf f = + let malloc_stmts = At_with_lscope.Malloc.find_all kf in + let fstmts = malloc_stmts @ f.sbody.bstmts in + f.sbody.bstmts <- fstmts; + (* Now that [malloc] stmts for [kf] have been inserted, + there is no more need to keep the corresponding entries in the + table managing them. *) + At_with_lscope.Malloc.remove_all kf + + method !vfunc f = + if generate then begin + let kf = Extlib.the self#current_kf in + if Functions.instrument kf then Exit_points.generate f; + Options.feedback ~dkey ~level:2 "entering in function %a." + Kernel_function.pretty kf; + List.iter (fun vi -> vi.vghost <- false) f.slocals; + Cil.DoChildrenPost + (fun f -> + Exit_points.clear (); + self#add_generated_variables_in_function f; + self#insert_malloc_and_free_stmts kf f; + Options.feedback ~dkey ~level:2 "function %a done." + Kernel_function.pretty kf; + f) + end else + Cil.DoChildren + + method private is_return old_kf stmt = + let old_ret = + try Kernel_function.find_return old_kf + with Kernel_function.No_Statement -> assert false + in + Stmt.equal stmt (Visitor_behavior.Get.stmt self#behavior old_ret) + + method private is_first_stmt old_kf stmt = + try + Stmt.equal + (Visitor_behavior.Get_orig.stmt self#behavior stmt) + (Kernel_function.find_first_stmt old_kf) + with Kernel_function.No_Statement -> + assert false + + method private is_main old_kf = + try + let main, _ = Globals.entry_point () in + Kernel_function.equal old_kf main + with Globals.No_such_entry_point _s -> + (* [JS 2013/05/21] already a warning in pre-analysis *) + (* Options.warning ~once:true "%s@ \ + @[The generated program may be incomplete.@]" + s;*) + false + + method !vstmt_aux stmt = + Options.debug ~level:4 "proceeding stmt (sid %d) %a@." + stmt.sid Stmt.pretty stmt; + let kf = Extlib.the self#current_kf in + let is_main = self#is_main kf in + let env = Env.push !function_env in + let env = match stmt.skind with + | Loop _ -> Env.push_loop env + | _ -> env + in + let env = + if self#is_first_stmt kf stmt then + (* JS: should be done in the new project? *) + let env = + if generate && not is_main then + let env = Memory.store env kf (Kernel_function.get_formals kf) in + Temporal.handle_function_parameters kf env + else + env + in + (* translate the precondition of the function *) + if Functions.check kf then + Project.on prj (Translate.translate_pre_spec kf env) !funspec + else + env + else + env + in + + let env, new_annots = + if Functions.check kf then + Annotations.fold_code_annot + (fun _ old_a (env, new_annots) -> + let a = + (* [VP] Don't use Visitor here, as it will fill the queue in the + middle of the computation... *) + Cil.visitCilCodeAnnotation (self :> Cil.cilVisitor) old_a + in + let env = + Project.on prj (Translate.translate_pre_code_annotation kf env) a + in + env, a :: new_annots) + (Visitor_behavior.Get_orig.stmt self#behavior stmt) + (env, []) + else + env, [] + in + + (* Add [__e_acsl_store_duplicate] calls for local variables which + * declarations are bypassed by gotos. Note: should be done before + * [vinst] method (which adds initializers) is executed, otherwise + * init calls appear before store calls. *) + let duplicates = Exit_points.store_vars stmt in + let env = + if generate then Memory.duplicate_store ~before:stmt env kf duplicates + else env + in + function_env := env; + + let mk_block stmt = + (* be careful: since this function is called in a post action, [env] has + been modified from the time where pre actions have been executed. + Use [function_env] to get it back. *) + let env = !function_env in + let env = + if generate then + (* Add temporal analysis instrumentations *) + let env = Temporal.handle_stmt stmt env in + (* Add initialization statements and store_block statements stemming + from Local_init *) + self#handle_instructions stmt env kf + else + env + in + let new_stmt, env, must_mv = + if Functions.check kf then + let env = + (* handle ghost statement *) + if stmt.ghost then begin + stmt.ghost <- false; + (* translate potential RTEs of ghost code *) + let rtes = Rte.stmt ~warn:false kf stmt in + Translate.translate_rte_annots Printer.pp_stmt stmt kf env rtes + end else + env + in + (* handle loop invariants *) + let new_stmt, env, must_mv = + Loops.preserve_invariant prj env kf stmt + in + let orig = Visitor_behavior.Get_orig.stmt self#behavior stmt in + Visitor_behavior.Set_orig.stmt self#behavior new_stmt orig; + Visitor_behavior.Set.stmt self#behavior orig new_stmt; + new_stmt, env, must_mv + else + stmt, env, false + in + let mk_post_env env = + (* [fold_right] to preserve order of generation of pre_conditions *) + Project.on + prj + (List.fold_right + (fun a env -> Translate.translate_post_code_annotation kf env a) + new_annots) + env + in + let new_stmt, env = + (* Remove local variables which scopes ended via goto/break/continue. *) + let del_vars = Exit_points.delete_vars stmt in + let env = + if generate then Memory.delete_from_set ~before:stmt env kf del_vars + else env + in + if self#is_return kf stmt then + let env = + if Functions.check kf then + (* must generate the post_block before including [stmt] (the + 'return') since no code is executed after it. However, since + this statement is pure (Cil invariant), that is semantically + correct. *) + (* [JS 2019/2/19] TODO: what about the other ways of early exiting + a block? *) + let env = mk_post_env env in + (* also handle the postcondition of the function and clear the + env *) + Project.on prj (Translate.translate_post_spec kf env) !funspec + else + env + in + (* de-allocating memory previously allocating by the kf *) + (* JS: should be done in the new project? *) + if generate then + (* Remove recorded function arguments *) + let fargs = Kernel_function.get_formals kf in + let env = + if generate then Memory.delete_from_list env kf fargs + else env + in + let b, env = + Env.pop_and_get env new_stmt ~global_clear:true Env.After + in + if is_main && Mmodel_analysis.use_model () then begin + let stmts = b.bstmts in + let l = List.rev stmts in + let mclean = (RTL.mk_api_name "memory_clean") in + match l with + | [] -> assert false (* at least the 'return' stmt *) + | ret :: l -> + let loc = Stmt.loc stmt in + let delete_stmts = + Global_observer.mk_delete + self#behavior + [ Misc.mk_call ~loc mclean []; ret ] + in + b.bstmts <- List.rev l @ delete_stmts + end; + let new_stmt = Misc.mk_block prj stmt b in + if not (Cil_datatype.Stmt.equal stmt new_stmt) then begin + (* move the labels of the return to the new block in order to + evaluate the postcondition when jumping to them. *) + E_acsl_label.move + (self :> Visitor.generic_frama_c_visitor) stmt new_stmt + end; + new_stmt, env + else + stmt, env + else (* i.e. not (is_return stmt) *) + if generate then begin + (* must generate [pre_block] which includes [stmt] before generating + [post_block] *) + let pre_block, env = + Env.pop_and_get + ~split:true + env + new_stmt + ~global_clear:false + Env.After + in + let env = + (* if [kf] is not monitored, do not translate any postcondition, + but still push an empty environment consumed by + [Env.pop_and_get] below. This [Env.pop_and_get] call is always + required in order to generate the code not directly related to + the annotations of the current stmt in anycase. *) + if Functions.check kf then mk_post_env (Env.push env) + else Env.push env + in + let post_block, env = + Env.pop_and_get + env + (Misc.mk_block prj new_stmt pre_block) + ~global_clear:false + Env.Before + in + let post_block = + if post_block.blocals = [] && new_stmt.labels = [] + then Cil.transient_block post_block + else post_block + in + let res = Misc.mk_block prj new_stmt post_block in + if not (Cil_datatype.Stmt.equal new_stmt res) then + E_acsl_label.move (self :> Visitor.generic_frama_c_visitor) + new_stmt res; + let orig = Visitor_behavior.Get_orig.stmt self#behavior stmt in + Visitor_behavior.Set.stmt self#behavior orig res; + Visitor_behavior.Set_orig.stmt self#behavior res orig; + res, env + end else + stmt, env + in + if must_mv then Loops.mv_invariants env ~old:new_stmt stmt; + function_env := env; + Options.debug ~level:4 + "@[new stmt (from sid %d):@ %a@]" stmt.sid Printer.pp_stmt new_stmt; + if generate then new_stmt else stmt + in + Cil.ChangeDoChildrenPost(stmt, mk_block) + + method private handle_instructions stmt env kf = + let add_initializer loc ?vi lv ?(post=false) stmt env kf = + assert generate; + if Functions.instrument kf then + let may_safely_ignore = function + | Var vi, NoOffset -> vi.vglob || vi.vformal + | _ -> false + in + let must_model = Mmodel_analysis.must_model_lval ~stmt ~kf lv in + if not (may_safely_ignore lv) && must_model then + let before = Cil.mkStmt stmt.skind in + let new_stmt = + (* Bitfields are not yet supported ==> no initializer. + A not_yet will be raised in [Translate]. *) + if Cil.isBitfield lv then Project.on prj Cil.mkEmptyStmt () + else Project.on prj (Misc.mk_initialize ~loc) lv + in + let env = Env.add_stmt ~post ~before env new_stmt in + let env = match vi with + | None -> env + | Some vi -> + let new_stmt = Project.on prj Misc.mk_store_stmt vi in + Env.add_stmt ~post ~before env new_stmt + in + env + else + env + else + env + in + let check_formats = Options.Validate_format_strings.get () in + let replace_libc_fn = Options.Replace_libc_functions.get () in + match stmt.skind with + | Instr(Set(lv, _, loc)) -> add_initializer loc lv stmt env kf + | Instr(Local_init(vi, init, loc)) -> + let lv = (Var vi, NoOffset) in + let env = add_initializer loc ~vi lv ~post:true stmt env kf in + (* Handle variable-length array allocation via [__fc_vla_alloc]. + Here each instance of [__fc_vla_alloc] is rewritten to [alloca] + (that is used to implement VLA) and further a custom call to + [store_block] tracking VLA allocation is issued. *) + (* KV: Do not add handling [alloca] allocation here (or anywhere else for + that matter). Handling of [alloca] should be implemented in Frama-C + (eventually). This is such that each call to [alloca] becomes + [__fc_vla_alloc]. It is already handled using the code below. *) + (match init with + | ConsInit (fvi, sz :: _, _) when Libc.is_vla_alloc_name fvi.vname -> + fvi.vname <- Libc.actual_alloca; + (* Since we need to pass [vi] by value cannot use [Misc.mk_store_stmt] + here. Do it manually. *) + let sname = RTL.mk_api_name "store_block" in + let store = Misc.mk_call ~loc sname [ Cil.evar vi ; sz ] in + Env.add_stmt ~post:true env store + (* Rewrite format functions (e.g., [printf]). See some comments below *) + | ConsInit (fvi, args, knd) when check_formats + && Libc.is_printf_name fvi.vname -> + let name = RTL.get_rtl_replacement_name fvi.vname in + let new_vi = Misc.get_lib_fun_vi name in + let fmt = Libc.get_printf_argument_str ~loc fvi.vname args in + stmt.skind <- + Instr(Local_init(vi, ConsInit(new_vi, fmt :: args, knd), loc)); + env + (* Rewrite names of functions for which we have alternative + definitions in the RTL. *) + | ConsInit (fvi, _, _) when replace_libc_fn && + RTL.has_rtl_replacement fvi.vname -> + fvi.vname <- RTL.get_rtl_replacement_name fvi.vname; + env + | _ -> env) + | Instr(Call (result, exp, args, loc)) -> + (* Rewrite names of functions for which we have alternative + definitions in the RTL. *) + (match exp.enode with + | Lval(Var vi, _) when replace_libc_fn && + RTL.has_rtl_replacement vi.vname -> + vi.vname <- RTL.get_rtl_replacement_name vi.vname + | Lval(Var vi , _) when Libc.is_vla_free_name vi.vname -> + (* Handle variable-length array allocation via [__fc_vla_free]. + Rewrite its name to [delete_block]. The rest is in place. *) + vi.vname <- RTL.mk_api_name "delete_block" + | Lval(Var vi, _) when check_formats && Libc.is_printf_name vi.vname -> + (* Rewrite names of format functions (such as printf). This case + differs from the above because argument list of format functions is + extended with an argument describing actual variadic arguments *) + (* Replacement name, e.g., [printf] -> [__e_acsl_builtin_printf] *) + let name = RTL.get_rtl_replacement_name vi.vname in + (* Variadic arguments descriptor *) + let fmt = Libc.get_printf_argument_str ~loc vi.vname args in + (* get the name of the library function we need. Cannot just rewrite + the name as AST check will then fail *) + let vi = Misc.get_lib_fun_vi name in + stmt.skind <- Instr(Call (result, Cil.evar vi, fmt :: args, loc)) + | _ -> ()); + (* Add statement tracking initialization of return values of function + calls *) + (match result with + | Some lv when not (RTL.is_generated_kf kf) -> + add_initializer loc lv ~post:false stmt env kf + | _ -> env) + | _ -> env + + method !vblock blk = + let handle_memory new_blk = + let kf = Extlib.the self#current_kf in + let free_stmts = At_with_lscope.Free.find_all kf in + match new_blk.blocals, free_stmts with + | [], [] -> + new_blk + | [], _ :: _ | _ :: _, [] | _ :: _, _ :: _ -> + let add_locals stmts = + if Functions.instrument kf then + List.fold_left + (fun acc vi -> + if Mmodel_analysis.must_model_vi ~bhv:self#behavior ~kf vi then + Misc.mk_delete_stmt vi :: acc + else + acc) + stmts + new_blk.blocals + else + stmts + in + let rec insert_in_innermost_last_block blk = function + | { skind = Return _ } as ret :: ((potential_clean :: tl) as l) -> + (* keep the return (enclosed in a generated block) at the end; + preceded by clean if any *) + let init, tl = + if self#is_main kf && Mmodel_analysis.use_model () then + free_stmts @ [ potential_clean; ret ], tl + else + free_stmts @ [ ret ], l + in + (* Now that [free] stmts for [kf] have been inserted, + there is no more need to keep the corresponding entries in the + table managing them. *) + At_with_lscope.Free.remove_all kf; + blk.bstmts <- + List.fold_left (fun acc v -> v :: acc) (add_locals init) tl + | { skind = Block b } :: _ -> + insert_in_innermost_last_block b (List.rev b.bstmts) + | l -> blk.bstmts <- + List.fold_left (fun acc v -> v :: acc) (add_locals []) l + in + insert_in_innermost_last_block new_blk (List.rev new_blk.bstmts); + if Functions.instrument kf then + new_blk.bstmts <- + List.fold_left + (fun acc vi -> + if Mmodel_analysis.must_model_vi vi && not vi.vdefined then + let vi = Visitor_behavior.Get.varinfo self#behavior vi in + Misc.mk_store_stmt vi :: acc + else acc) + new_blk.bstmts + blk.blocals; + new_blk + in + if generate then Cil.DoChildrenPost handle_memory else Cil.DoChildren + + (* Processing expressions for the purpose of replacing literal strings found + in the code with variables generated by E-ACSL. *) + method !vexpr _ = + if generate then begin + match is_initializer with + (* Do not touch global initializers because they accept only constants *) + | true -> Cil.DoChildren + (* Replace literal strings elsewhere *) + | false -> + Cil.DoChildrenPost + (fun e -> + let e, env = Literal_observer.exp !function_env e in + function_env := env; + e) + end else + Cil.SkipChildren + + initializer + Misc.reset (); + Logic_functions.reset (); + Literal_strings.reset (); + Global_observer.reset (); + Keep_status.before_translation (); + self#reset_env () + +end + +let do_visit ?(prj=Project.current ()) generate = + (* The main visitor proceeds by tracking declarations belonging to the + E-ACSL runtime library and then using these declarations to generate + statements used in instrumentation. The following code reorders AST + so declarations belonging to E-ACSL library appear atop of any location + requiring instrumentation. *) + Misc.reorder_ast (); + Options.feedback ~level:2 "%s annotations in %a." + (if generate then "translating" else "checking") + Project.pretty prj; + let vis = + Extlib.try_finally ~finally:Typing.clear (new e_acsl_visitor prj) generate + in + (* explicit type annotation in order to check that no new method is + introduced by error *) + (vis : Visitor.frama_c_visitor) + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff --git a/src/plugins/e-acsl/src/code_generator/visit.mli b/src/plugins/e-acsl/src/code_generator/visit.mli new file mode 100644 index 0000000000000000000000000000000000000000..5e01f665644868c2e38968375ac5a1ae2014c1aa --- /dev/null +++ b/src/plugins/e-acsl/src/code_generator/visit.mli @@ -0,0 +1,29 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C's E-ACSL plug-in. *) +(* *) +(* Copyright (C) 2012-2018 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +val do_visit: ?prj:Project.t -> bool -> Visitor.frama_c_visitor + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff --git a/src/plugins/e-acsl/src/libraries/builtins.ml b/src/plugins/e-acsl/src/libraries/builtins.ml new file mode 100644 index 0000000000000000000000000000000000000000..ca591dc3496d098ac6e933a0f56a7bfbfa891b4c --- /dev/null +++ b/src/plugins/e-acsl/src/libraries/builtins.ml @@ -0,0 +1,88 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C's E-ACSL plug-in. *) +(* *) +(* Copyright (C) 2012-2018 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +open Cil_types + +(* store the E-ACSL built-ins by associating a varinfo to its name. *) +let tbl + : varinfo ref Datatype.String.Hashtbl.t + = Datatype.String.Hashtbl.create 7 + +let mem = Datatype.String.Hashtbl.mem tbl +let find s = !(Datatype.String.Hashtbl.find tbl s) + +(* the initial varinfos in the table belong to the original project. At the time + of code generation, we need to update them to the ones of the new project. *) +let update s vi = + try + let vref = Datatype.String.Hashtbl.find tbl s in + vref := vi + with Not_found -> + () + +(* add [vi] in the built-in table if it is an E-ACSL built-in that is not + [already] registered. *) +let add_builtin vi already = + if not already then + let bl_name = vi.vname in + if Options.Builtins.mem bl_name then + match Cil.unrollType vi.vtype with + | TFun(ret_typ, param_typs, _, _) -> + let bl_type = match Cil.unrollType ret_typ with + | TVoid _ -> + Options.fatal + "Expecting a non-void return type for the E-ACSL built-in %s" + bl_name + | _ -> Some (Ctype ret_typ) + in + let bl_profile = match param_typs with + | None -> [] + | Some l -> List.map (fun (name, ty, _) -> (name, Ctype ty)) l + in + let bli = + { bl_name; bl_labels = []; bl_params = []; bl_type; bl_profile } + in + (* add the built-in locally as an E-ACSL built-in, but also as a new + Frama-C built-in. This way, the annotated C code will be parsed when + using it *) + Logic_builtin.add bli; + Datatype.String.Hashtbl.add tbl bl_name (ref vi) + | _ -> + Options.fatal "Expecting a function type for the E-ACSL built-in %s" + bl_name + +let init () = + Datatype.String.Hashtbl.clear tbl; + if not (Options.Builtins.is_empty ()) then + (* every time a new global is visited by [Cabs2cil], check if we must add it + as a new E-ACSL built-in *) + Cabs2cil.register_new_global_hook add_builtin + +(* Initialization of the database must be done before anything else, but parsing + the command line *) +let () = Cmdline.run_after_configuring_stage init + +(* +Local Variables: +compile-command: "make" +End: +*) diff --git a/src/plugins/e-acsl/src/libraries/builtins.mli b/src/plugins/e-acsl/src/libraries/builtins.mli new file mode 100644 index 0000000000000000000000000000000000000000..7e1eb3f7b809988be06a54b4318cfd81dcc54f62 --- /dev/null +++ b/src/plugins/e-acsl/src/libraries/builtins.mli @@ -0,0 +1,40 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C's E-ACSL plug-in. *) +(* *) +(* Copyright (C) 2012-2018 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(** E-ACSL built-in database. *) + +val mem: string -> bool +(** @return true iff the given function name is an E-ACSL built-in *) + +val find: string -> Cil_types.varinfo +(** Get the varinfo corresponding to the given E-ACSL built-in name. + @raise Not_found if it is not a built-in *) + +val update: string -> Cil_types.varinfo -> unit +(** If the given name is an E-ACSL built-in, change its old varinfo by the given + new one. *) + +(* +Local Variables: +compile-command: "make" +End: +*) diff --git a/src/plugins/e-acsl/src/libraries/error.ml b/src/plugins/e-acsl/src/libraries/error.ml new file mode 100644 index 0000000000000000000000000000000000000000..6276d7da7f75ca0279007013a092c329ae360ef0 --- /dev/null +++ b/src/plugins/e-acsl/src/libraries/error.ml @@ -0,0 +1,74 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C's E-ACSL plug-in. *) +(* *) +(* Copyright (C) 2012-2018 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +exception Typing_error of string +let untypable s = raise (Typing_error s) + +exception Not_yet of string +let not_yet s = raise (Not_yet s) + +module Nb_typing = + State_builder.Ref + (Datatype.Int) + (struct + let name = "E_ACSL.Error.Nb_typing" + let default () = 0 + let dependencies = [ Ast.self ] + end) + +let nb_untypable = Nb_typing.get + +module Nb_not_yet = + State_builder.Ref + (Datatype.Int) + (struct + let name = "E_ACSL.Error.Nb_not_yet" + let default () = 0 + let dependencies = [ Ast.self ] + end) + +let nb_not_yet = Nb_not_yet.get + +let generic_handle f res x = + try + f x + with + | Typing_error s -> + let msg = Format.sprintf "@[invalid E-ACSL construct@ `%s'.@]" s in + Options.warning ~once:true ~current:true "@[%s@ Ignoring annotation.@]" msg; + Nb_typing.set (Nb_typing.get () + 1); + res + | Not_yet s -> + let msg = + Format.sprintf "@[E-ACSL construct@ `%s'@ is not yet supported.@]" s + in + Options.warning ~once:true ~current:true "@[%s@ Ignoring annotation.@]" msg; + Nb_not_yet.set (Nb_not_yet.get () + 1); + res + +let handle f x = generic_handle f x x + +(* +Local Variables: +compile-command: "make" +End: +*) diff --git a/src/plugins/e-acsl/src/libraries/error.mli b/src/plugins/e-acsl/src/libraries/error.mli new file mode 100644 index 0000000000000000000000000000000000000000..3e59a8fa0cf462f3d1226abb4eee9195a9aa4981 --- /dev/null +++ b/src/plugins/e-acsl/src/libraries/error.mli @@ -0,0 +1,52 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C's E-ACSL plug-in. *) +(* *) +(* Copyright (C) 2012-2018 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(** Handling errors. *) + +exception Typing_error of string +exception Not_yet of string + +val untypable: string -> 'a +(** Type error built from the given argument. *) + +val not_yet: string -> 'a +(** Not_yet_implemented error built from the given argument. *) + +val handle: ('a -> 'a) -> 'a -> 'a +(** Run the closure with the given argument and handle potential errors. + Return the provide argument in case of errors. *) + +val generic_handle: ('a -> 'b) -> 'b -> 'a -> 'b +(** Run the closure with the given argument and handle potential errors. + Return the additional argument in case of errors. *) + +val nb_untypable: unit -> int +(** Number of untypable annotations. *) + +val nb_not_yet: unit -> int +(** Number of not-yet-supported annotations. *) + +(* +Local Variables: +compile-command: "make" +End: +*) diff --git a/src/plugins/e-acsl/src/libraries/functions.ml b/src/plugins/e-acsl/src/libraries/functions.ml new file mode 100644 index 0000000000000000000000000000000000000000..b97ca171f7a810a1d2edd68bddb2c9089fa84865 --- /dev/null +++ b/src/plugins/e-acsl/src/libraries/functions.ml @@ -0,0 +1,246 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C's E-ACSL plug-in. *) +(* *) +(* Copyright (C) 2012-2018 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +open Cil_types + +(* ************************************************************************** *) +(* Misc functions *) +(* ************************************************************************** *) + +(* return true if the string s starts with prefix p and false otherwise *) +let startswith p s = + let lp = String.length p in + if lp <= String.length s then + p = String.sub s 0 lp + else + false + +(* if string s is prefixed with string p, then return s without p, otherwise + * return s as is *) +let strip_prefix p s = + let lp = String.length p in + if startswith p s then + String.sub s lp (String.length s - lp) + else + s + +(* True if a named function has a definition and false otherwise *) +let has_fundef exp = match exp.enode with + | Lval(Var vi, _) -> + let kf = + try Globals.Functions.get vi + with Not_found -> Options.fatal "[has_fundef] not a function" + in + Kernel_function.is_definition kf + | Lval _ (* function pointer *) -> + false + | _ -> + Options.fatal "[has_fundef] not a left-value: '%a'" Printer.pp_exp exp + +(* ************************************************************************** *) +(* RTL functions *) +(* ************************************************************************** *) + +module RTL = struct + + (* prefix of all functions/variables from the public E-ACSL API *) + let e_acsl_api_prefix = "__e_acsl_" + + (* prefix of temporal analysis functions of the public E-ACSL API *) + let e_acsl_temporal_prefix = e_acsl_api_prefix ^ "temporal_" + + (* prefix of all builtin functions/variables from the public E-ACSL API, + Builtin functions replace original calls in programs. *) + let e_acsl_builtin_prefix = e_acsl_api_prefix ^ "builtin_" + + (* prefix of functions/variables generated by E-ACSL *) + let e_acsl_gen_prefix = "__gen_e_acsl_" + + (* prefix of literal strings generated by E-ACSL *) + let e_acsl_lit_string_prefix = e_acsl_gen_prefix ^ "literal_string" + + let mk_api_name fname = e_acsl_api_prefix ^ fname + + let mk_temporal_name fname = e_acsl_temporal_prefix ^ fname + + let mk_gen_name name = e_acsl_gen_prefix ^ name + + let get_original_name kf = + strip_prefix e_acsl_gen_prefix (Kernel_function.get_name kf) + + let is_generated_name name = startswith e_acsl_gen_prefix name + + let is_generated_kf kf = + is_generated_name (Kernel_function.get_name kf) + + let is_rtl_name name = startswith e_acsl_api_prefix name + + let is_generated_literal_string_name name = + startswith e_acsl_lit_string_prefix name + + let get_rtl_replacement_name fn = e_acsl_builtin_prefix ^ fn + + let has_rtl_replacement = function + | "strcpy" | "strncpy" | "strlen" | "strcat" | "strncat" | "strcmp" + | "strncmp" | "memcpy" | "memset" | "memcmp" | "memmove" -> true + | _ -> false + +end + +(* ************************************************************************** *) +(* Libc functions *) +(* ************************************************************************** *) + +module Libc = struct + + let is_dyn_alloc_name name = + name = "malloc" || name = "realloc" || name = "calloc" + + let is_dyn_free_name name = name = "free" || name = "cfree" + + let is_vla_alloc_name name = name = "__fc_vla_alloc" + let is_vla_free_name name = name = "__fc_vla_free" + + let actual_alloca = "__builtin_alloca" + let is_alloca_name name = name = "alloca" || name = actual_alloca + + let is_memcpy_name name = name = "memcpy" + let is_memset_name name = name = "memset" + + let apply_fn f exp = match exp.enode with + | Lval(Var vi, _) -> f vi.vname + | Lval _ (* function pointer *) -> false + | _ -> Options.fatal "[Functions.Rtl.apply_fn] not a left-value" + + let is_dyn_alloc exp = apply_fn is_dyn_alloc_name exp + let is_dyn_free exp = apply_fn is_dyn_free_name exp + let is_vla_alloc exp = apply_fn is_vla_alloc_name exp + let is_vla_free exp = apply_fn is_vla_free_name exp + let is_alloca exp = apply_fn is_alloca_name exp + let is_memcpy exp = apply_fn is_memcpy_name exp + let is_memset exp = apply_fn is_memset_name exp + + let printf_fmt_position = function + | "printf" -> 1 + | "syslog" | "dprintf" | "fprintf" | "sprintf" -> 2 + | "snprintf" -> 3 + | _ -> 0 + + let is_printf_name name = printf_fmt_position name <> 0 + let is_printf exp = apply_fn is_printf_name exp + + let get_printf_argument_str ~loc fn args = + assert (is_printf_name fn); + (* drop first n elements from a list *) + let rec drop n l = + assert (n >= 0); + if n > 0 then + let l = match l with _ :: e -> e | [] -> [] in + drop (n-1) l + else + l + in + (* get a character representing an integer type *) + let get_ikind_str = function + | IInt -> "d" (* [int] *) + | IUInt -> "D" (* [unsigned int] *) + | ILong -> "l" (* [long] *) + | IULong -> "L" (* [unsigned long] *) + | ILongLong -> "r" (* [long long] *) + | IULongLong -> "R" (* [unsigned long long] *) + (* _Bool, char and short (either signed or unsigned are promoted to + int) *) + | IBool | IChar | ISChar | IUChar | IShort | IUShort -> "d" + in + (* get a character representing a floating point type *) + let get_fkind_str = function + (* Format-based functions expect only double-precision floats. + Single-precision floating points are promoted to doubles so + this case should never happen in fact. *) + | FFloat -> assert false (* "f" *) (* [float] *) + | FDouble -> "e" (* [float/double] *) + | FLongDouble -> "E" (* [long double] *) + in + (* get a character representing a pointer type *) + let get_pkind_str ty = match ty with + | TInt(IChar,_) | TInt(ISChar,_) -> "s" (* [char*] *) + | TInt(IUChar,_) -> "S" (* [unsigned char*] *) + | TInt(IShort,_) -> "q" (* [short*] *) + | TInt(IUShort,_) -> "Q" (* [unsigned short*] *) + | TInt(IInt,_) -> "i" (* [int*] *) + | TInt(IUInt,_) -> "I" (* [unsigned int*] *) + | TInt(ILong,_) -> "z" (* [long int*] *) + | TInt(IULong,_) -> "Z" (* [unsigned long int*] *) + | TInt(ILongLong,_) -> "w" (* [long int*] *) + | TInt(IULongLong,_) -> "W" (* [unsigned long int*] *) + | TVoid _ -> "p" (* [void*] *) + | _ -> + Options.fatal "Unexpected argument type in printf: %a @." + Printer.pp_typ ty + in + let exps = drop (printf_fmt_position fn) args in + let param_str = + List.fold_right + (fun exp acc -> match Cil.unrollType (Cil.typeOf exp) with + | TInt(k, _) -> get_ikind_str k ^ acc + | TFloat(k, _) -> get_fkind_str k ^ acc + | TPtr(ty, _) -> get_pkind_str (Cil.unrollType ty) ^ acc + | TVoid _ | TArray _ | TFun _ | TNamed _ | TComp _ | TEnum _ + | TBuiltin_va_list _ -> assert false) + exps + "" + in + Cil.mkString ~loc param_str + +end + +let check kf = + (* [kf] is monitored iff all functions must be monitored or [kf] belongs to + the white list *) + Options.Functions.is_empty () + || Options.Functions.mem kf + || + (* also check if [kf] is a duplicate of a monitored function *) + let s = RTL.get_original_name kf in + try + let gen_kf = Globals.Functions.find_by_name s in + Options.Functions.mem gen_kf + with Not_found -> + false + +let instrument kf = + (* [kf] is monitored iff all functions must be monitored or [kf] belongs to + the white list *) + Options.Instrument.is_empty () + || + (Options.Instrument.mem kf + && + (not (RTL.is_generated_kf kf) + || + (* all duplicates belong to [Options.Instrument]. For them, look for + their original version. *) + let s = RTL.get_original_name kf in + try + let gen_kf = Globals.Functions.find_by_name s in + Options.Instrument.mem gen_kf + with Not_found -> + false)) diff --git a/src/plugins/e-acsl/src/libraries/functions.mli b/src/plugins/e-acsl/src/libraries/functions.mli new file mode 100644 index 0000000000000000000000000000000000000000..c549f3abc4c59ac67bc7eb7a1dc4351ee54b74e3 --- /dev/null +++ b/src/plugins/e-acsl/src/libraries/functions.mli @@ -0,0 +1,180 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C's E-ACSL plug-in. *) +(* *) +(* Copyright (C) 2012-2018 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +open Cil_types + +val has_fundef: exp -> bool +(** @return [true] if a function whose name is given via [exp] is defined and + [false] otherwise *) + +val check: kernel_function -> bool +(** @return [true] iff code must be generated for annotations of the given + function. *) + +val instrument: kernel_function -> bool +(** @return [true] iff the given function must be instrumented. *) + +(* ************************************************************************** *) +(** {2 RTL} Operations on function belonging to the runtime library of E-ACSL *) +(* ************************************************************************** *) + +module RTL: sig + + val mk_api_name: string -> string + (** Prefix a name (of a variable or a function) with a string that identifies + it as belonging to the public API of E-ACSL runtime library *) + + val mk_temporal_name: string -> string + (** Prefix a name (of a variable or a function) with a string that identifies + it as belonging to the public API of E-ACSL runtime library dealing + with temporal analysis. *) + + val mk_gen_name: string -> string + (** Prefix a name (of a variable or a function) with a string indicating + that this name has been generated during instrumentation phase. *) + + val is_generated_name: string -> bool + (** @return [true] if the prefix of the given name indicates that it has been + generated by E-ACSL instrumentation (see [mk_gen_name] function). *) + + val is_generated_kf: kernel_function -> bool + (** Same as [is_generated_name] but for kernel functions *) + + val is_rtl_name: string -> bool + (** @return [true] if the prefix of the given name indicates that it + belongs to the public API of the E-ACSL Runtime Library *) + + val is_generated_literal_string_name: string -> bool + (** Same as [is_generated_name] but indicates that the name represents a local + variable that replaced a literal string. *) + + val get_original_name: kernel_function -> string + (** Retrieve the name of the kernel function and strip prefix that indicates + that it has been generated by the instrumentation. *) + + val get_rtl_replacement_name: string -> string + (** Given the name of C library function return the name of the RTL function + that potentially replaces it. *) + + val has_rtl_replacement: string -> bool + (** Given the name of C library function return true if there is a drop-in + replacement function for it in the RTL. *) + +end (* Rtl *) + +(* ************************************************************************** *) +(** {2 Libc} Operations on functions belonging to standard library *) +(* ************************************************************************** *) + +module Libc: sig + + val is_memcpy: exp -> bool + (** Return [true] if [exp] captures a function name that matches [memcpy] or + an equivalent function *) + + val is_memcpy_name: string -> bool + (** Same as [is_memcpy] but for strings *) + + val is_memset: exp -> bool + (** Return [true] if [exp] captures a function name that matches [memset] or + an equivalent function *) + + val is_memset_name: string -> bool + (** Same as [is_memset] but for strings *) + + val is_dyn_alloc: exp -> bool + (** Return [true] if [exp] captures a function name that matches a function + that dynamically allocates memory such as [malloc] or [calloc] *) + + val is_dyn_alloc_name: string -> bool + (** Same as [is_dyn_alloc] but for strings *) + + val is_dyn_free: exp -> bool + (** Return [true] if [exp] captures a function name that matches + a function that dynamically deallocates memory (e.g., [free]) *) + + val is_dyn_free_name: string -> bool + (** Same as [is_dyn_free] but for strings *) + + val is_vla_free: exp -> bool + (** Return [true] if [exp] captures a function name that matches + a function that allocates memory for a variable-size array. *) + + val is_vla_free_name: string -> bool + (** Return [true] if [string] captures a function name that matches + a function that deallocates memory for a variable-size array. *) + + val is_vla_alloc: exp -> bool + (** Return [true] if [exp] captures a function name that matches + a function that deallocates memory for a variable-size array. *) + + val is_vla_alloc_name: string -> bool + (** Same as [is_dyn_alloc] but for strings *) + + val is_alloca: exp -> bool + (** Return [true] if [exp] captures a function name that matches + a function that allocates memory on stack. *) + + val is_alloca_name: string -> bool + (** Same as [is_alloca] but for strings *) + + val is_printf: exp -> bool + (** Return [true] if [exp] captures a function name that matches + a printf-like function such as [printf], [fprintf], [dprintf] etc. *) + + val is_printf_name: string -> bool + (** Same as [is_printf] but for strings *) + + val printf_fmt_position: string -> int + (** Given the name of a printf-like function (as determined by + [is_printf_name]) return the number of arguments preceding its variadic + arguments. *) + + val get_printf_argument_str: loc:location -> string -> exp list -> exp + (** Given the name of a printf-like function and the list of its variadic + arguments return a literal string expression where each character + describes the type of an argument from a list. Such characters are also + called abbreviated types. Conversion between abbreviated and C types + characters is as follows: + - "b" -> [_Bool] + - "c" -> [signed char] + - "C" -> [unsigned char] + - "d" -> [int] + - "D" -> [unsigned int] + - "h" -> [short] + - "H" -> [unsigned short] + - "l" -> [long] + - "L" -> [unsigned long] + - "r" -> [long long] + - "R" -> [unsigned long long] + - "f" -> [float] + - "e" -> [double] + - "E" -> [long double] + - "s" -> [char*] + - "i" -> [int*] + - "p" -> [void*] *) + + val actual_alloca: string + (** The name of an actual [alloca] function used at link-time. + In GCC/Clang [alloca] is typically implemented via [__builtin_alloca] *) + +end (* Libc *) diff --git a/src/plugins/e-acsl/src/libraries/gmp_types.ml b/src/plugins/e-acsl/src/libraries/gmp_types.ml new file mode 100644 index 0000000000000000000000000000000000000000..4a89c181276117bb6075c43a468ce26219175c9f --- /dev/null +++ b/src/plugins/e-acsl/src/libraries/gmp_types.ml @@ -0,0 +1,114 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C's E-ACSL plug-in. *) +(* *) +(* Copyright (C) 2012-2018 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(** GMP Values. *) + +open Cil_types + +(**************************************************************************) +(***************************** GMP types***********************************) +(**************************************************************************) + +let mk_dummy_type_info_ref () = + ref + { torig_name = ""; + tname = ""; + ttype = TVoid []; + treferenced = false } + +module type S = sig + val t: unit -> typ + val t_as_ptr: unit -> typ + val is_now_referenced: unit -> unit + val is_t: typ -> bool +end + +module Make(X: sig end) = struct + + let t_torig_ref = mk_dummy_type_info_ref () + let t_struct_torig_ref = mk_dummy_type_info_ref () + + let set_t ty = t_torig_ref := ty + let set_t_struct ty = t_struct_torig_ref := ty + + let is_now_referenced () = !t_torig_ref.treferenced <- true + + let t () = TNamed(!t_torig_ref, []) + + (* create a unique shared representation in order to use [==] in [is_t] *) + let t_as_ptr_info = + lazy + { + torig_name = ""; + tname = !t_struct_torig_ref.tname ^ " *"; + ttype = TArray( + TNamed(!t_struct_torig_ref, []), + Some (Cil.one ~loc:Cil_datatype.Location.unknown), + {scache = Not_Computed}, + []); + treferenced = true; + } + + let t_as_ptr () = TNamed (Lazy.force t_as_ptr_info, []) + + let is_t ty = match ty with + | TNamed(tinfo, []) -> + tinfo == !t_torig_ref || tinfo == Lazy.force t_as_ptr_info + | _ -> false + +end + +module Z = Make(struct end) +module Q = Make(struct end) + +(**************************************************************************) +(******************* Initialization of mpz and mpq types ******************) +(**************************************************************************) + +let init () = + Options.feedback ~level:2 "initializing GMP types."; + let set_mp_t = object (self) + inherit Cil.nopCilVisitor + + (* exit after having initialized the 4 values (for Z.t and Q.t) *) + val mutable visited = 0 + method private set f info = + f info; + if visited = 3 then + raise Exit + else begin + visited <- visited + 1; + Cil.SkipChildren + end + + method !vglob = function + | GType({ torig_name = name } as info, _) -> + if name = "__e_acsl_mpz_t" then self#set Z.set_t info + else if name = "__e_acsl_mpz_struct" then self#set Z.set_t_struct info + else if name = "__e_acsl_mpq_t" then self#set Q.set_t info + else if name = "__e_acsl_mpq_struct" then self#set Q.set_t_struct info + else Cil.SkipChildren + | _ -> + Cil.SkipChildren + + end in + try Cil.visitCilFileSameGlobals set_mp_t (Ast.get ()) with Exit -> () diff --git a/src/plugins/e-acsl/src/libraries/gmp_types.mli b/src/plugins/e-acsl/src/libraries/gmp_types.mli new file mode 100644 index 0000000000000000000000000000000000000000..8c5558f3119762fee113f7669e7db2d2f9eb05cd --- /dev/null +++ b/src/plugins/e-acsl/src/libraries/gmp_types.mli @@ -0,0 +1,55 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C's E-ACSL plug-in. *) +(* *) +(* Copyright (C) 2012-2018 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(** GMP Values. *) + +open Cil_types + +val init: unit -> unit +(** Must be called before any use of GMP *) + +(**************************************************************************) +(******************************** Types ***********************************) +(**************************************************************************) + +(** Signature of a GMP type *) +module type S = sig + + val t: unit -> typ + (** @return the GMP type *) + + val t_as_ptr: unit -> typ + (** type equivalent to [t] but seen as a pointer *) + + val is_now_referenced: unit -> unit + (** Call this function when using this type for the first time. *) + + val is_t: typ -> bool + (** @return true iff the given type is equivalent to the GMP type. *) + +end + +(** Representation of the unbounded integer type at runtime *) +module Z: S + +(** Representation of the rational type at runtime *) +module Q: S diff --git a/src/plugins/e-acsl/src/libraries/misc.ml b/src/plugins/e-acsl/src/libraries/misc.ml new file mode 100644 index 0000000000000000000000000000000000000000..2f886c8ce5492a491518d8b1751a9bfdcd4a9144 --- /dev/null +++ b/src/plugins/e-acsl/src/libraries/misc.ml @@ -0,0 +1,344 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C's E-ACSL plug-in. *) +(* *) +(* Copyright (C) 2012-2018 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +module RTL = Functions.RTL +open Cil_types +open Cil_datatype + +(* ************************************************************************** *) +(** {2 Handling the E-ACSL's C-libraries, part I} *) +(* ************************************************************************** *) + +let library_files () = + List.map + (fun d -> Options.Share.file ~error:true d) + [ "e_acsl_gmp_api.h"; + "e_acsl.h" ] + +let normalized_library_files = + lazy (List.map Datatype.Filepath.of_string (library_files ())) + +let is_library_loc (loc, _) = + List.mem loc.Filepath.pos_path (Lazy.force normalized_library_files) + +let library_functions = Datatype.String.Hashtbl.create 17 +let register_library_function vi = + Datatype.String.Hashtbl.add library_functions vi.vname vi + +let reset () = Datatype.String.Hashtbl.clear library_functions + +(* ************************************************************************** *) +(** {2 Builders} *) +(* ************************************************************************** *) + +exception Unregistered_library_function of string +let get_lib_fun_vi fname = + try Datatype.String.Hashtbl.find library_functions fname + with Not_found -> + try Builtins.find fname + with Not_found -> + (* should not happen in normal mode, but could be raised when E-ACSL is + used as a library *) + raise (Unregistered_library_function fname) + +let mk_call ~loc ?result fname args = + let vi = get_lib_fun_vi fname in + let f = Cil.evar ~loc vi in + vi.vreferenced <- true; + let make_args args ty_params = + List.map2 + (fun (_, ty, _) arg -> + let e = + match ty, Cil.unrollType (Cil.typeOf arg), arg.enode with + | TPtr _, TArray _, Lval lv -> Cil.new_exp ~loc (StartOf lv) + | TPtr _, TArray _, _ -> assert false + | _, _, _ -> arg + in + Cil.mkCast ~force:false ~newt:ty ~e) + ty_params + args + in + let args = match vi.vtype with + | TFun(_, Some params, _, _) -> make_args args params + | TFun(_, None, _, _) -> [] + | _ -> assert false + in + Cil.mkStmtOneInstr ~valid_sid:true (Call(result, f, args, loc)) + +let mk_deref ~loc lv = + Cil.new_exp ~loc (Lval(Mem(lv), NoOffset)) + +type annotation_kind = + | Assertion + | Precondition + | Postcondition + | Invariant + | RTE + +let kind_to_string loc k = + Cil.mkString + ~loc + (match k with + | Assertion -> "Assertion" + | Precondition -> "Precondition" + | Postcondition -> "Postcondition" + | Invariant -> "Invariant" + | RTE -> "RTE") + +(* Build a C conditional doing a runtime assertion check. *) +let mk_e_acsl_guard ?(reverse=false) kind kf e p = + let loc = p.pred_loc in + let msg = + Kernel.Unicode.without_unicode + (Format.asprintf "%a@?" Printer.pp_predicate) p + in + let line = (fst loc).Filepath.pos_lnum in + let e = + if reverse then e else Cil.new_exp ~loc:e.eloc (UnOp(LNot, e, Cil.intType)) + in + mk_call + ~loc + (RTL.mk_api_name "assert") + [ e; + kind_to_string loc kind; + Cil.mkString ~loc (RTL.get_original_name kf); + Cil.mkString ~loc msg; + Cil.integer loc line ] + +let mk_block prj stmt b = + let mk b = match b.bstmts with + | [] -> + (match stmt.skind with + | Instr(Skip _) -> stmt + | _ -> assert false) + | [ s ] -> s + | _ :: _ -> Cil.mkStmt ~valid_sid:true (Block b) + in + Project.on prj mk b + +(* ************************************************************************** *) +(** {2 Handling \result} *) +(* ************************************************************************** *) + +let result_lhost kf = + let stmt = + try Kernel_function.find_return kf + with Kernel_function.No_Statement -> assert false + in + match stmt.skind with + | Return(Some { enode = Lval (lhost, NoOffset) }, _) -> lhost + | _ -> assert false + +let result_vi kf = match result_lhost kf with + | Var vi -> vi + | Mem _ -> assert false + +(* ************************************************************************** *) +(** {2 Handling the E-ACSL's C-libraries, part II} *) +(* ************************************************************************** *) + +let mk_full_init_stmt ?(addr=true) vi = + let loc = vi.vdecl in + let mk = mk_call ~loc (RTL.mk_api_name "full_init") in + match addr, Cil.unrollType vi.vtype with + | _, TArray(_,Some _, _, _) | false, _ -> mk [ Cil.evar ~loc vi ] + | _ -> mk [ Cil.mkAddrOfVi vi ] + +let mk_initialize ~loc (host, offset as lv) = match host, offset with + | Var _, NoOffset -> mk_call ~loc + (RTL.mk_api_name "full_init") + [ Cil.mkAddrOf ~loc lv ] + | _ -> + let typ = Cil.typeOfLval lv in + mk_call ~loc + (RTL.mk_api_name "initialize") + [ Cil.mkAddrOf ~loc lv; Cil.new_exp loc (SizeOf typ) ] + +let mk_named_store_stmt name ?str_size vi = + let ty = Cil.unrollType vi.vtype in + let loc = vi.vdecl in + let store = mk_call ~loc (RTL.mk_api_name name) in + match ty, str_size with + | TArray(_, Some _,_,_), None -> + store [ Cil.evar ~loc vi ; Cil.sizeOf ~loc ty ] + | TPtr(TInt(IChar, _), _), Some size -> store [ Cil.evar ~loc vi ; size ] + | _, None -> store [ Cil.mkAddrOfVi vi ; Cil.sizeOf ~loc ty ] + | _, Some _ -> assert false + +let mk_store_stmt ?str_size vi = + mk_named_store_stmt "store_block" ?str_size vi + +let mk_duplicate_store_stmt ?str_size vi = + mk_named_store_stmt "store_block_duplicate" ?str_size vi + +let mk_delete_stmt vi = + let loc = vi.vdecl in + let mk = mk_call ~loc (RTL.mk_api_name "delete_block") in + match Cil.unrollType vi.vtype with + | TArray(_, Some _, _, _) -> mk [ Cil.evar ~loc vi ] + | _ -> mk [ Cil.mkAddrOfVi vi ] + +let mk_mark_readonly vi = + let loc = vi.vdecl in + mk_call ~loc (RTL.mk_api_name "mark_readonly") [ Cil.evar ~loc vi ] + +(* ************************************************************************** *) +(** {2 Other stuff} *) +(* ************************************************************************** *) + +let term_addr_of ~loc tlv ty = + Logic_const.taddrof ~loc tlv (Ctype (TPtr(ty, []))) + +let reorder_ast () = + let ast = Ast.get() in + let is_from_library = function + | GType(ti, _) when ti.tname = "size_t" || ti.tname = "FILE" + || RTL.is_rtl_name ti.tname -> true + | GCompTag (ci, _) when RTL.is_rtl_name ci.cname -> true + | GFunDecl(_, _, loc) | GVarDecl(_, loc) when is_library_loc loc -> true + | _ -> false in + let rtl, other = List.partition is_from_library ast.globals in + ast.globals <- rtl @ other + +let cty = function + | Ctype ty -> ty + | lty -> Options.fatal "Expecting a C type. Got %a" Printer.pp_logic_type lty + +let rec ptr_index ?(loc=Location.unknown) ?(index=(Cil.zero loc)) exp = + let arith_op = function + | MinusPI -> MinusA + | PlusPI -> PlusA + | IndexPI -> PlusA + | _ -> assert false in + match exp.enode with + | BinOp(op, lhs, rhs, _) -> + (match op with + (* Pointer arithmetic: split pointer and integer parts *) + | MinusPI | PlusPI | IndexPI -> + let index = Cil.mkBinOp exp.eloc (arith_op op) index rhs in + ptr_index ~index lhs + (* Other arithmetic: treat the whole expression as pointer address *) + | MinusPP | PlusA | MinusA | Mult | Div | Mod + | BAnd | BXor | BOr | Shiftlt | Shiftrt + | Lt | Gt | Le | Ge | Eq | Ne | LAnd | LOr -> (exp, index)) + | CastE _ -> ptr_index ~loc ~index (Cil.stripCasts exp) + | Info (exp, _) -> ptr_index ~loc ~index exp + | Const _ | StartOf _ | AddrOf _ | Lval _ | UnOp _ -> (exp, index) + | SizeOf _ | SizeOfE _ | SizeOfStr _ | AlignOf _ | AlignOfE _ + -> assert false + +(* TODO: should not be in this file *) +let term_of_li li = match li.l_body with +| LBterm t -> t +| LBnone | LBreads _ | LBpred _ | LBinductive _ -> + Options.fatal "li.l_body does not match LBterm(t) in Misc.term_of_li" + +let is_set_of_ptr_or_array lty = + if Logic_const.is_set_type lty then + let lty = Logic_const.type_of_element lty in + Logic_utils.isLogicPointerType lty || Logic_utils.isLogicArrayType lty + else + false + +exception Range_found_exception +let is_range_free t = + try + let has_range_visitor = object inherit Visitor.frama_c_inplace + method !vterm t = match t.term_node with + | Trange _ -> raise Range_found_exception + | _ -> Cil.DoChildren + end + in + ignore (Visitor.visitFramacTerm has_range_visitor t); + true + with Range_found_exception -> + false + +let is_bitfield_pointers lty = + let is_bitfield_pointer = function + | Ctype typ -> + begin match Cil.unrollType typ with + | TPtr(typ, _) -> + let attrs = Cil.typeAttrs typ in + Cil.hasAttribute Cil.bitfield_attribute_name attrs + | _ -> + false + end + | Ltype _ | Lvar _ | Linteger | Lreal | Larrow _ -> + false + in + if Logic_const.is_set_type lty then + is_bitfield_pointer (Logic_const.type_of_element lty) + else + is_bitfield_pointer lty + +exception Lv_from_vi_found +let term_has_lv_from_vi t = + try + let o = object inherit Visitor.frama_c_inplace + method !vlogic_var_use lv = match lv.lv_origin with + | None -> Cil.DoChildren + | Some _ -> raise Lv_from_vi_found + end + in + ignore (Visitor.visitFramacTerm o t); + false + with Lv_from_vi_found -> + true + +type pred_or_term = PoT_pred of predicate | PoT_term of term + +let mk_ptr_sizeof typ loc = + match Cil.unrollType typ with + | TPtr (t', _) -> Cil.new_exp ~loc (SizeOf t') + | _ -> assert false + +let finite_min_and_max i = match Ival.min_and_max i with + | Some min, Some max -> min, max + | None, _ | _, None -> assert false + +let name_of_binop = function + | Lt -> "lt" + | Gt -> "gt" + | Le -> "le" + | Ge -> "ge" + | Eq -> "eq" + | Ne -> "ne" + | LOr -> "or" + | LAnd -> "and" + | BOr -> "bor" + | BXor -> "bxor" + | BAnd -> "band" + | Shiftrt -> "shiftr" + | Shiftlt -> "shiftl" + | Mod -> "mod" + | Div -> "div" + | Mult -> "mul" + | PlusA -> "add" + | MinusA -> "sub" + | MinusPP | MinusPI | IndexPI | PlusPI -> assert false + +(* +Local Variables: +compile-command: "make" +End: +*) diff --git a/src/plugins/e-acsl/src/libraries/misc.mli b/src/plugins/e-acsl/src/libraries/misc.mli new file mode 100644 index 0000000000000000000000000000000000000000..c116a7dff4102a5649bec9a67090c30998bf066c --- /dev/null +++ b/src/plugins/e-acsl/src/libraries/misc.mli @@ -0,0 +1,137 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C's E-ACSL plug-in. *) +(* *) +(* Copyright (C) 2012-2018 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(** Utilities for E-ACSL. *) + +open Cil_types +open Cil_datatype + +(* ************************************************************************** *) +(** {2 Builders} *) +(* ************************************************************************** *) + +exception Unregistered_library_function of string +val get_lib_fun_vi: string -> varinfo +(** Return varinfo corresponding to a name of a given library function *) + +val mk_call: loc:Location.t -> ?result:lval -> string -> exp list -> stmt +(** Call an E-ACSL library function or an E-ACSL built-in. + @raise Unregistered_library_function if the given string does not represent + such a function or if these functions were never registered (only possible + when using E-ACSL through its API. *) + +val mk_deref: loc:Location.t -> exp -> exp +(** Make a dereference of an expression *) + +type annotation_kind = + | Assertion + | Precondition + | Postcondition + | Invariant + | RTE + +val mk_e_acsl_guard: + ?reverse:bool -> annotation_kind -> kernel_function -> exp -> predicate + -> stmt + +val mk_block: Project.t -> stmt -> block -> stmt + +(* ************************************************************************** *) +(** {2 Handling \result} *) +(* ************************************************************************** *) + +val result_lhost: kernel_function -> lhost +(** @return the lhost corresponding to \result in the given function *) + +val result_vi: kernel_function -> varinfo +(** @return the varinfo corresponding to \result in the given function *) + +(* ************************************************************************** *) +(** {2 Handling the E-ACSL's C-libraries} *) +(* ************************************************************************** *) + +val library_files: unit -> string list +val is_library_loc: location -> bool +val register_library_function: varinfo -> unit +val reset: unit -> unit + +val mk_store_stmt: ?str_size:exp -> varinfo -> stmt +val mk_duplicate_store_stmt: ?str_size:exp -> varinfo -> stmt +val mk_delete_stmt: varinfo -> stmt +val mk_full_init_stmt: ?addr:bool -> varinfo -> stmt +val mk_initialize: loc:location -> lval -> stmt +val mk_mark_readonly: varinfo -> stmt + +(* ************************************************************************** *) +(** {2 Other stuff} *) +(* ************************************************************************** *) + +val term_addr_of: loc:location -> term_lval -> typ -> term + +val reorder_ast: unit -> unit +(* Reorder current AST by bringing all global declarations belonging to the + * E-ACSL runtime library and their dependencies (e.g., typedef size_t) to + * the very top of the file. *) + +val cty: logic_type -> typ +(** Assume that the logic type is indeed a C type. Just return it. *) + +val ptr_index: ?loc:location -> ?index:exp -> exp + -> Cil_types.exp * Cil_types.exp +(** Split pointer-arithmetic expression of the type `p + i` into its + pointer and integer parts. *) + +val term_of_li: logic_info -> term +(** [term_of_li li] assumes that [li.l_body] matches [LBterm t] + and returns [t]. *) + +val is_set_of_ptr_or_array: logic_type -> bool +(** Checks whether the given logic type is a set of pointers. *) + +val is_range_free: term -> bool +(** Returns [true] iff the given term does not contain any range. *) + +val is_bitfield_pointers: logic_type -> bool +(** Returns [true] iff the given logic type is a bitfield pointer or a + set of bitfield pointers. *) + +val term_has_lv_from_vi: term -> bool +(** Return [true] iff the given term contains a variables that originates from + a C varinfo, that is a non-purely logic variable. *) + +type pred_or_term = PoT_pred of predicate | PoT_term of term + +val mk_ptr_sizeof: typ -> location -> exp +(** [mk_ptr_sizeof ptr_typ loc] takes the pointer typ [ptr_typ] that points + to a [typ] typ and returns [sizeof(typ)]. *) + +val name_of_binop: binop -> string +(** Returns the name of the given binop as a string *) + +val finite_min_and_max: Ival.t -> Integer.t * Integer.t +(** [finite_min_and_max i] takes the finite ival [i] and returns its bounds *) + +(* +Local Variables: +compile-command: "make" +End: +*) diff --git a/src/plugins/e-acsl/src/libraries/varname.ml b/src/plugins/e-acsl/src/libraries/varname.ml new file mode 100644 index 0000000000000000000000000000000000000000..ee620d48895f00794a4aec2e87c751c2208eb4ef --- /dev/null +++ b/src/plugins/e-acsl/src/libraries/varname.ml @@ -0,0 +1,52 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C's E-ACSL plug-in. *) +(* *) +(* Copyright (C) 2012-2018 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +type scope = + | Global + | Function + | Block + +module H = Datatype.String.Hashtbl +let tbl = H.create 7 +let globals = H.create 7 + +let get ~scope s = + let _, u = + Extlib.make_unique_name + (fun s -> H.mem tbl s || H.mem globals s) + ~sep:"_" + s + in + let add = match scope with + | Global -> H.add globals + | Function | Block -> H.add tbl + in + add u (); + u + +let clear_locals () = H.clear tbl + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff --git a/src/plugins/e-acsl/src/libraries/varname.mli b/src/plugins/e-acsl/src/libraries/varname.mli new file mode 100644 index 0000000000000000000000000000000000000000..bb003c543372c2050b7099b3389f5468ff014a7b --- /dev/null +++ b/src/plugins/e-acsl/src/libraries/varname.mli @@ -0,0 +1,41 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C's E-ACSL plug-in. *) +(* *) +(* Copyright (C) 2012-2018 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* Variable name generator wrt a lexical scope. *) + +type scope = + | Global + | Function + | Block + +val get: scope:scope -> string -> string +(** @return a fresh variable name for the given scope wrt the given name. *) + +val clear_locals: unit -> unit +(** Reset the generator for variables that are local to a block or a + function. *) + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff --git a/src/plugins/e-acsl/src/local_config.mli b/src/plugins/e-acsl/src/local_config.mli new file mode 100644 index 0000000000000000000000000000000000000000..6374af51bc59a8f33297791f584842456eed57f1 --- /dev/null +++ b/src/plugins/e-acsl/src/local_config.mli @@ -0,0 +1,29 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C's E-ACSL plug-in. *) +(* *) +(* Copyright (C) 2012-2018 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +val version: string + +(* +Local Variables: +compile-command: "make" +End: +*) diff --git a/src/plugins/e-acsl/src/main.ml b/src/plugins/e-acsl/src/main.ml new file mode 100644 index 0000000000000000000000000000000000000000..826323b205dfea4183cf1b39e41b043fc7151721 --- /dev/null +++ b/src/plugins/e-acsl/src/main.ml @@ -0,0 +1,273 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C's E-ACSL plug-in. *) +(* *) +(* Copyright (C) 2012-2018 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +let check () = + Visitor.visitFramacFileSameGlobals (Visit.do_visit false) (Ast.get ()); + let t = Error.nb_untypable () in + let n = Error.nb_not_yet () in + let print msg n = + Options.result "@[%d annotation%s %s ignored,@ being %s.@]" + n + (if n > 1 then "s" else "") + (if n > 1 then "were" else "was") + msg + in + print "untypable" t; + print "unsupported" n; + n + t = 0 + +let check = + Dynamic.register + ~plugin:"e-acsl" + ~journalize:true + "check" + (Datatype.func Datatype.unit Datatype.bool) + check + +type extended_project = + | To_be_extended + | Already_extended of Project.t option (* None = keep the current project *) + +let extended_ast_project: extended_project ref = ref To_be_extended + +let unmemoized_extend_ast () = + let extend () = + let share = Options.Share.dir ~error:true () in + Options.feedback ~level:3 "setting kernel options for E-ACSL."; + Kernel.CppExtraArgs.add + (Format.asprintf " -DE_ACSL_MACHDEP=%s -I%s/memory_model" + (Kernel.Machdep.get ()) + share); + Kernel.Keep_unused_specified_functions.off (); + if Plugin.is_present "variadic-translation" then + Dynamic.Parameter.Bool.off "-variadic-translation" (); + let ppc, ppk = File.get_preprocessor_command () in + let register s = + File.pre_register + (File.NeedCPP + (s, + ppc + ^ Format.asprintf " -I%s" share, + ppk)) + in + List.iter register (Misc.library_files ()) + in + if Ast.is_computed () then begin + (* do not modify the existing project: work on a copy. + Must also extend the current AST with the E-ACSL's library files. *) + Options.feedback ~level:2 "AST already computed: \ +E-ACSL is going to work on a copy."; + let name = Project.get_name (Project.current ()) in + let tmpfile = + Extlib.temp_file_cleanup_at_exit ("e_acsl_" ^ name) ".i" in + let cout = open_out tmpfile in + let fmt = Format.formatter_of_out_channel cout in + File.pretty_ast ~fmt (); + let selection = + State_selection.diff + State_selection.full + (State_selection.with_dependencies Ast.self) + in + let prj = + Project.create_by_copy + ~last:false + ~selection + (Format.asprintf "%s for E-ACSL" name) + in + Project.on prj + (fun () -> + Kernel.Files.set [ tmpfile ]; + extend ()) + (); + Some prj + end else begin + extend (); + None + end + +let extend_ast () = match !extended_ast_project with + | To_be_extended -> + let prj = unmemoized_extend_ast () in + extended_ast_project := Already_extended prj; + (match prj with + | None -> Project.current () + | Some prj -> prj) + | Already_extended None -> + Project.current () + | Already_extended(Some prj) -> + prj + +let apply_on_e_acsl_ast f x = + let tmp_prj = extend_ast () in + let res = Project.on tmp_prj f x in + (match !extended_ast_project with + | To_be_extended -> assert false + | Already_extended None -> () + | Already_extended (Some prj) -> + assert (Project.equal prj tmp_prj); + extended_ast_project := To_be_extended; + if Options.Debug.get () = 0 then Project.remove ~project:tmp_prj ()); + res + +module Resulting_projects = + State_builder.Hashtbl + (Datatype.String.Hashtbl) + (Project.Datatype) + (struct + let name = "E-ACSL resulting projects" + let size = 7 + let dependencies = Ast.self :: Options.parameter_states + end) + +let () = + State_dependency_graph.add_dependencies + ~from:Resulting_projects.self + [ Label.self ] + +let generate_code = + Resulting_projects.memo + (fun name -> + apply_on_e_acsl_ast + (fun () -> + Options.feedback "beginning translation."; + Temporal.enable (Options.Temporal_validity.get ()); + let prepared_prj = Prepare_ast.prepare () in + let res = + Project.on prepared_prj + (fun () -> + let dup_prj = Dup_functions.dup () in + let res = + Project.on + dup_prj + (fun () -> + Gmp_types.init (); + Mmodel_analysis.reset (); + let visit prj = Visit.do_visit ~prj true in + let prj = + File.create_project_from_visitor name visit + in + Loops.apply_after_transformation prj; + (* remove the RTE's results computed from E-ACSL: + their are partial and associated with the wrong + kernel function (the one of the old project). *) + let selection = + State_selection.with_dependencies !Db.RteGen.self + in + Project.clear ~selection ~project:prj (); + Resulting_projects.mark_as_computed (); + let selection = + State_selection.singleton Kernel.Files.self + in + Project.copy ~selection prj; + prj) + () + in + if Options.Debug.get () = 0 then + Project.remove ~project:dup_prj (); + res) + () + in + if Options.Debug.get () = 0 then begin + Project.remove ~project:prepared_prj (); + end; + Options.feedback "translation done in project \"%s\"." + (Options.Project_name.get ()); + res) + ()) + +let generate_code = + Dynamic.register + ~plugin:"E_ACSL" + ~journalize:true + "generate_code" + (Datatype.func Datatype.string Project.ty) + generate_code + +let predicate_to_exp = + Dynamic.register + ~plugin:"E_ACSL" + ~journalize:false + "predicate_to_exp" + (Datatype.func2 + Kernel_function.ty Cil_datatype.Predicate.ty Cil_datatype.Exp.ty) + Translate.predicate_to_exp + +let add_e_acsl_library _files = + if Options.must_visit () || Options.Prepare.get () then ignore (extend_ast ()) + +(* extending the AST as soon as possible reduce the amount of time the AST is + duplicated: + - that is faster + - locations are better (indicate an existing file, and not a temp file) *) +let () = Cmdline.run_after_configuring_stage add_e_acsl_library + +(* The Frama-C standard library contains specific built-in variables prefixed by + "__fc_" and declared as extern: they prevent the generated code to be + linked. This modification of the default printer replaces them by their + original version from the stdlib. For instance, [__fc_stdout] is replaced by + [stdout]. That is very hackish since it modifies the default Frama-C + printer. + + TODO: should be done by the Frama-C default printer at some points. *) +let change_printer = + (* not projectified on purpose: this printer change is common to each + project. *) + let first = ref true in + fun () -> + if !first then begin + first := false; + let r = Str.regexp "^__fc_" in + let module Printer_class(X: Printer.PrinterClass) = struct + class printer = object + inherit X.printer as super + method !varinfo fmt vi = + if vi.Cil_types.vghost || vi.Cil_types.vstorage <> Cil_types.Extern + then + super#varinfo fmt vi + else + let s = Str.replace_first r "" vi.Cil_types.vname in + Format.fprintf fmt "%s" s + end + end in + Printer.update_printer (module Printer_class: Printer.PrinterExtension) + end + +let main () = + Keep_status.clear (); + if Options.Run.get () then begin + change_printer (); + ignore (generate_code (Options.Project_name.get ())) + end else + if Options.Check.get () then + apply_on_e_acsl_ast + (fun () -> + Gmp_types.init (); + ignore (check ())) + () + +let () = Db.Main.extend main + +(* +Local Variables: +compile-command: "make -C .." +End: +*) diff --git a/src/plugins/e-acsl/src/options.ml b/src/plugins/e-acsl/src/options.ml new file mode 100644 index 0000000000000000000000000000000000000000..43993429a8c7ced5df2df9250ba7ff66952b5e91 --- /dev/null +++ b/src/plugins/e-acsl/src/options.ml @@ -0,0 +1,177 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C's E-ACSL plug-in. *) +(* *) +(* Copyright (C) 2012-2018 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +let () = Plugin.is_share_visible () +module P = Plugin.Register + (struct + let name = "E-ACSL" + let shortname = "e-acsl" + let help = "Executable ANSI/ISO C Specification Language --- runtime \ +assertion checker generator" + end) +module PP = P (* [PP] required to avoid an ocamldoc error in OCaml 4.02 *) +include PP + +module Check = + False + (struct + let option_name = "-e-acsl-check" + let help = "only type check E-ACSL annotated program" + end) + +module Run = + False + (struct + let option_name = "-e-acsl" + let help = "generate a new project where E-ACSL annotations are \ +translated to executable C code" + end) + +module Project_name = + String + (struct + let option_name = "-e-acsl-project" + let help = "the name of the generated project is <prj> \ +(default to \"e-acsl\")" + let default = "e-acsl" + let arg_name = "prj" + end) + +module Valid = + False + (struct + let option_name = "-e-acsl-valid" + let help = "translate annotation which have been proven valid" + end) + +module Prepare = + False + (struct + let option_name = "-e-acsl-prepare" + let help = "prepare the AST to be directly usable by E-ACSL" + end) + +module Gmp_only = + False + (struct + let option_name = "-e-acsl-gmp-only" + let help = "always use GMP integers instead of C integral types" + end) + +module Temporal_validity = + False + (struct + let option_name = "-e-acsl-temporal-validity" + let help = "enable temporal analysis in valid annotations" + end) + +module Validate_format_strings = + False + (struct + let option_name = "-e-acsl-validate-format-strings" + let help = "enable runtime validation of stdio.h format functions" + end) + +module Replace_libc_functions = + False + (struct + let option_name = "-e-acsl-replace-libc-functions" + let help = "replace some libc functions (such as strcpy) with built-in\ + RTL alternatives" + end) + +module Full_mmodel = + False + (struct + let option_name = "-e-acsl-full-mmodel" + let help = "maximal memory-related instrumentation" + end) + +module Builtins = + String_set + (struct + let option_name = "-e-acsl-builtins" + let arg_name = "" + let help = "C functions which can be used in the E-ACSL specifications" + end) + +module Functions = + Kernel_function_set + (struct + let option_name = "-e-acsl-functions" + let arg_name = "f1, ..., fn" + let help = "only annotations in functions f1, ..., fn are checked at \ +runtime" + end) + +module Instrument = + Kernel_function_set + (struct + let option_name = "-e-acsl-instrument" + let arg_name = "f1, ..., fn" + let help = "only instrument functions f1, ..., fn. \ +Be aware that runtime verdicts may become partial." + end) + + +let () = Parameter_customize.set_group help +module Version = + False + (struct + let option_name = "-e-acsl-version" + let help = "version of plug-in E-ACSL" + end) + +let version () = + if Version.get () then begin + Log.print_on_output + (fun fmt -> + Format.fprintf + fmt + "Version of plug-in E-ACSL: %s@?" + Local_config.version); + raise Cmdline.Exit + end +let () = Cmdline.run_after_configuring_stage version + +let parameter_states = + [ Valid.self; + Gmp_only.self; + Full_mmodel.self; + Builtins.self; + Temporal_validity.self; + Validate_format_strings.self; + Functions.self; + Instrument.self ] + +let must_visit () = Run.get () || Check.get () + +let dkey_analysis = register_category "analysis" +let dkey_dup = register_category "duplication" +let dkey_translation = register_category "translation" +let dkey_typing = register_category "typing" + +(* +Local Variables: +compile-command: "make" +End: +*) diff --git a/src/plugins/e-acsl/src/options.mli b/src/plugins/e-acsl/src/options.mli new file mode 100644 index 0000000000000000000000000000000000000000..acfb14aa16fcb8fb5bd46eedec5ef4a849ca4cf7 --- /dev/null +++ b/src/plugins/e-acsl/src/options.mli @@ -0,0 +1,53 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C's E-ACSL plug-in. *) +(* *) +(* Copyright (C) 2012-2018 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +include Plugin.S (** implementation of Log.S for E-ACSL *) + +module Check: Parameter_sig.Bool +module Run: Parameter_sig.Bool +module Valid: Parameter_sig.Bool +module Prepare: Parameter_sig.Bool +module Gmp_only: Parameter_sig.Bool +module Full_mmodel: Parameter_sig.Bool +module Project_name: Parameter_sig.String +module Builtins: Parameter_sig.String_set +module Temporal_validity: Parameter_sig.Bool +module Validate_format_strings: Parameter_sig.Bool +module Replace_libc_functions: Parameter_sig.Bool + +module Functions: Parameter_sig.Kernel_function_set +module Instrument: Parameter_sig.Kernel_function_set + +val parameter_states: State.t list + +val must_visit: unit -> bool + +val dkey_analysis: category +val dkey_dup: category +val dkey_translation: category +val dkey_typing: category + +(* +Local Variables: +compile-command: "make" +End: +*) diff --git a/src/plugins/e-acsl/src/project_initializer/dup_functions.ml b/src/plugins/e-acsl/src/project_initializer/dup_functions.ml new file mode 100644 index 0000000000000000000000000000000000000000..205fac4cd6d951a9d8b394b1847cf03e1eb871fa --- /dev/null +++ b/src/plugins/e-acsl/src/project_initializer/dup_functions.ml @@ -0,0 +1,428 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C's E-ACSL plug-in. *) +(* *) +(* Copyright (C) 2012-2018 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +open Cil_types + +let dkey = Options.dkey_dup + +(* ********************************************************************** *) +(* Environment *) +(* ********************************************************************** *) + +let fct_tbl: unit Kernel_function.Hashtbl.t = Kernel_function.Hashtbl.create 7 + +let actions = Queue.create () + +module Global: sig + val add_logic_info: logic_info -> unit + val mem_logic_info: logic_info -> bool + val reset: unit -> unit +end = struct + + let tbl = Cil_datatype.Logic_info.Hashtbl.create 7 + let add_logic_info x = Cil_datatype.Logic_info.Hashtbl.add tbl x () + let mem_logic_info x = Cil_datatype.Logic_info.Hashtbl.mem tbl x + let reset () = Cil_datatype.Logic_info.Hashtbl.clear tbl + +end + +let reset () = + Kernel_function.Hashtbl.clear fct_tbl; + Global.reset (); + Queue.clear actions + +(* ********************************************************************** *) +(* Duplicating functions *) +(* ********************************************************************** *) + +let dup_funspec tbl bhv spec = + (* Options.feedback "DUP SPEC %a" Cil.d_funspec spec;*) + let o = object + inherit Cil.genericCilVisitor bhv + + val already_visited = Cil_datatype.Logic_var.Hashtbl.create 7 + + method !vlogic_info_use li = + if Global.mem_logic_info li then + Cil.ChangeDoChildrenPost + ({ li with l_var_info = li.l_var_info } (* force a copy *), + Visitor_behavior.Get.logic_info bhv) + else + Cil.JustCopy + + method !vterm_offset _ = + Cil.DoChildrenPost + (function + (* no way to directly visit fieldinfo and model_info uses *) + | TField(fi, off) -> TField(Visitor_behavior.Get.fieldinfo bhv fi, off) + | TModel(mi, off) -> TModel(Visitor_behavior.Get.model_info bhv mi, off) + | off -> off) + + method !vlogic_var_use orig_lvi = + match orig_lvi.lv_origin with + | None -> + Cil.JustCopy + | Some vi -> + try + let new_lvi = + Cil_datatype.Logic_var.Hashtbl.find already_visited orig_lvi + in + Cil.ChangeTo new_lvi + with Not_found -> + Cil.ChangeDoChildrenPost + ({ orig_lvi with lv_id = orig_lvi.lv_id } (* force a copy *), + fun lvi -> + (* using [Visitor_behavior.Get.logic_var bhv lvi] is correct only because the + lv_id used to compare the lvi does not change between the + original one and this copy *) + try + let new_vi = Cil_datatype.Varinfo.Hashtbl.find tbl vi in + Cil_datatype.Logic_var.Hashtbl.add + already_visited orig_lvi lvi; + lvi.lv_id <- new_vi.vid; + lvi.lv_name <- new_vi.vname; + lvi.lv_origin <- Some new_vi; + new_vi.vlogic_var_assoc <- Some lvi; + lvi + with Not_found -> + assert vi.vglob; + Visitor_behavior.Get.logic_var bhv lvi) + + method !videntified_term _ = + Cil.DoChildrenPost Logic_const.refresh_identified_term + + method !videntified_predicate _ = + Cil.DoChildrenPost Logic_const.refresh_predicate + end in + Cil.visitCilFunspec o spec + +let dup_fundec loc spec bhv sound_verdict_vi kf vi new_vi = + new_vi.vdefined <- true; + let formals = Kernel_function.get_formals kf in + let mk_formal vi = + let name = + if vi.vname = "" then + (* unnamed formal parameter: must generate a fresh name since a fundec + cannot have unnamed formals (see bts #2303). *) + Varname.get + ~scope:Varname.Function + (Functions.RTL.mk_gen_name "unamed_formal") + else + vi.vname + in + Cil.copyVarinfo vi name + in + let new_formals = List.map mk_formal formals in + let res = + let ty = Kernel_function.get_return_type kf in + if Cil.isVoidType ty then None + else Some (Cil.makeVarinfo false false ~referenced:true "__retres" ty) + in + let return = + Cil.mkStmt ~valid_sid:true + (Return(Extlib.opt_map (Cil.evar ~loc) res, loc)) + in + let stmts = + let l = + [ Cil.mkStmtOneInstr ~valid_sid:true + (Call(Extlib.opt_map Cil.var res, + Cil.evar ~loc vi, + List.map (Cil.evar ~loc) new_formals, + loc)); + return ] + in + if Functions.instrument kf then + l + else + (* set the 'unsound_verdict' variable to 'false' whenever required *) + let unsound = + Cil.mkStmtOneInstr ~valid_sid:true + (Set((Var sound_verdict_vi, NoOffset), Cil.zero ~loc, loc)) + in + unsound :: l + in + let locals = match res with None -> [] | Some r -> [ r ] in + let body = Cil.mkBlock stmts in + body.blocals <- locals; + let tbl = Cil_datatype.Varinfo.Hashtbl.create 7 in + List.iter2 (Cil_datatype.Varinfo.Hashtbl.add tbl) formals new_formals; + let new_spec = dup_funspec tbl bhv spec in + { svar = new_vi; + sformals = new_formals; + slocals = locals; + smaxid = List.length new_formals; + sbody = body; + smaxstmtid = None; + sallstmts = []; + sspec = new_spec } + +let dup_global loc actions spec bhv sound_verdict_vi kf vi new_vi = + let name = vi.vname in + Options.feedback ~dkey ~level:2 "entering in function %s" name; + let fundec = dup_fundec loc spec bhv sound_verdict_vi kf vi new_vi in + let fct = Definition(fundec, loc) in + let new_spec = fundec.sspec in + let new_kf = { fundec = fct; spec = new_spec } in + Queue.add (fun () -> + Kernel_function.Hashtbl.add fct_tbl new_kf (); + Globals.Functions.register new_kf; + Globals.Functions.replace_by_definition new_spec fundec loc; + Annotations.register_funspec new_kf) + actions; + Options.feedback ~dkey ~level:2 "function %s" name; + (* remove the specs attached to the previous kf iff it is a definition: + it is necessary to keep stable the number of annotations in order to get + [Keep_status] working fine. *) + let kf = Visitor_behavior.Get.kernel_function bhv kf in + if Kernel_function.is_definition kf then begin + Queue.add + (fun () -> + let bhvs = + Annotations.fold_behaviors (fun e b acc -> (e, b) :: acc) kf [] + in + List.iter + (fun (e, b) -> Annotations.remove_behavior ~force:true e kf b) + bhvs; + Annotations.iter_decreases + (fun e _ -> Annotations.remove_decreases e kf) + kf; + Annotations.iter_terminates + (fun e _ -> Annotations.remove_terminates e kf) + kf; + Annotations.iter_complete + (fun e l -> Annotations.remove_complete e kf l) + kf; + Annotations.iter_disjoint + (fun e l -> Annotations.remove_disjoint e kf l) + kf) + actions + end; + GFun(fundec, loc), GFunDecl(new_spec, new_vi, loc) + +(* ********************************************************************** *) +(* Visitor *) +(* ********************************************************************** *) + +type position = Before_gmp | Gmpz | After_gmp | Memory_model | Code + +class dup_functions_visitor prj = object (self) + inherit Visitor.frama_c_copy prj + + val unduplicable_functions = + let white_list = + [ "__builtin_va_arg"; + "__builtin_va_end"; + "__builtin_va_start"; + "__builtin_va_copy" ] + in + List.fold_left + (fun acc s -> Datatype.String.Set.add s acc) + Datatype.String.Set.empty + white_list + + val fct_tbl = Cil_datatype.Varinfo.Hashtbl.create 7 + val mutable before_memory_model = Before_gmp + val mutable new_definitions: global list = [] + (* new definitions of the annotated functions which will contain the + translation of the E-ACSL contract *) + + val mutable sound_verdict_vi = + let name = Functions.RTL.mk_api_name "sound_verdict" in + let vi = Project.on prj (Cil.makeGlobalVar name) Cil.intType in + vi.vstorage <- Extern; + vi.vreferenced <- true; + vi + + method private before_memory_model = match before_memory_model with + | Before_gmp | Gmpz | After_gmp -> true + | Memory_model | Code -> false + + method private insert_libc l = + match new_definitions with + | [] -> l + | _ :: _ -> + (* add the generated definitions of libc at the end of [l]. This way, + we are sure that they have access to all of it (in particular, the + memory model, GMP and the soundness variable). + + Also add the [__e_acsl_sound_verdict] variable at the beginning *) + let res = + GVarDecl(sound_verdict_vi, Cil_datatype.Location.unknown) + :: l + @ new_definitions in + new_definitions <- []; + res + + method private next () = + match before_memory_model with + | Before_gmp -> () + | Gmpz -> before_memory_model <- After_gmp + | After_gmp -> () + | Memory_model -> before_memory_model <- Code + | Code -> () + + method !vlogic_info_decl li = + Global.add_logic_info li; + Cil.JustCopy + + method !vvrbl vi = + try + let new_vi = Cil_datatype.Varinfo.Hashtbl.find fct_tbl vi in + Cil.ChangeTo new_vi + with Not_found -> + Cil.JustCopy + + method private is_unvariadic_function vi = + match Cil.unrollType vi.vtype with + | TFun(_, _, variadic, _) -> not variadic + | _ -> false + + method !vglob_aux = function + | GFunDecl(_, vi, loc) | GFun({ svar = vi }, loc) + when (* duplicate a function iff: *) + not (Cil_datatype.Varinfo.Hashtbl.mem fct_tbl vi) + (* it is not already duplicated *) + && not (Datatype.String.Set.mem vi.vname unduplicable_functions) + (* it is duplicable *) + && self#is_unvariadic_function vi (* it is not a variadic function *) + && not (Misc.is_library_loc loc) (* it is not in the E-ACSL's RTL *) + && not (Cil.is_builtin vi) (* it is not a Frama-C built-in *) + && + (let kf = + try Globals.Functions.get vi with Not_found -> assert false + in + not (Functions.instrument kf) + (* either explicitely listed as to be not instrumented *) + || + (* or: *) + (not (Cil.is_empty_funspec + (Annotations.funspec ~populate:false + (Extlib.the self#current_kf))) + (* it has a function contract *) + && Functions.check kf + (* its annotations must be monitored *))) + -> + self#next (); + let name = Functions.RTL.mk_gen_name vi.vname in + let new_vi = + Project.on prj (Cil.makeGlobalVar name) vi.vtype + in + Cil_datatype.Varinfo.Hashtbl.add fct_tbl vi new_vi; + Cil.DoChildrenPost + (fun l -> match l with + | [ GVarDecl(vi, _) | GFunDecl(_, vi, _) | GFun({ svar = vi }, _) as g ] + -> + (match g with + | GFunDecl _ -> + if not (Kernel_function.is_definition (Extlib.the self#current_kf)) + && vi.vname <> "malloc" && vi.vname <> "free" + then + Options.warning "@[annotating undefined function `%a':@ \ +the generated program may miss memory instrumentation@ \ +if there are memory-related annotations.@]" + Printer.pp_varinfo vi + | GFun _ -> () + | _ -> assert false); + let tmp = vi.vname in + if tmp = Kernel.MainFunction.get () then begin + (* the new function becomes the new main: simply swap the name of both + functions *) + vi.vname <- new_vi.vname; + new_vi.vname <- tmp + end; + let kf = + try + Globals.Functions.get (Visitor_behavior.Get_orig.varinfo self#behavior vi) + with Not_found -> + Options.fatal + "unknown function `%s' while trying to duplicate it" + vi.vname + in + let spec = Annotations.funspec ~populate:false kf in + let vi_bhv = Visitor_behavior.Get.varinfo self#behavior vi in + let new_g, new_decl = + dup_global + loc + self#get_filling_actions + spec + self#behavior + sound_verdict_vi + kf + vi_bhv + new_vi + in + (* postpone the introduction of the new function definition to the + end *) + new_definitions <- new_g :: new_definitions; + (* put the declaration before the original function in order to solve + issue with recursive functions *) + [ new_decl; g ] + | _ -> assert false) + | GVarDecl(_, loc) | GFunDecl(_, _, loc) | GFun(_, loc) + when Misc.is_library_loc loc -> + (match before_memory_model with + | Before_gmp -> before_memory_model <- Gmpz + | Gmpz | Memory_model -> () + | After_gmp -> before_memory_model <- Memory_model + | Code -> () (* still processing the GMP and memory model headers, + but reading some libc code *)); + Cil.JustCopy + | GVarDecl(vi, _) | GFunDecl(_, vi, _) | GFun({ svar = vi }, _) + when Cil.is_builtin vi -> + self#next (); + Cil.JustCopy + | _ -> + self#next (); + Cil.DoChildren + + method !vfile _ = + Cil.DoChildrenPost + (fun f -> + match new_definitions with + | [] -> f + | _ :: _ -> + (* required by the few cases where there is no global tagged as + [Code] in the file. *) + f.globals <- self#insert_libc f.globals; + f) + + initializer + Project.copy ~selection:(Parameter_state.get_selection ()) prj; + reset () + +end + +let dup () = + Options.feedback ~level:2 "duplicating annotated functions"; + let prj = + File.create_project_from_visitor + "e_acsl_dup_functions" + (new dup_functions_visitor) + in + Queue.iter (fun f -> f ()) actions; + prj + +(* +Local Variables: +compile-command: "make" +End: +*) diff --git a/src/plugins/e-acsl/src/project_initializer/dup_functions.mli b/src/plugins/e-acsl/src/project_initializer/dup_functions.mli new file mode 100644 index 0000000000000000000000000000000000000000..fa893ceabbea6f91bbe773fde4c3c321ebfd0524 --- /dev/null +++ b/src/plugins/e-acsl/src/project_initializer/dup_functions.mli @@ -0,0 +1,29 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C's E-ACSL plug-in. *) +(* *) +(* Copyright (C) 2012-2018 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +val dup: unit -> Project.t + +(* +Local Variables: +compile-command: "make" +End: +*) diff --git a/src/plugins/e-acsl/src/project_initializer/keep_status.ml b/src/plugins/e-acsl/src/project_initializer/keep_status.ml new file mode 100644 index 0000000000000000000000000000000000000000..cb76ec3fcc5a2f673d3a6b2a63ca37dca8ab2635 --- /dev/null +++ b/src/plugins/e-acsl/src/project_initializer/keep_status.ml @@ -0,0 +1,152 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C's E-ACSL plug-in. *) +(* *) +(* Copyright (C) 2012-2018 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* E-ACSL needs to access to the property status of every property (in + particular for the option -e-acsl-valid). However, the necessary elements for + building a property are copied/modified several times from the original + project to the final project and the property statuses are destroyed when + creating the intermediate projects; so there is no easy way to access to + property statuses from the final project. + + This module aims at solving this issue by providing an access to property + statuses from the final project. To work properly, it requires to visit every + property during the final visit in the very same order than during the AST + preparation visit. Indeed, for each function, it associates to each + property an unique integer corresponding to its visit ordering. *) + +(* the kind is only used for a few additional consistency checks between [push] + and [must_translate]*) +type kind = + | K_Assert + | K_Invariant + | K_Variant + | K_StmtSpec + | K_Allocation + | K_Assigns + | K_Decreases + | K_Terminates + | K_Complete + | K_Disjoint + | K_Requires + | K_Ensures + +let pretty_kind fmt k = + Format.fprintf fmt "%s" + (match k with + | K_Assert -> "assert" + | K_Invariant -> "invariant" + | K_Variant -> "variant" + | K_StmtSpec -> "stmtspec" + | K_Allocation -> "allocation" + | K_Assigns -> "assigns" + | K_Decreases -> "decreases" + | K_Terminates -> "terminates" + | K_Complete -> "complete" + | K_Disjoint -> "disjoint" + | K_Requires -> "requires" + | K_Ensures -> "ensures") + +(* information attached to every kernel_function containing an annotation *) +type kf_info = + { mutable cpt: int; (* counter building the relationship between [push] and + [must_translate *) + mutable statuses: (kind * bool) Datatype.Int.Map.t + (* map associating a property as an integer to its kind and status + ([true] = proved) *) } + +(* statuses for each function represented by its name (because the [kf] itself + changes from a project to another). *) +let keep_status + : kf_info Datatype.String.Hashtbl.t + = Datatype.String.Hashtbl.create 17 + +(* will contain the value of a few options from the original project + in order to safely use them from the final project. *) +let option_valid = ref false +let option_check = ref false + +let clear () = + Datatype.String.Hashtbl.clear keep_status; + option_valid := Options.Valid.get (); + option_check := Options.Check.get () + +let push kf kind ppt = +(* Options.feedback "PUSHING %a for %a" + pretty_kind kind + Kernel_function.pretty kf;*) + (* no registration when -e-acsl-check or -e-acsl-valid *) + if not (!option_check || !option_valid) then + let keep = + let open Property_status in + match get ppt with + | Never_tried + | Inconsistent _ + | Best ((False_if_reachable | False_and_reachable | Dont_know), _) -> + true + | Best (True, _) -> + false + in + let status = kind, keep in + let name = Kernel_function.get_name kf in + try + let info = Datatype.String.Hashtbl.find keep_status name in + info.cpt <- info.cpt + 1; + info.statuses <- Datatype.Int.Map.add info.cpt status info.statuses + with Not_found -> + let info = { cpt = 1; statuses = Datatype.Int.Map.singleton 1 status } in + Datatype.String.Hashtbl.add keep_status name info + +let before_translation () = + (* reset all counters *) + Datatype.String.Hashtbl.iter (fun _ info -> info.cpt <- 0) keep_status + +let must_translate kf kind = +(* Options.feedback "GETTING %a for %a" + pretty_kind kind + Kernel_function.pretty kf;*) + !option_check + || + !option_valid + || + (* function contracts have been moved from the original function to its + duplicate by [Dup_function] but they are still associated to the original + function here *) + let name = Functions.RTL.get_original_name kf in + try + let info = + try Datatype.String.Hashtbl.find keep_status name + with Not_found -> + Options.fatal "[keep_status] unbound function" Datatype.String.pretty kf + in + info.cpt <- info.cpt + 1; + let kind', keep = + try Datatype.Int.Map.find info.cpt info.statuses + with Not_found -> + Options.fatal "[keep_status] unbound annotation (id %d)" info.cpt + in + (* check kind consistency in order to detect more abnormal behaviors *) + if kind <> kind' then + Options.fatal "[keep_status] incorrect kind '%a' (expected: '%a')" + pretty_kind kind + pretty_kind kind'; + keep + with Not_found -> true diff --git a/src/plugins/e-acsl/src/project_initializer/keep_status.mli b/src/plugins/e-acsl/src/project_initializer/keep_status.mli new file mode 100644 index 0000000000000000000000000000000000000000..fb780c54aa0870d6c3f11c1286090f8a5d8f3c7d --- /dev/null +++ b/src/plugins/e-acsl/src/project_initializer/keep_status.mli @@ -0,0 +1,54 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C's E-ACSL plug-in. *) +(* *) +(* Copyright (C) 2012-2018 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(** Make the property statuses of the initial project accessible when + doing the main translation *) + +type kind = + | K_Assert + | K_Invariant + | K_Variant + | K_StmtSpec + | K_Allocation + | K_Assigns + | K_Decreases + | K_Terminates (* TODO: should be removed: not part of the E-ACSL subset *) + | K_Complete + | K_Disjoint + | K_Requires + | K_Ensures + +val clear: unit -> unit +(** to be called before any program transformation *) + +val push: Kernel_function.t -> kind -> Property.t -> unit +(** store the given property of the given kind for the given function *) + +val before_translation: unit -> unit +(** to be called just before the main translation *) + +val must_translate: Kernel_function.t -> kind -> bool +(** To be called just before transforming a property of the given kind for the + given function. + VERY IMPORTANT: the property of the n-th call to this function exactly + correspond to the n-th pushed property (see {!push}). + @return true if and only if the translation must occur. *) diff --git a/src/plugins/e-acsl/src/project_initializer/prepare_ast.ml b/src/plugins/e-acsl/src/project_initializer/prepare_ast.ml new file mode 100644 index 0000000000000000000000000000000000000000..602461c6e5816c00cf7d23bbcb5f019f6874b34f --- /dev/null +++ b/src/plugins/e-acsl/src/project_initializer/prepare_ast.ml @@ -0,0 +1,227 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C's E-ACSL plug-in. *) +(* *) +(* Copyright (C) 2012-2018 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +open Cil_types + +exception Alignment_error of string +let align_error s = raise (Alignment_error s) + +(* Returns true if the list of attributes [attrs] contains an [align] + * attribute of [algn] or greater. Returns false otherwise. + * Throws an exception if + * - [attrs] contains several [align] attributes specifying different + * alignment + * - [attrs] has a single align attribute with a value which is less than [algn] *) +let sufficiently_aligned attrs algn = + let alignment = List.fold_left (fun acc attr -> + match attr with + | Attr("align", [AInt i]) -> + let alignment = Integer.to_int i in + if acc <> 0 && acc <> alignment then + (* Multiple align attributes with different values *) + align_error "Multiple alignment attributes" + else if alignment < algn then + (* If there is an alignment attribute it should be greater + * or equal to [algn] *) + align_error "Insufficient alignment" + else + alignment + | Attr("align", _) -> + (* Align attribute with an argument other than a single number, + should not happen really *) + assert false + | _ -> acc + ) 0 attrs in alignment > 0 + +(* Given the type and the list of attributes of [varinfo] ([fieldinfo]) return + * true if that [varinfo] ([fieldinfo]) requires to be aligned at the boundary + * of [algn] (i.e., less than [algn] bytes and has no alignment attribute *) +let require_alignment typ attrs algn = + Cil.bitsSizeOf typ < algn*8 && not (sufficiently_aligned attrs algn) + +class prepare_visitor prj = object (self) + inherit Visitor.frama_c_copy prj + + (* Add align attributes to local variables (required by temporal analysis) *) + method !vblock _ = + if Options.Temporal_validity.get () then + Cil.DoChildrenPost (fun blk -> + List.iter (fun vi -> + (* 4 bytes alignment is required to allow sufficient space for storage + of 32-bit timestamps in a 1:1 shadow. *) + if require_alignment vi.vtype vi.vattr 4; then begin + vi.vattr <- Attr("aligned",[AInt Integer.four]) :: vi.vattr + end) + blk.blocals; + blk) + else + Cil.DoChildren + + (* IMPORTANT: for keeping property statuses, we must preserve the ordering of + translation, see function [Translate.translate_pre_spec] and + [Translate.translate_post_spec]: be careful when modifying it. *) + + method private push_pre_spec s = + let kf = Extlib.the self#current_kf in + let kinstr = self#current_kinstr in + let open Keep_status in + Extlib.may + (fun v -> push kf K_Decreases (Property.ip_of_decreases kf kinstr v)) + s.spec_variant; + Extlib.may + (fun t -> push kf K_Terminates (Property.ip_of_terminates kf kinstr t)) + s.spec_terminates; + List.iter + (fun l -> + push kf K_Complete (Property.ip_of_complete kf kinstr ~active:[] l)) + s.spec_complete_behaviors; + List.iter + (fun l -> + push kf K_Disjoint (Property.ip_of_disjoint kf kinstr ~active:[] l)) + s.spec_disjoint_behaviors; + List.iter + (fun b -> + List.iter + (fun p -> push kf K_Requires (Property.ip_of_requires kf kinstr b p)) + b.b_requires) + s.spec_behavior + + method private push_post_spec spec = + let do_behavior b = + let kf = Extlib.the self#current_kf in + let ki = match self#current_stmt with + | None -> Kglobal + | Some stmt -> Kstmt stmt + in + let open Keep_status in + Extlib.may + (push kf K_Assigns) + (Property.ip_of_assigns + kf + ki + (Property.Id_contract (Datatype.String.Set.empty (* TODO *), b)) + b.b_assigns); + List.iter + (fun p -> push kf K_Ensures (Property.ip_of_ensures kf ki b p)) + b.b_post_cond + in + (* fix ordering of behaviors' iterations *) + let bhvs = + List.sort + (fun b1 b2 -> String.compare b1.b_name b2.b_name) + spec.spec_behavior + in + List.iter do_behavior bhvs + + method private push_pre_code_annot a = + let kf = Extlib.the self#current_kf in + let stmt = Extlib.the self#current_stmt in + let push_single k a = + Keep_status.push kf k (Property.ip_of_code_annot_single kf stmt a) + in + let open Keep_status in + match a.annot_content with + | AAssert _ -> push_single K_Assert a + | AStmtSpec(_ (* TODO *), s) -> self#push_pre_spec s + | AInvariant _ -> push_single K_Invariant a + | AVariant v -> + push kf K_Variant (Property.ip_of_decreases kf (Kstmt stmt) v) + | AAssigns _ -> + (* TODO: should be a postcondition, but considered as a unhandled + precondition in translate.ml right now; and we need to preserve the + same ordering *) + Extlib.may + (push kf K_Assigns) + (Property.ip_assigns_of_code_annot kf (Kstmt stmt) a) + | AAllocation(_ (* TODO *), alloc) -> + Extlib.may + (push kf K_Allocation) + (Property.ip_of_allocation kf (Kstmt stmt) (Property.Id_loop a) alloc) + | APragma _ -> () (* not yet translated *) + | AExtended _ -> () (* never translate extensions *) + + method private push_post_code_annot a = match a.annot_content with + | AStmtSpec(_ (* TODO *), s) -> self#push_post_spec s + | AAssert _ + | AInvariant _ + | AVariant _ + | AAssigns _ + | AAllocation _ + | APragma _ + | AExtended _ -> () + + (* Move variable declared in the body of a switch statement to the outer + scope *) + method !vstmt_aux init_stmt = + Annotations.iter_code_annot + (fun _ a -> self#push_pre_code_annot a) + init_stmt; + Cil.DoChildrenPost + (fun stmt -> + Annotations.iter_code_annot + (fun _ a -> self#push_post_code_annot a) + init_stmt; + match stmt.skind with + | Switch(_,sw_blk,_,_) -> + let new_blk = Cil.mkBlock [ stmt ] in + let new_stmt = Cil.mkStmt (Block new_blk) in + new_blk.blocals <- sw_blk.blocals; + sw_blk.blocals <- []; + new_stmt + | _ -> stmt) + + method private is_unvariadic_function vi = + match Cil.unrollType vi.vtype with + | TFun(_, _, variadic, _) -> not variadic + | _ -> false + + method !vglob_aux = function + | GVarDecl(vi, loc) | GFunDecl(_, vi, loc) | GFun({ svar = vi }, loc) + when self#is_unvariadic_function vi + && not (Misc.is_library_loc loc) + && not (Cil.is_builtin vi) + -> + let kf = Extlib.the self#current_kf in + let s = Annotations.funspec ~populate:false kf in + Cil.DoChildrenPost + (fun f -> + self#push_pre_spec s; + self#push_post_spec s; + f) + | _ -> + Cil.DoChildren + + initializer Project.copy ~selection:(Parameter_state.get_selection ()) prj + + end + +let prepare () = + Options.feedback ~level:2 "prepare AST for E-ACSL transformations"; + File.create_project_from_visitor + "e_acsl_prepare_ast" + (new prepare_visitor) + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff --git a/src/plugins/e-acsl/src/project_initializer/prepare_ast.mli b/src/plugins/e-acsl/src/project_initializer/prepare_ast.mli new file mode 100644 index 0000000000000000000000000000000000000000..f46a04474c2952413cc5d1c6b3821d2b45b97ab3 --- /dev/null +++ b/src/plugins/e-acsl/src/project_initializer/prepare_ast.mli @@ -0,0 +1,36 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C's E-ACSL plug-in. *) +(* *) +(* Copyright (C) 2012-2018 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(** Prepare AST for E-ACSL generation. + + So for this module performs two tasks: + - move declarations of variables declared in the bodies of switch + statements to upper scopes; + - store what is necessary to translate in [Keep_status]. *) + +val prepare: unit -> Project.t + +(* +Local Variables: +compile-command: "make -C ../.." +End: +*) diff --git a/src/plugins/e-acsl/tests/arith/arith.i b/src/plugins/e-acsl/tests/arith/arith.i new file mode 100644 index 0000000000000000000000000000000000000000..df97877fb148968c52cd69013790c311dcf6160b --- /dev/null +++ b/src/plugins/e-acsl/tests/arith/arith.i @@ -0,0 +1,39 @@ +/* run.config + COMMENT: arithmetic operations +*/ + +int main(void) { + int x = -3; + int y = 2; + long z = 2L; + + /*@ assert -3 == x; */ ; + /*@ assert x == -3; */ ; + /*@ assert 0 != ~0; */ ; + + /*@ assert x+1 == -2; */ ; + /*@ assert x-1 == -4; */ ; + /*@ assert x*3 == -9; */ ; + /*@ assert x/3 == -1; */ ; + /*@ assert 0xffffffffffffffffffffff/0xffffffffffffffffffffff == 1; */ ; + /*@ assert x % 2 == -1; */ ; + /*@ assert -3 % -2 == -1; */ ; + /*@ assert 3 % -2 == 1; */ ; + + /*@ assert x * 2 + (3 + y) - 4 + (x - y) == -10; */ ; + + /*@ assert (0 == 1) == !(0 == 0); */ ; + /*@ assert (0 <= -1) == (0 > 0); */ ; + /*@ assert (0 >= -1) == (0 <= 0); */ ; + /*@ assert (0 != 1) == !(0 != 0); */ ; + + /*@ assert 0 == !1; */ ; + /*@ assert 4 / y == 2; */ // non trivial division added when fixing bts #751 + + // example from the JFLA'15 paper (but for a 64-bit architecture) + /*@ assert 1 + ((z+1) / (y-123456789123456789)) == 1; */ + + /*@ assert 1 - x == -x + 1; */ // test GIT issue #37 + + return 0; +} diff --git a/src/plugins/e-acsl/tests/arith/array.i b/src/plugins/e-acsl/tests/arith/array.i new file mode 100644 index 0000000000000000000000000000000000000000..6211cf0950134f6a9c05becab68884473392be21 --- /dev/null +++ b/src/plugins/e-acsl/tests/arith/array.i @@ -0,0 +1,17 @@ +/* run.config_ci + COMMENT: arrays + STDOPT: #"-slevel 5" +*/ + +int T1[3],T2[4]; + +int main(void) { + + for(int i = 0; i < 3; i++) T1[i] = i; + for(int i = 0; i < 4; i++) T2[i] = 2*i; + + /*@ assert T1[0] == T2[0]; */ + /*@ assert T1[1] != T2[1]; */ + + return 0; +} diff --git a/src/plugins/e-acsl/tests/arith/at.i b/src/plugins/e-acsl/tests/arith/at.i new file mode 100644 index 0000000000000000000000000000000000000000..fd3830e91d0bb02db49c6cef81caff9f8c600c57 --- /dev/null +++ b/src/plugins/e-acsl/tests/arith/at.i @@ -0,0 +1,56 @@ +/* run.config + COMMENT: \at +*/ + +int A = 0; + +/*@ ensures \at(A,Post) == 3; */ +void f(void) { + A = 1; + F: A = 2; + /*@ assert \at(A,Pre) == 0; */ + /*@ assert \at(A,F) == 1; */ + /*@ assert \at(A,Here) == 2; */ + /*@ assert \at(\at(A,Pre),F) == 0; */ + A = 3; +} + +void g(int *p, int *q) { + *p = 0; + *(p+1) = 1; + *q = 0; + L1: *p = 2; + *(p+1) = 3; + *q = 1; + L2: A = 4; + /*@ assert (\at(*(p+\at(*q,L1)),L2) == 2); */ + L3: + /*@ assert (\at(*(p+\at(*q,L1)),Here) == 2); */ + + // /*@ assert (\at(*(p+\at(*q,L1)),L3) == 2); */ // doesn't work yet + // /*@ assert (\at(*(p+\at(*q,L2)),L1)) == 1; */ + return ; +} + +/*@ ensures \result == x; */ +int h(int x) { return x; } + +int main(void) { + + int x; + + x = h(0); + L: /*@ assert x == 0; */ x = 1; + x = 2; + + f(); + + /*@ assert \at(x,L) == 0; */ + /*@ assert \at(x+1,L) == 1; */ + /*@ assert \at(x,L)+1 == 1; */ + + int t[2]; + g(t,&x); + + return 0; +} diff --git a/src/plugins/e-acsl/tests/arith/at_on-purely-logic-variables.c b/src/plugins/e-acsl/tests/arith/at_on-purely-logic-variables.c new file mode 100644 index 0000000000000000000000000000000000000000..a289de1d5a1c02e97bd12f1f5205a24c93639039 --- /dev/null +++ b/src/plugins/e-acsl/tests/arith/at_on-purely-logic-variables.c @@ -0,0 +1,69 @@ +/* run.config + COMMENT: \at on purely logic variables + COMMENT: +*/ + +/*@ ensures \forall integer n; 1 < n <= 3 ==> + \old(t[n] == 12) && \old(t[n - 1] > 5); + ensures \let m = 4; \old(t[m] == -4) && \old(t[m - 4]) == 9; */ +void f(int *t) {} + +void g() { + int m; + m = 8; + Q: ; + m = 10; + /*@ assert \exists integer w; 3 <= w < 6 && \at(m + w == 12, Q); */ ; +} + +int main(void) { + int n; + n = 7; + L: ; + n = 9; + K: ; + n = 666; + + // Predicates: + /*@ assert \let i = 3; \at(n + i == 10, L); */ ; + /*@ assert \exists integer j; 2 <= j < 5 && \at(n + j == 11, L); */ ; + /*@ assert + \let k = -7; + \exists integer u; 9 <= u < 21 && + \forall integer v; -5 < v <= 6 ==> + \at((u > 0 ? n + k : u + v) > 0, K); */ ; + + // Terms: + /*@ assert \let i = 3; \at(n + i, L) == 10; */ ; + unsigned int m = 3; + G: ; + m = -3; + /*@ assert \exists integer k; -9 < k < 0 && \at(m + k, G) == 0; */ ; + /*@ assert + \exists integer u; 9 <= u < 21 && + \forall integer v; -5 < v <= (u < 15 ? u + 6 : 3) ==> + \at(n + u + v > 0, K); */ ; + + // Function calls: + int t[5] = {9, 12, 12, 12, -4}; + f(t); + g(); + + // Name capturing + /*@ assert + \exists integer u; 10 <= u < 20 + && \exists integer v; -10 < v <= -5 + (\let u = -2; u) // another u + && \exists integer w; 100 < w <= 200 + && \at(n - u + + (\let u = 42; u) // yet another u + + v + w > 0, K); */ ; + + // Not yet: + /*@ assert + \exists integer j; 2 <= j < 10000000000000000 // too big => not_yet + && \at(n + j == 11, L); */ ; + /*@ assert \let i = n; // lv defined with C var => not_yet + \at(n + i == 10, L); */ ; + + return 0; +} \ No newline at end of file diff --git a/src/plugins/e-acsl/tests/arith/cast.i b/src/plugins/e-acsl/tests/arith/cast.i new file mode 100644 index 0000000000000000000000000000000000000000..910ca8b40d183e54f664850186174b06b5df7508 --- /dev/null +++ b/src/plugins/e-acsl/tests/arith/cast.i @@ -0,0 +1,25 @@ +/* run.config + COMMENT: cast +*/ + +int main(void) { + long x = 0; + int y = 0; + + /*@ assert (int)x == y; */ ; + /*@ assert x == (long)y; */ ; + + /*@ assert y == (int)0; */ ; // cast from integer to int + /*@ assert (unsigned int) y == (unsigned int)0; */ ; /* cast from integer + to unsigned int */ + + /*@ assert y != (int)0xfffffffffffffff; */ ; // cast from integer to int + /*@ assert (unsigned int) y != (unsigned int)0xfffffffffffffff; */ ; + /* cast from integer to unsigned int */ + + /* heterogeneous casts from/to integers */ + int t[2] = { 0, 1 }; + /*@ assert (float)x == t[(int)0.1]; */ + + return 0; +} diff --git a/src/plugins/e-acsl/tests/arith/comparison.i b/src/plugins/e-acsl/tests/arith/comparison.i new file mode 100644 index 0000000000000000000000000000000000000000..3c74cd1d2e52df0154ec185cd836d41e40e6971e --- /dev/null +++ b/src/plugins/e-acsl/tests/arith/comparison.i @@ -0,0 +1,29 @@ +/* run.config + COMMENT: comparison operators +*/ + +int main(void) { + int x = 0, y = 1; + /*@ assert x < y; */ + /*@ assert y > x; */ + /*@ assert x <= 0; */ + /*@ assert y >= 1; */ + char *s = "toto"; + /*@ assert s == s; */ + // waiting for clarification of semantics of ACSL's literal strings + // /*@ assert "toto" != "titi"; */ + /*@ assert 5 < 18; */ + /*@ assert 32 > 3; */ + /*@ assert 12 <= 13; */ + /*@ assert 123 >= 12; */ + /*@ assert 0xff == 0xff; */ + /*@ assert 1 != 2; */ + + /*@ assert -5 < 18; */ + /*@ assert 32 > -3; */ + /*@ assert -12 <= 13; */ + /*@ assert 123 >= -12; */ + /*@ assert -0xff == -(+0xff); */ + /*@ assert +1 != -2; */ + return 0; +} diff --git a/src/plugins/e-acsl/tests/arith/functions.c b/src/plugins/e-acsl/tests/arith/functions.c new file mode 100644 index 0000000000000000000000000000000000000000..9d0bc001ab61c0b89201f3c3ecffae481965c120 --- /dev/null +++ b/src/plugins/e-acsl/tests/arith/functions.c @@ -0,0 +1,73 @@ +/* run.config + COMMENT: logic functions without labels +*/ + +/*@ predicate p1(int x, int y) = x + y > 0; */ +/*@ predicate p2(integer x, integer y) = x + y > 0; */ + +/*@ logic integer f1(integer x, integer y) = x + y; */ + +// E-ACSL integer typing: +// types less than int are considered as int +/*@ logic char h_char(char c) = c; */ +/*@ logic short h_short(short s) = s; */ + +/*@ logic int g_hidden(int x) = x; */ +/*@ logic int g(int x) = g_hidden(x); */ + +struct mystruct { int k, l; }; +typedef struct mystruct mystruct; +/*@ logic mystruct t1(mystruct m) = m; */ +/*@ logic integer t2(mystruct m) = m.k + m.l; */ + +// To test function call in other clauses than assert: +/*@ predicate k_pred(integer x) = x > 0; */ +/*@ requires k_pred(x); */ +void k(int x) {} + +// To test non-interference with global inits: +int glob = 5; + +// To test that functions that are never called are not generated: +/*@ predicate never_called(int x) = x == x; */ + +/*@ logic double f2(double x) = (double)(1/x); */ /* handle in MR !226 */ + +// To test not_yet: +/*@ predicate p_notyet{L}(integer x) = x > 0; */ +/*@ logic integer f_notyet{L}(integer x) = x; */ + +int main (void) { + int x = 1, y = 2; + /*@ assert p1(x, y); */ ; + /*@ assert p2(3, 4); */ ; + /*@ assert p2(5, 99999999999999999999999999999); */ ; + + /*@ assert f1(x, y) == 3; */ ; + /*@ assert p2(x, f1(3, 4)); */ ; + /*@ assert f1(9, 99999999999999999999999999999) > 0; */ ; + /*@ assert f1(99999999999999999999999999999, + 99999999999999999999999999999) == + 199999999999999999999999999998; */ ; + + /*@ assert g(x) == x; */ ; + + char c = 'c'; + /*@ assert h_char(c) == c; */ ; + short s = 1; + /*@ assert h_short(s) == s; */ ; + + mystruct m; + m.k = 8; + m.l = 9; + /*@ assert t2(t1(m)) == 17; */ ; + + k(9); + + double d = 2.0; + /*@ assert f2(d) > 0; */ ; + + // not yet supported + /* /\*@ assert p_notyet(27); *\/ ; */ + /* /\*@ assert f_notyet(27) == 27; *\/ ; */ +} diff --git a/src/plugins/e-acsl/tests/arith/functions_rec.c b/src/plugins/e-acsl/tests/arith/functions_rec.c new file mode 100644 index 0000000000000000000000000000000000000000..8feb6f4e59dde504eb7ad2e4374c94867e39802a --- /dev/null +++ b/src/plugins/e-acsl/tests/arith/functions_rec.c @@ -0,0 +1,31 @@ +/* run.config_ci + COMMENT: recursive logic functions + STDOPT: +"-eva-ignore-recursive-calls" +*/ + +/*@ logic integer f1(integer n) = + n <= 0 ? 0 : f1(n - 1) + n; */ + +/*@ logic integer f2(integer n) = + n < 0 ? 1 : f2(n - 1)*f2(n - 2)/f2(n - 3); */ + +/*@ logic integer g(integer n) = 0; */ +/*@ logic integer f3(integer n) = + n > 0 ? g(n)*f3(n - 1) - 5 : g(n + 1); */ + +/*@ logic integer f4(integer n) = + n < 100 ? f4(n + 1) : + n < 0x7fffffffffffffffL ? 0x7fffffffffffffffL : + 6; */ + +int main (void) { + /*@ assert f1(0) == 0; */ ; + /*@ assert f1(1) == 1; */ ; + /*@ assert f1(100) == 5050; */ ; + + /*@ assert f2(7) == 1; */ ; + + /*@ assert f3(6) == -5; */ ; + + /*@ assert f4(9) > 0; */ ; +} diff --git a/src/plugins/e-acsl/tests/arith/integer_constant.i b/src/plugins/e-acsl/tests/arith/integer_constant.i new file mode 100644 index 0000000000000000000000000000000000000000..059857733e5890e34bfe6c0ca04848561833c1f5 --- /dev/null +++ b/src/plugins/e-acsl/tests/arith/integer_constant.i @@ -0,0 +1,14 @@ +/* run.config + COMMENT: integer constant + a stmt after the assertion +*/ +int main(void) { + int x; + /*@ assert 0 == 0; */ x = 0; + x++; /* prevent GCC's warning */ + /*@ assert 0 != 1; */ + /*@ assert 1152921504606846975 == 0xfffffffffffffff; */ + + /*@ assert 0xffffffffffffffffffffffffffffffff == 0xffffffffffffffffffffffffffffffff; */ + + return 0; +} diff --git a/src/plugins/e-acsl/tests/arith/let.c b/src/plugins/e-acsl/tests/arith/let.c new file mode 100644 index 0000000000000000000000000000000000000000..d7245e3560e00727a1bce494dc6021118ff213ed --- /dev/null +++ b/src/plugins/e-acsl/tests/arith/let.c @@ -0,0 +1,42 @@ +/* run.config + COMMENT: let binding +*/ + +int main(void) { + int n = -2; + /*@ assert \let u = n*n; u >= 0; */ ; + /*@ assert + \let u = n*n; + \let v = u + 1; u > 0; */ ; + + /*@ assert ((\let u = 1; u) + 1) == 2; */ ; + /*@ assert + \let u = 1; + (\let v = u + 1; v) == 2; */ ; + /*@ assert + \let u = 1; + (\let u = u + 1; u) == 2; */ ; + + long m = 0x7fffffffffffffffL; + /*@ assert (\let u = m; u*u) > m; */ ; + + char c = 'a'; + /*@ assert \let u = 'b'; c < u; */ ; + + float f = 1.0f; + /*@ assert \let u = f; u == f; */ ; + + int t[4] = {1,2,3,4}; + /*@ assert \let u = t + 1; 1 == 1; */ ; // testing warnings when using + // let on pointers/arrays + /*@ assert (\let u = t + 1; 1) == 1; */ ; // same but for terms + + struct {int x, y;} r = {1, 2}; + /*@ assert \let u = r; u.x + u.y == 3; */ ; + + union {int x; char *y;} s; + s.x = 5; + /*@ assert (\let u = s; u.x) > 0; */ ; + + return 0; +} diff --git a/src/plugins/e-acsl/tests/arith/longlong.i b/src/plugins/e-acsl/tests/arith/longlong.i new file mode 100644 index 0000000000000000000000000000000000000000..9be4c44511b20d6b432aee24fd7b92f026d3cd9f --- /dev/null +++ b/src/plugins/e-acsl/tests/arith/longlong.i @@ -0,0 +1,19 @@ +/* run.config_ci + COMMENT: upgrading longlong to GMP + STDOPT: +"-eva-ignore-recursive-calls" +*/ + +unsigned long long my_pow(unsigned int x, unsigned int n) { + int tmp; + if (n <= 1) return 1; + tmp = my_pow(x, n / 2); + tmp *= tmp; + if (n % 2 == 0) return tmp; + return x * tmp; +} + +int main(void) { + unsigned long long x = my_pow(2, 63); + /*@ assert (2 * x + 1) % 2 == 1; */ + return 0; +} diff --git a/src/plugins/e-acsl/tests/arith/not.i b/src/plugins/e-acsl/tests/arith/not.i new file mode 100644 index 0000000000000000000000000000000000000000..5fb8adfdcbe31eadefd28a156d15d5f260888e9d --- /dev/null +++ b/src/plugins/e-acsl/tests/arith/not.i @@ -0,0 +1,9 @@ +/* run.config + COMMENT: predicate [!p] +*/ +int main(void) { + int x = 0; + /*@ assert ! x; */ + if (x) /*@ assert x; */ ; + return 0; +} diff --git a/src/plugins/e-acsl/tests/arith/oracle_ci/arith.res.oracle b/src/plugins/e-acsl/tests/arith/oracle_ci/arith.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..38a48a7633bc1bd9ce121d8e99f5a422b09d05fa --- /dev/null +++ b/src/plugins/e-acsl/tests/arith/oracle_ci/arith.res.oracle @@ -0,0 +1,12 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". +[eva:alarm] tests/arith/arith.i:18: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/arith/arith.i:34: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/arith/arith.i:34: Warning: + signed overflow. assert -2147483648 ≤ 1 + __gen_e_acsl__7; +[eva:alarm] tests/arith/arith.i:34: Warning: + signed overflow. assert 1 + __gen_e_acsl__7 ≤ 2147483647; +[eva:alarm] tests/arith/arith.i:34: Warning: + function __e_acsl_assert: precondition got status unknown. diff --git a/src/plugins/e-acsl/tests/arith/oracle_ci/array.res.oracle b/src/plugins/e-acsl/tests/arith/oracle_ci/array.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..3e67d49ba6f489b956ea155d471c63c57a47de33 --- /dev/null +++ b/src/plugins/e-acsl/tests/arith/oracle_ci/array.res.oracle @@ -0,0 +1,8 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". +[eva:alarm] tests/arith/array.i:13: Warning: assertion got status unknown. +[eva:alarm] tests/arith/array.i:13: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/arith/array.i:14: Warning: assertion got status unknown. +[eva:alarm] tests/arith/array.i:14: Warning: + function __e_acsl_assert: precondition got status unknown. diff --git a/src/plugins/e-acsl/tests/arith/oracle_ci/at.res.oracle b/src/plugins/e-acsl/tests/arith/oracle_ci/at.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..1b2e6b52d1efc3ffa1b839a0d3fde9961a0799af --- /dev/null +++ b/src/plugins/e-acsl/tests/arith/oracle_ci/at.res.oracle @@ -0,0 +1,9 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". +[eva:alarm] tests/arith/at.i:12: Warning: assertion got status unknown. +[eva:alarm] tests/arith/at.i:14: Warning: assertion got status unknown. +[eva:alarm] tests/arith/at.i:48: Warning: assertion got status unknown. +[eva:alarm] tests/arith/at.i:49: Warning: assertion got status unknown. +[eva:alarm] tests/arith/at.i:50: Warning: assertion got status unknown. +[eva:alarm] tests/arith/at.i:26: Warning: assertion got status unknown. +[eva:alarm] tests/arith/at.i:28: Warning: assertion got status unknown. diff --git a/src/plugins/e-acsl/tests/arith/oracle_ci/at_on-purely-logic-variables.res.oracle b/src/plugins/e-acsl/tests/arith/oracle_ci/at_on-purely-logic-variables.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..41e3ddedf6b9a2429d3dd3af4bf79b709853a896 --- /dev/null +++ b/src/plugins/e-acsl/tests/arith/oracle_ci/at_on-purely-logic-variables.res.oracle @@ -0,0 +1,87 @@ +[e-acsl] beginning translation. +[e-acsl] tests/arith/at_on-purely-logic-variables.c:64: Warning: + E-ACSL construct + `\at on purely logic variables that needs to allocate too much memory (bigger than int_max bytes)' + is not yet supported. + Ignoring annotation. +[e-acsl] tests/arith/at_on-purely-logic-variables.c:65: Warning: + E-ACSL construct `\at with logic variable linked to C variable' + is not yet supported. + Ignoring annotation. +[e-acsl] translation done in project "e-acsl". +[eva:alarm] tests/arith/at_on-purely-logic-variables.c:28: Warning: + assertion got status unknown. +[eva:alarm] tests/arith/at_on-purely-logic-variables.c:29: Warning: + assertion got status unknown. +[eva:alarm] tests/arith/at_on-purely-logic-variables.c:29: Warning: + accessing uninitialized left-value. + assert \initialized(__gen_e_acsl_at_2 + (__gen_e_acsl_j - 2)); +[eva:alarm] tests/arith/at_on-purely-logic-variables.c:29: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/arith/at_on-purely-logic-variables.c:29: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/arith/at_on-purely-logic-variables.c:31: Warning: + assertion got status unknown. +[eva:alarm] tests/arith/at_on-purely-logic-variables.c:33: Warning: + accessing uninitialized left-value. + assert + \initialized(__gen_e_acsl_at_3 + + ((__gen_e_acsl_u - 9) * 11 + ((__gen_e_acsl_v - -5) - 1))); +[eva:alarm] tests/arith/at_on-purely-logic-variables.c:34: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/arith/at_on-purely-logic-variables.c:37: Warning: + assertion got status unknown. +[eva:alarm] tests/arith/at_on-purely-logic-variables.c:41: Warning: + assertion got status unknown. +[eva:alarm] tests/arith/at_on-purely-logic-variables.c:41: Warning: + accessing uninitialized left-value. + assert \initialized(__gen_e_acsl_at_5 + ((__gen_e_acsl_k_3 - -9) - 1)); +[eva:alarm] tests/arith/at_on-purely-logic-variables.c:41: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/arith/at_on-purely-logic-variables.c:41: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/arith/at_on-purely-logic-variables.c:43: Warning: + assertion got status unknown. +[eva:alarm] tests/arith/at_on-purely-logic-variables.c:44: Warning: + accessing uninitialized left-value. + assert + \initialized(__gen_e_acsl_at_6 + + ((__gen_e_acsl_u_3 - 9) * 32 + ((__gen_e_acsl_v_3 - -5) - 1))); +[eva:alarm] tests/arith/at_on-purely-logic-variables.c:45: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/arith/at_on-purely-logic-variables.c:7: Warning: + accessing uninitialized left-value. + assert \initialized(__gen_e_acsl_at + ((__gen_e_acsl_n - 1) - 1)); +[eva:alarm] tests/arith/at_on-purely-logic-variables.c:7: Warning: + accessing uninitialized left-value. + assert \initialized(__gen_e_acsl_at_2 + ((__gen_e_acsl_n - 1) - 1)); +[eva:alarm] tests/arith/at_on-purely-logic-variables.c:7: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/arith/at_on-purely-logic-variables.c:7: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/arith/at_on-purely-logic-variables.c:6: Warning: + function __gen_e_acsl_f: postcondition got status unknown. +[eva:alarm] tests/arith/at_on-purely-logic-variables.c:8: Warning: + function __gen_e_acsl_f: postcondition got status unknown. +[eva:alarm] tests/arith/at_on-purely-logic-variables.c:16: Warning: + assertion got status unknown. +[eva:alarm] tests/arith/at_on-purely-logic-variables.c:16: Warning: + accessing uninitialized left-value. + assert \initialized(__gen_e_acsl_at + (__gen_e_acsl_w - 3)); +[eva:alarm] tests/arith/at_on-purely-logic-variables.c:16: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/arith/at_on-purely-logic-variables.c:16: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/arith/at_on-purely-logic-variables.c:54: Warning: + assertion got status unknown. +[eva:alarm] tests/arith/at_on-purely-logic-variables.c:56: Warning: + accessing uninitialized left-value. + assert + \initialized(__gen_e_acsl_at_7 + + ((__gen_e_acsl_u_5 - 10) * 300 + + (((__gen_e_acsl_v_5 - -10) - 1) * 100 + + ((__gen_e_acsl_w - 100) - 1)))); +[eva:alarm] tests/arith/at_on-purely-logic-variables.c:63: Warning: + assertion got status unknown. +[eva:alarm] tests/arith/at_on-purely-logic-variables.c:65: Warning: + assertion got status unknown. diff --git a/src/plugins/e-acsl/tests/arith/oracle_ci/cast.res.oracle b/src/plugins/e-acsl/tests/arith/oracle_ci/cast.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..91932086457759e419ca8dfd663c8ec59a66b00d --- /dev/null +++ b/src/plugins/e-acsl/tests/arith/oracle_ci/cast.res.oracle @@ -0,0 +1,4 @@ +[e-acsl] beginning translation. +[e-acsl] tests/arith/cast.i:22: Warning: + E-ACSL construct `R to Int' is not yet supported. Ignoring annotation. +[e-acsl] translation done in project "e-acsl". diff --git a/src/plugins/e-acsl/tests/arith/oracle_ci/comparison.res.oracle b/src/plugins/e-acsl/tests/arith/oracle_ci/comparison.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..efd026311297e55d8fefb674326118e6ece88624 --- /dev/null +++ b/src/plugins/e-acsl/tests/arith/oracle_ci/comparison.res.oracle @@ -0,0 +1,2 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". diff --git a/src/plugins/e-acsl/tests/arith/oracle_ci/functions.res.oracle b/src/plugins/e-acsl/tests/arith/oracle_ci/functions.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..52987f8cb85873505e7b239e37b417394cf058af --- /dev/null +++ b/src/plugins/e-acsl/tests/arith/oracle_ci/functions.res.oracle @@ -0,0 +1,14 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". +[eva:alarm] tests/arith/functions.c:44: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/arith/functions.c:47: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/arith/functions.c:48: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/arith/functions.c:49: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/arith/functions.c:68: Warning: + non-finite double value. assert \is_finite(__gen_e_acsl__10); +[eva:alarm] tests/arith/functions.c:68: Warning: + function __e_acsl_assert: precondition got status unknown. diff --git a/src/plugins/e-acsl/tests/arith/oracle_ci/functions_rec.res.oracle b/src/plugins/e-acsl/tests/arith/oracle_ci/functions_rec.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..83535c9eff51d9ead77b1907e70cb8423c8cf4f6 --- /dev/null +++ b/src/plugins/e-acsl/tests/arith/oracle_ci/functions_rec.res.oracle @@ -0,0 +1,87 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". +[eva:alarm] tests/arith/functions_rec.c:22: Warning: + assertion got status unknown. +[eva:alarm] tests/arith/functions_rec.c:22: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/arith/functions_rec.c:23: Warning: + assertion got status unknown. +[eva:alarm] tests/arith/functions_rec.c:23: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/arith/functions_rec.c:24: Warning: + assertion got status unknown. +[eva] tests/arith/functions_rec.c:7: Warning: + recursive call during value analysis + of __gen_e_acsl_f1_2 (__gen_e_acsl_f1_2 <- __gen_e_acsl_f1_2 :: tests/arith/functions_rec.c:7 <- + __gen_e_acsl_f1 :: tests/arith/functions_rec.c:24 <- + main). + Assuming the call has no effect. The analysis will be unsound. +[eva:alarm] tests/arith/functions_rec.c:24: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/arith/functions_rec.c:26: Warning: + assertion got status unknown. +[eva] tests/arith/functions_rec.c:10: Warning: + recursive call during value analysis + of __gen_e_acsl_f2_2 (__gen_e_acsl_f2_2 <- __gen_e_acsl_f2_2 :: tests/arith/functions_rec.c:10 <- + __gen_e_acsl_f2 :: tests/arith/functions_rec.c:26 <- + main). + Assuming the call has no effect. The analysis will be unsound. +[eva] tests/arith/functions_rec.c:10: Warning: + recursive call during value analysis + of __gen_e_acsl_f2_2 (__gen_e_acsl_f2_2 <- __gen_e_acsl_f2_2 :: tests/arith/functions_rec.c:10 <- + __gen_e_acsl_f2 :: tests/arith/functions_rec.c:26 <- + main). + Assuming the call has no effect. The analysis will be unsound. +[eva] tests/arith/functions_rec.c:10: Warning: + recursive call during value analysis + of __gen_e_acsl_f2_2 (__gen_e_acsl_f2_2 <- __gen_e_acsl_f2_2 :: tests/arith/functions_rec.c:10 <- + __gen_e_acsl_f2 :: tests/arith/functions_rec.c:26 <- + main). + Assuming the call has no effect. The analysis will be unsound. +[eva:alarm] tests/arith/functions_rec.c:10: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/arith/functions_rec.c:10: Warning: + division by zero. assert __gen_e_acsl_f2_8 ≢ 0; +[eva:alarm] tests/arith/functions_rec.c:10: Warning: + signed overflow. + assert -2147483648 ≤ __gen_e_acsl_f2_4 * __gen_e_acsl_f2_6; +[eva:alarm] tests/arith/functions_rec.c:10: Warning: + signed overflow. assert __gen_e_acsl_f2_4 * __gen_e_acsl_f2_6 ≤ 2147483647; +[eva:alarm] tests/arith/functions_rec.c:10: Warning: + signed overflow. + assert + (int)(__gen_e_acsl_f2_4 * __gen_e_acsl_f2_6) / __gen_e_acsl_f2_8 ≤ + 2147483647; +[eva:alarm] tests/arith/functions_rec.c:10: Warning: + division by zero. assert __gen_e_acsl_f2_13 ≢ 0; +[eva:alarm] tests/arith/functions_rec.c:10: Warning: + signed overflow. + assert -2147483648 ≤ __gen_e_acsl_f2_9 * __gen_e_acsl_f2_11; +[eva:alarm] tests/arith/functions_rec.c:10: Warning: + signed overflow. + assert __gen_e_acsl_f2_9 * __gen_e_acsl_f2_11 ≤ 2147483647; +[eva:alarm] tests/arith/functions_rec.c:10: Warning: + signed overflow. + assert + (int)(__gen_e_acsl_f2_9 * __gen_e_acsl_f2_11) / __gen_e_acsl_f2_13 ≤ + 2147483647; +[eva:alarm] tests/arith/functions_rec.c:26: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/arith/functions_rec.c:28: Warning: + assertion got status unknown. +[eva] tests/arith/functions_rec.c:14: Warning: + recursive call during value analysis + of __gen_e_acsl_f3_2 (__gen_e_acsl_f3_2 <- __gen_e_acsl_f3_2 :: tests/arith/functions_rec.c:14 <- + __gen_e_acsl_f3 :: tests/arith/functions_rec.c:28 <- + main). + Assuming the call has no effect. The analysis will be unsound. +[eva:alarm] tests/arith/functions_rec.c:30: Warning: + assertion got status unknown. +[eva] tests/arith/functions_rec.c:17: Warning: + recursive call during value analysis + of __gen_e_acsl_f4_2 (__gen_e_acsl_f4_2 <- __gen_e_acsl_f4_2 :: tests/arith/functions_rec.c:17 <- + __gen_e_acsl_f4 :: tests/arith/functions_rec.c:30 <- + main). + Assuming the call has no effect. The analysis will be unsound. +[eva:alarm] tests/arith/functions_rec.c:30: Warning: + function __e_acsl_assert: precondition got status unknown. diff --git a/src/plugins/e-acsl/tests/arith/oracle_ci/gen_arith.c b/src/plugins/e-acsl/tests/arith/oracle_ci/gen_arith.c new file mode 100644 index 0000000000000000000000000000000000000000..a3c67a7d24d396ed36195a55be80a2c265159870 --- /dev/null +++ b/src/plugins/e-acsl/tests/arith/oracle_ci/gen_arith.c @@ -0,0 +1,140 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +int main(void) +{ + int __retres; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + int x = -3; + int y = 2; + long z = 2L; + /*@ assert -3 ≡ x; */ + __e_acsl_assert(-3 == x,(char *)"Assertion",(char *)"main", + (char *)"-3 == x",10); + /*@ assert x ≡ -3; */ + __e_acsl_assert(x == -3,(char *)"Assertion",(char *)"main", + (char *)"x == -3",11); + /*@ assert 0 ≢ ~0; */ + __e_acsl_assert(1,(char *)"Assertion",(char *)"main",(char *)"0 != ~0",12); + /*@ assert x + 1 ≡ -2; */ + __e_acsl_assert(x + 1L == -2L,(char *)"Assertion",(char *)"main", + (char *)"x + 1 == -2",14); + /*@ assert x - 1 ≡ -4; */ + __e_acsl_assert(x - 1L == -4L,(char *)"Assertion",(char *)"main", + (char *)"x - 1 == -4",15); + /*@ assert x * 3 ≡ -9; */ + __e_acsl_assert(x * 3L == -9L,(char *)"Assertion",(char *)"main", + (char *)"x * 3 == -9",16); + /*@ assert x / 3 ≡ -1; */ + __e_acsl_assert(x / 3 == -1,(char *)"Assertion",(char *)"main", + (char *)"x / 3 == -1",17); + /*@ assert 0xffffffffffffffffffffff / 0xffffffffffffffffffffff ≡ 1; */ + { + __e_acsl_mpz_t __gen_e_acsl_; + __e_acsl_mpz_t __gen_e_acsl__2; + int __gen_e_acsl_div_guard; + __e_acsl_mpz_t __gen_e_acsl_div; + long __gen_e_acsl__3; + __gmpz_init_set_str(__gen_e_acsl_,"309485009821345068724781055",10); + __gmpz_init_set_si(__gen_e_acsl__2,0L); + __gen_e_acsl_div_guard = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__2)); + __gmpz_init(__gen_e_acsl_div); + /*@ assert E_ACSL: 0xffffffffffffffffffffff ≢ 0; */ + __e_acsl_assert(! (__gen_e_acsl_div_guard == 0),(char *)"Assertion", + (char *)"main",(char *)"0xffffffffffffffffffffff == 0", + 18); + __gmpz_tdiv_q(__gen_e_acsl_div, + (__e_acsl_mpz_struct const *)(__gen_e_acsl_), + (__e_acsl_mpz_struct const *)(__gen_e_acsl_)); + __gen_e_acsl__3 = __gmpz_get_si((__e_acsl_mpz_struct const *)(__gen_e_acsl_div)); + __e_acsl_assert(__gen_e_acsl__3 == 1L,(char *)"Assertion",(char *)"main", + (char *)"0xffffffffffffffffffffff / 0xffffffffffffffffffffff == 1", + 18); + __gmpz_clear(__gen_e_acsl_); + __gmpz_clear(__gen_e_acsl__2); + __gmpz_clear(__gen_e_acsl_div); + } + /*@ assert x % 2 ≡ -1; */ + __e_acsl_assert(x % 2 == -1,(char *)"Assertion",(char *)"main", + (char *)"x % 2 == -1",19); + /*@ assert -3 % -2 ≡ -1; */ + __e_acsl_assert(1,(char *)"Assertion",(char *)"main", + (char *)"-3 % -2 == -1",20); + /*@ assert 3 % -2 ≡ 1; */ + __e_acsl_assert(1,(char *)"Assertion",(char *)"main",(char *)"3 % -2 == 1", + 21); + /*@ assert ((x * 2 + (3 + y)) - 4) + (x - y) ≡ -10; */ + __e_acsl_assert(((x * 2L + (3L + y)) - 4L) + (x - (long)y) == -10L, + (char *)"Assertion",(char *)"main", + (char *)"((x * 2 + (3 + y)) - 4) + (x - y) == -10",23); + /*@ assert (0 ≡ 1) ≡ !(0 ≡ 0); */ + __e_acsl_assert(1,(char *)"Assertion",(char *)"main", + (char *)"(0 == 1) == !(0 == 0)",25); + /*@ assert (0 ≤ -1) ≡ (0 > 0); */ + __e_acsl_assert(1,(char *)"Assertion",(char *)"main", + (char *)"(0 <= -1) == (0 > 0)",26); + /*@ assert (0 ≥ -1) ≡ (0 ≤ 0); */ + __e_acsl_assert(1,(char *)"Assertion",(char *)"main", + (char *)"(0 >= -1) == (0 <= 0)",27); + /*@ assert (0 ≢ 1) ≡ !(0 ≢ 0); */ + __e_acsl_assert(1,(char *)"Assertion",(char *)"main", + (char *)"(0 != 1) == !(0 != 0)",28); + /*@ assert (0 ≢ 0) ≡ !(1 ≢ 0); */ + __e_acsl_assert(1,(char *)"Assertion",(char *)"main", + (char *)"(0 != 0) == !(1 != 0)",30); + /*@ assert 4 / y ≡ 2; */ + { + __e_acsl_assert(y != 0,(char *)"RTE",(char *)"main", + (char *)"division_by_zero: y != 0",31); + __e_acsl_assert(4 / y == 2,(char *)"Assertion",(char *)"main", + (char *)"4 / y == 2",31); + } + /*@ assert 1 + (z + 1) / (y - 123456789123456789) ≡ 1; */ + { + __e_acsl_mpz_t __gen_e_acsl_z; + __e_acsl_mpz_t __gen_e_acsl__4; + __e_acsl_mpz_t __gen_e_acsl_add; + __e_acsl_mpz_t __gen_e_acsl__5; + __e_acsl_mpz_t __gen_e_acsl__6; + int __gen_e_acsl_div_guard_2; + __e_acsl_mpz_t __gen_e_acsl_div_2; + long __gen_e_acsl__7; + __gmpz_init_set_si(__gen_e_acsl_z,z); + __gmpz_init_set_si(__gen_e_acsl__4,1L); + __gmpz_init(__gen_e_acsl_add); + __gmpz_add(__gen_e_acsl_add, + (__e_acsl_mpz_struct const *)(__gen_e_acsl_z), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__4)); + __gmpz_init_set_si(__gen_e_acsl__5,y - 123456789123456789L); + __gmpz_init_set_si(__gen_e_acsl__6,0L); + __gen_e_acsl_div_guard_2 = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl__5), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__6)); + __gmpz_init(__gen_e_acsl_div_2); + /*@ assert E_ACSL: y - 123456789123456789 ≢ 0; */ + __e_acsl_assert(! (__gen_e_acsl_div_guard_2 == 0),(char *)"Assertion", + (char *)"main",(char *)"y - 123456789123456789 == 0",34); + __gmpz_tdiv_q(__gen_e_acsl_div_2, + (__e_acsl_mpz_struct const *)(__gen_e_acsl_add), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__5)); + __gen_e_acsl__7 = __gmpz_get_si((__e_acsl_mpz_struct const *)(__gen_e_acsl_div_2)); + /*@ assert Eva: signed_overflow: -2147483648 ≤ 1 + __gen_e_acsl__7; */ + /*@ assert Eva: signed_overflow: 1 + __gen_e_acsl__7 ≤ 2147483647; */ + __e_acsl_assert(1 + __gen_e_acsl__7 == 1,(char *)"Assertion", + (char *)"main", + (char *)"1 + (z + 1) / (y - 123456789123456789) == 1",34); + __gmpz_clear(__gen_e_acsl_z); + __gmpz_clear(__gen_e_acsl__4); + __gmpz_clear(__gen_e_acsl_add); + __gmpz_clear(__gen_e_acsl__5); + __gmpz_clear(__gen_e_acsl__6); + __gmpz_clear(__gen_e_acsl_div_2); + } + /*@ assert 1 - x ≡ -x + 1; */ + __e_acsl_assert(1L - x == - ((long)x) + 1L,(char *)"Assertion", + (char *)"main",(char *)"1 - x == -x + 1",36); + __retres = 0; + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/arith/oracle_ci/gen_array.c b/src/plugins/e-acsl/tests/arith/oracle_ci/gen_array.c new file mode 100644 index 0000000000000000000000000000000000000000..e5f0d771cd64e8662ae052d763d753d3bbc244e6 --- /dev/null +++ b/src/plugins/e-acsl/tests/arith/oracle_ci/gen_array.c @@ -0,0 +1,34 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +int T1[3]; +int T2[4]; +int main(void) +{ + int __retres; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + { + int i = 0; + while (i < 3) { + T1[i] = i; + i ++; + } + } + { + int i_0 = 0; + while (i_0 < 4) { + T2[i_0] = 2 * i_0; + i_0 ++; + } + } + /*@ assert T1[0] ≡ T2[0]; */ + __e_acsl_assert(T1[0] == T2[0],(char *)"Assertion",(char *)"main", + (char *)"T1[0] == T2[0]",13); + /*@ assert T1[1] ≢ T2[1]; */ + __e_acsl_assert(T1[1] != T2[1],(char *)"Assertion",(char *)"main", + (char *)"T1[1] != T2[1]",14); + __retres = 0; + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/arith/oracle_ci/gen_at.c b/src/plugins/e-acsl/tests/arith/oracle_ci/gen_at.c new file mode 100644 index 0000000000000000000000000000000000000000..e25c22550a06dc73724a2690d7744e2d6ba5efe7 --- /dev/null +++ b/src/plugins/e-acsl/tests/arith/oracle_ci/gen_at.c @@ -0,0 +1,196 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +extern int __e_acsl_sound_verdict; + +int A = 0; +/*@ ensures \at(A,Post) ≡ 3; */ +void __gen_e_acsl_f(void); + +void f(void) +{ + int __gen_e_acsl_at_4; + int __gen_e_acsl_at_3; + int __gen_e_acsl_at_2; + int __gen_e_acsl_at; + __gen_e_acsl_at_3 = A; + __gen_e_acsl_at = A; + A = 1; + F: { + __gen_e_acsl_at_4 = __gen_e_acsl_at_3; + __gen_e_acsl_at_2 = A; + A = 2; + } + /*@ assert \at(A,Pre) ≡ 0; */ + __e_acsl_assert(__gen_e_acsl_at == 0,(char *)"Assertion",(char *)"f", + (char *)"\\at(A,Pre) == 0",11); + /*@ assert \at(A,F) ≡ 1; */ + __e_acsl_assert(__gen_e_acsl_at_2 == 1,(char *)"Assertion",(char *)"f", + (char *)"\\at(A,F) == 1",12); + /*@ assert \at(A,Here) ≡ 2; */ + __e_acsl_assert(A == 2,(char *)"Assertion",(char *)"f", + (char *)"\\at(A,Here) == 2",13); + /*@ assert \at(\at(A,Pre),F) ≡ 0; */ + __e_acsl_assert(__gen_e_acsl_at_4 == 0,(char *)"Assertion",(char *)"f", + (char *)"\\at(\\at(A,Pre),F) == 0",14); + A = 3; + return; +} + +void g(int *p, int *q) +{ + int __gen_e_acsl_at_3; + int __gen_e_acsl_at_2; + int __gen_e_acsl_at; + __e_acsl_store_block((void *)(& q),(size_t)8); + __e_acsl_store_block((void *)(& p),(size_t)8); + __e_acsl_initialize((void *)p,sizeof(int)); + *p = 0; + __e_acsl_initialize((void *)(p + 1),sizeof(int)); + *(p + 1) = 1; + __e_acsl_initialize((void *)q,sizeof(int)); + *q = 0; + L1: + { + { + int __gen_e_acsl_valid_read_3; + __gen_e_acsl_valid_read_3 = __e_acsl_valid_read((void *)q,sizeof(int), + (void *)q, + (void *)(& q)); + __e_acsl_assert(__gen_e_acsl_valid_read_3,(char *)"RTE",(char *)"g", + (char *)"mem_access: \\valid_read(q)",28); + __gen_e_acsl_at_3 = *q; + } + { + int __gen_e_acsl_valid_read; + __gen_e_acsl_valid_read = __e_acsl_valid_read((void *)q,sizeof(int), + (void *)q,(void *)(& q)); + __e_acsl_assert(__gen_e_acsl_valid_read,(char *)"RTE",(char *)"g", + (char *)"mem_access: \\valid_read(q)",26); + __gen_e_acsl_at = *q; + } + __e_acsl_initialize((void *)p,sizeof(int)); + *p = 2; + } + __e_acsl_initialize((void *)(p + 1),sizeof(int)); + *(p + 1) = 3; + __e_acsl_initialize((void *)q,sizeof(int)); + *q = 1; + L2: + { + { + int __gen_e_acsl_valid_read_2; + __gen_e_acsl_valid_read_2 = __e_acsl_valid_read((void *)(p + __gen_e_acsl_at), + sizeof(int),(void *)p, + (void *)(& p)); + __e_acsl_assert(__gen_e_acsl_valid_read_2,(char *)"RTE",(char *)"g", + (char *)"mem_access: \\valid_read(p + __gen_e_acsl_at)", + 26); + __gen_e_acsl_at_2 = *(p + __gen_e_acsl_at); + } + A = 4; + } + /*@ assert \at(*(p + \at(*q,L1)),L2) ≡ 2; */ + __e_acsl_assert(__gen_e_acsl_at_2 == 2,(char *)"Assertion",(char *)"g", + (char *)"\\at(*(p + \\at(*q,L1)),L2) == 2",26); + L3: + /*@ assert \at(*(p + \at(*q,L1)),Here) ≡ 2; */ + { + int __gen_e_acsl_valid_read_4; + __gen_e_acsl_valid_read_4 = __e_acsl_valid_read((void *)(p + __gen_e_acsl_at_3), + sizeof(int),(void *)p, + (void *)(& p)); + __e_acsl_assert(__gen_e_acsl_valid_read_4,(char *)"RTE",(char *)"g", + (char *)"mem_access: \\valid_read(p + __gen_e_acsl_at_3)", + 28); + __e_acsl_assert(*(p + __gen_e_acsl_at_3) == 2,(char *)"Assertion", + (char *)"g",(char *)"\\at(*(p + \\at(*q,L1)),Here) == 2", + 28); + } + __e_acsl_delete_block((void *)(& q)); + __e_acsl_delete_block((void *)(& p)); + return; +} + +/*@ ensures \result ≡ \old(x); */ +int __gen_e_acsl_h(int x); + +int h(int x) +{ + __e_acsl_store_block((void *)(& x),(size_t)4); + __e_acsl_delete_block((void *)(& x)); + return x; +} + +int main(void) +{ + long __gen_e_acsl_at_3; + long __gen_e_acsl_at_2; + int __gen_e_acsl_at; + int __retres; + int x; + int t[2]; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + __e_acsl_store_block((void *)(t),(size_t)8); + __e_acsl_store_block((void *)(& x),(size_t)4); + __e_acsl_full_init((void *)(& x)); + x = __gen_e_acsl_h(0); + L: + /*@ assert x ≡ 0; */ + { + __gen_e_acsl_at_3 = (long)x; + __gen_e_acsl_at_2 = x + 1L; + __gen_e_acsl_at = x; + __e_acsl_assert(x == 0,(char *)"Assertion",(char *)"main", + (char *)"x == 0",43); + } + __e_acsl_full_init((void *)(& x)); + x = 1; + __e_acsl_full_init((void *)(& x)); + x = 2; + __gen_e_acsl_f(); + /*@ assert \at(x,L) ≡ 0; */ + __e_acsl_assert(__gen_e_acsl_at == 0,(char *)"Assertion",(char *)"main", + (char *)"\\at(x,L) == 0",48); + /*@ assert \at(x + 1,L) ≡ 1; */ + __e_acsl_assert(__gen_e_acsl_at_2 == 1L,(char *)"Assertion",(char *)"main", + (char *)"\\at(x + 1,L) == 1",49); + /*@ assert \at(x,L) + 1 ≡ 1; */ + __e_acsl_assert(__gen_e_acsl_at_3 + 1L == 1L,(char *)"Assertion", + (char *)"main",(char *)"\\at(x,L) + 1 == 1",50); + g(t,& x); + __retres = 0; + __e_acsl_delete_block((void *)(t)); + __e_acsl_delete_block((void *)(& x)); + __e_acsl_memory_clean(); + return __retres; +} + +/*@ ensures \result ≡ \old(x); */ +int __gen_e_acsl_h(int x) +{ + int __gen_e_acsl_at; + int __retres; + __e_acsl_store_block((void *)(& __retres),(size_t)4); + __gen_e_acsl_at = x; + __e_acsl_store_block((void *)(& x),(size_t)4); + __retres = h(x); + __e_acsl_assert(__retres == __gen_e_acsl_at,(char *)"Postcondition", + (char *)"h",(char *)"\\result == \\old(x)",35); + __e_acsl_delete_block((void *)(& x)); + __e_acsl_delete_block((void *)(& __retres)); + return __retres; +} + +/*@ ensures \at(A,Post) ≡ 3; */ +void __gen_e_acsl_f(void) +{ + int __gen_e_acsl_at; + f(); + __gen_e_acsl_at = A; + __e_acsl_assert(__gen_e_acsl_at == 3,(char *)"Postcondition",(char *)"f", + (char *)"\\at(A,Post) == 3",7); + return; +} + + diff --git a/src/plugins/e-acsl/tests/arith/oracle_ci/gen_at_on-purely-logic-variables.c b/src/plugins/e-acsl/tests/arith/oracle_ci/gen_at_on-purely-logic-variables.c new file mode 100644 index 0000000000000000000000000000000000000000..fa74ebe91f81599c66fb07b42953c67ccafb1e6f --- /dev/null +++ b/src/plugins/e-acsl/tests/arith/oracle_ci/gen_at_on-purely-logic-variables.c @@ -0,0 +1,716 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +extern int __e_acsl_sound_verdict; + +/*@ ensures + ∀ ℤ n; + 1 < n ≤ 3 ⇒ \old(*(t + n) ≡ 12) ∧ \old(*(t + (n - 1)) > 5); + ensures \let m = 4; \old(*(t + m) ≡ -4) ∧ \old(*(t + (m - 4))) ≡ 9; + */ +void __gen_e_acsl_f(int *t); + +void f(int *t) +{ + __e_acsl_store_block((void *)(& t),(size_t)8); + __e_acsl_delete_block((void *)(& t)); + return; +} + +void g(void) +{ + int *__gen_e_acsl_at; + int m; + __gen_e_acsl_at = (int *)malloc((size_t)12); + m = 8; + Q: + { + { + int __gen_e_acsl_w_2; + __gen_e_acsl_w_2 = 3; + while (1) { + if (__gen_e_acsl_w_2 < 6) ; else break; + *(__gen_e_acsl_at + (__gen_e_acsl_w_2 - 3)) = m + (long)__gen_e_acsl_w_2 == 12L; + __gen_e_acsl_w_2 ++; + } + } + ; + } + m = 10; + /*@ assert ∃ ℤ w; 3 ≤ w < 6 ∧ \at(m + w ≡ 12,Q); */ + { + int __gen_e_acsl_exists; + int __gen_e_acsl_w; + __gen_e_acsl_exists = 0; + __gen_e_acsl_w = 3; + while (1) { + if (__gen_e_acsl_w < 6) ; else break; + { + int __gen_e_acsl_valid_read; + __gen_e_acsl_valid_read = __e_acsl_valid_read((void *)(__gen_e_acsl_at + (int)( + __gen_e_acsl_w - 3L)), + sizeof(int), + (void *)__gen_e_acsl_at, + (void *)(& __gen_e_acsl_at)); + __e_acsl_assert(__gen_e_acsl_valid_read,(char *)"RTE",(char *)"g", + (char *)"mem_access: \\valid_read(__gen_e_acsl_at + (int)(__gen_e_acsl_w - 3))", + 16); + /*@ assert + Eva: initialization: + \initialized(__gen_e_acsl_at + (__gen_e_acsl_w - 3)); + */ + if (! *(__gen_e_acsl_at + (__gen_e_acsl_w - 3))) ; + else { + __gen_e_acsl_exists = 1; + goto e_acsl_end_loop1; + } + } + __gen_e_acsl_w ++; + } + e_acsl_end_loop1: ; + __e_acsl_assert(__gen_e_acsl_exists,(char *)"Assertion",(char *)"g", + (char *)"\\exists integer w; 3 <= w < 6 && \\at(m + w == 12,Q)", + 16); + } + free((void *)__gen_e_acsl_at); + return; +} + +int main(void) +{ + int *__gen_e_acsl_at_7; + int *__gen_e_acsl_at_6; + long *__gen_e_acsl_at_5; + long *__gen_e_acsl_at_4; + int *__gen_e_acsl_at_3; + int *__gen_e_acsl_at_2; + int *__gen_e_acsl_at; + int __retres; + int n; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + __gen_e_acsl_at_7 = (int *)malloc((size_t)12000); + __gen_e_acsl_at_6 = (int *)malloc((size_t)1536); + __gen_e_acsl_at_5 = (long *)malloc((size_t)64); + __gen_e_acsl_at_4 = (long *)malloc((size_t)8); + __gen_e_acsl_at_3 = (int *)malloc((size_t)528); + __gen_e_acsl_at_2 = (int *)malloc((size_t)12); + __gen_e_acsl_at = (int *)malloc((size_t)4); + __e_acsl_store_block((void *)(& n),(size_t)4); + __e_acsl_full_init((void *)(& n)); + n = 7; + L: + { + { + int __gen_e_acsl_i_4; + __gen_e_acsl_i_4 = 3; + *(__gen_e_acsl_at_4 + 0) = n + (long)__gen_e_acsl_i_4; + } + { + int __gen_e_acsl_j_2; + __gen_e_acsl_j_2 = 2; + while (1) { + if (__gen_e_acsl_j_2 < 5) ; else break; + *(__gen_e_acsl_at_2 + (__gen_e_acsl_j_2 - 2)) = n + (long)__gen_e_acsl_j_2 == 11L; + __gen_e_acsl_j_2 ++; + } + } + { + int __gen_e_acsl_i_2; + __gen_e_acsl_i_2 = 3; + *(__gen_e_acsl_at + 0) = n + (long)__gen_e_acsl_i_2 == 10L; + } + ; + } + __e_acsl_full_init((void *)(& n)); + n = 9; + K: + { + { + int __gen_e_acsl_u_6; + int __gen_e_acsl_v_6; + int __gen_e_acsl_w_2; + __gen_e_acsl_u_6 = 10; + while (1) { + if (__gen_e_acsl_u_6 < 20) ; else break; + __gen_e_acsl_v_6 = -10 + 1; + while (1) { + { + int __gen_e_acsl_u_8; + __gen_e_acsl_u_8 = -2; + if (__gen_e_acsl_v_6 <= -5 + __gen_e_acsl_u_8) ; else break; + } + __gen_e_acsl_w_2 = 100 + 1; + while (1) { + if (__gen_e_acsl_w_2 <= 200) ; else break; + { + int __gen_e_acsl_u_7; + __gen_e_acsl_u_7 = 42; + *(__gen_e_acsl_at_7 + ((__gen_e_acsl_u_6 - 10) * 300 + ( + ((__gen_e_acsl_v_6 - -10) - 1) * 100 + ( + (__gen_e_acsl_w_2 - 100) - 1)))) = + (((n - (long)__gen_e_acsl_u_6) + __gen_e_acsl_u_7) + __gen_e_acsl_v_6) + __gen_e_acsl_w_2 > 0L; + } + __gen_e_acsl_w_2 ++; + } + __gen_e_acsl_v_6 ++; + } + __gen_e_acsl_u_6 ++; + } + } + { + int __gen_e_acsl_u_4; + int __gen_e_acsl_v_4; + __gen_e_acsl_u_4 = 9; + while (1) { + if (__gen_e_acsl_u_4 < 21) ; else break; + __gen_e_acsl_v_4 = -5 + 1; + while (1) { + { + int __gen_e_acsl_if_2; + if (__gen_e_acsl_u_4 < 15) __gen_e_acsl_if_2 = __gen_e_acsl_u_4 + 6; + else __gen_e_acsl_if_2 = 3; + if (__gen_e_acsl_v_4 <= __gen_e_acsl_if_2) ; else break; + } + *(__gen_e_acsl_at_6 + ((__gen_e_acsl_u_4 - 9) * 32 + ((__gen_e_acsl_v_4 - -5) - 1))) = + (n + (long)__gen_e_acsl_u_4) + __gen_e_acsl_v_4 > 0L; + __gen_e_acsl_v_4 ++; + } + __gen_e_acsl_u_4 ++; + } + } + { + int __gen_e_acsl_k_2; + int __gen_e_acsl_u_2; + int __gen_e_acsl_v_2; + __gen_e_acsl_k_2 = -7; + __gen_e_acsl_u_2 = 9; + while (1) { + if (__gen_e_acsl_u_2 < 21) ; else break; + __gen_e_acsl_v_2 = -5 + 1; + while (1) { + if (__gen_e_acsl_v_2 <= 6) ; else break; + { + long __gen_e_acsl_if; + if (__gen_e_acsl_u_2 > 0) __gen_e_acsl_if = n + (long)__gen_e_acsl_k_2; + else __gen_e_acsl_if = __gen_e_acsl_u_2 + __gen_e_acsl_v_2; + *(__gen_e_acsl_at_3 + ((__gen_e_acsl_u_2 - 9) * 11 + ((__gen_e_acsl_v_2 - -5) - 1))) = + __gen_e_acsl_if > 0L; + } + __gen_e_acsl_v_2 ++; + } + __gen_e_acsl_u_2 ++; + } + } + ; + } + __e_acsl_full_init((void *)(& n)); + n = 666; + /*@ assert \let i = 3; \at(n + i ≡ 10,L); */ + { + int __gen_e_acsl_i; + int __gen_e_acsl_valid_read; + __gen_e_acsl_i = 3; + __gen_e_acsl_valid_read = __e_acsl_valid_read((void *)(__gen_e_acsl_at + 0), + sizeof(int), + (void *)__gen_e_acsl_at, + (void *)(& __gen_e_acsl_at)); + __e_acsl_assert(__gen_e_acsl_valid_read,(char *)"RTE",(char *)"main", + (char *)"mem_access: \\valid_read(__gen_e_acsl_at + 0)", + 28); + __e_acsl_assert(*(__gen_e_acsl_at + 0),(char *)"Assertion", + (char *)"main", + (char *)"\\let i = 3; \\at(n + i == 10,L)",28); + } + /*@ assert ∃ ℤ j; 2 ≤ j < 5 ∧ \at(n + j ≡ 11,L); */ + { + int __gen_e_acsl_exists; + int __gen_e_acsl_j; + __gen_e_acsl_exists = 0; + __gen_e_acsl_j = 2; + while (1) { + if (__gen_e_acsl_j < 5) ; else break; + { + int __gen_e_acsl_valid_read_2; + __gen_e_acsl_valid_read_2 = __e_acsl_valid_read((void *)(__gen_e_acsl_at_2 + (int)( + __gen_e_acsl_j - 2L)), + sizeof(int), + (void *)__gen_e_acsl_at_2, + (void *)(& __gen_e_acsl_at_2)); + __e_acsl_assert(__gen_e_acsl_valid_read_2,(char *)"RTE", + (char *)"main", + (char *)"mem_access: \\valid_read(__gen_e_acsl_at_2 + (int)(__gen_e_acsl_j - 2))", + 29); + /*@ assert + Eva: initialization: + \initialized(__gen_e_acsl_at_2 + (__gen_e_acsl_j - 2)); + */ + if (! *(__gen_e_acsl_at_2 + (__gen_e_acsl_j - 2))) ; + else { + __gen_e_acsl_exists = 1; + goto e_acsl_end_loop2; + } + } + __gen_e_acsl_j ++; + } + e_acsl_end_loop2: ; + __e_acsl_assert(__gen_e_acsl_exists,(char *)"Assertion",(char *)"main", + (char *)"\\exists integer j; 2 <= j < 5 && \\at(n + j == 11,L)", + 29); + } + /*@ assert \let k = -7; + ∃ ℤ u; + 9 ≤ u < 21 ∧ + (∀ ℤ v; -5 < v ≤ 6 ⇒ \at((u > 0? n + k: u + v) > 0,K)); + */ + { + int __gen_e_acsl_k; + int __gen_e_acsl_exists_2; + int __gen_e_acsl_u; + __gen_e_acsl_k = -7; + __gen_e_acsl_exists_2 = 0; + __gen_e_acsl_u = 9; + while (1) { + if (__gen_e_acsl_u < 21) ; else break; + { + int __gen_e_acsl_forall; + int __gen_e_acsl_v; + __gen_e_acsl_forall = 1; + __gen_e_acsl_v = -5 + 1; + while (1) { + if (__gen_e_acsl_v <= 6) ; else break; + { + int __gen_e_acsl_valid_read_3; + __gen_e_acsl_valid_read_3 = __e_acsl_valid_read((void *)( + __gen_e_acsl_at_3 + (int)( + (long)((int)( + (long)((int)( + __gen_e_acsl_u - 9L)) * 11L)) + (int)( + (int)(__gen_e_acsl_v - -5L) - 1))), + sizeof(int), + (void *)__gen_e_acsl_at_3, + (void *)(& __gen_e_acsl_at_3)); + __e_acsl_assert(__gen_e_acsl_valid_read_3,(char *)"RTE", + (char *)"main", + (char *)"mem_access:\n \\valid_read(__gen_e_acsl_at_3 +\n (int)((int)((int)(__gen_e_acsl_u - 9) * 11) +\n (int)((int)(__gen_e_acsl_v - -5) - 1)))", + 34); + /*@ assert + Eva: initialization: + \initialized(__gen_e_acsl_at_3 + + ((__gen_e_acsl_u - 9) * 11 + + ((__gen_e_acsl_v - -5) - 1))); + */ + if (*(__gen_e_acsl_at_3 + ((__gen_e_acsl_u - 9) * 11 + (( + __gen_e_acsl_v - -5) - 1)))) + ; + else { + __gen_e_acsl_forall = 0; + goto e_acsl_end_loop3; + } + } + __gen_e_acsl_v ++; + } + e_acsl_end_loop3: ; + if (! __gen_e_acsl_forall) ; + else { + __gen_e_acsl_exists_2 = 1; + goto e_acsl_end_loop4; + } + } + __gen_e_acsl_u ++; + } + e_acsl_end_loop4: ; + __e_acsl_assert(__gen_e_acsl_exists_2,(char *)"Assertion",(char *)"main", + (char *)"\\let k = -7;\n\\exists integer u;\n 9 <= u < 21 &&\n (\\forall integer v; -5 < v <= 6 ==> \\at((u > 0? n + k: u + v) > 0,K))", + 31); + } + /*@ assert \let i = 3; \at(n + i,L) ≡ 10; */ + { + int __gen_e_acsl_i_3; + int __gen_e_acsl_valid_read_4; + __gen_e_acsl_i_3 = 3; + __gen_e_acsl_valid_read_4 = __e_acsl_valid_read((void *)(__gen_e_acsl_at_4 + 0), + sizeof(long), + (void *)__gen_e_acsl_at_4, + (void *)(& __gen_e_acsl_at_4)); + __e_acsl_assert(__gen_e_acsl_valid_read_4,(char *)"RTE",(char *)"main", + (char *)"mem_access: \\valid_read(__gen_e_acsl_at_4 + 0)", + 37); + __e_acsl_assert(*(__gen_e_acsl_at_4 + 0) == 10L,(char *)"Assertion", + (char *)"main", + (char *)"\\let i = 3; \\at(n + i,L) == 10",37); + } + unsigned int m = (unsigned int)3; + G: + { + { + int __gen_e_acsl_k_4; + __gen_e_acsl_k_4 = -9 + 1; + while (1) { + if (__gen_e_acsl_k_4 < 0) ; else break; + *(__gen_e_acsl_at_5 + ((__gen_e_acsl_k_4 - -9) - 1)) = m + (long)__gen_e_acsl_k_4; + __gen_e_acsl_k_4 ++; + } + } + ; + } + m = (unsigned int)(-3); + /*@ assert ∃ ℤ k; -9 < k < 0 ∧ \at(m + k,G) ≡ 0; */ + { + int __gen_e_acsl_exists_3; + int __gen_e_acsl_k_3; + __gen_e_acsl_exists_3 = 0; + __gen_e_acsl_k_3 = -9 + 1; + while (1) { + if (__gen_e_acsl_k_3 < 0) ; else break; + { + int __gen_e_acsl_valid_read_5; + __gen_e_acsl_valid_read_5 = __e_acsl_valid_read((void *)(__gen_e_acsl_at_5 + ( + (int)( + __gen_e_acsl_k_3 - -9L) - 1)), + sizeof(long), + (void *)__gen_e_acsl_at_5, + (void *)(& __gen_e_acsl_at_5)); + __e_acsl_assert(__gen_e_acsl_valid_read_5,(char *)"RTE", + (char *)"main", + (char *)"mem_access:\n \\valid_read(__gen_e_acsl_at_5 + (int)((int)(__gen_e_acsl_k_3 - -9) - 1))", + 41); + /*@ assert + Eva: initialization: + \initialized(__gen_e_acsl_at_5 + ((__gen_e_acsl_k_3 - -9) - 1)); + */ + if (! (*(__gen_e_acsl_at_5 + ((__gen_e_acsl_k_3 - -9) - 1)) == 0L)) + ; + else { + __gen_e_acsl_exists_3 = 1; + goto e_acsl_end_loop5; + } + } + __gen_e_acsl_k_3 ++; + } + e_acsl_end_loop5: ; + __e_acsl_assert(__gen_e_acsl_exists_3,(char *)"Assertion",(char *)"main", + (char *)"\\exists integer k; -9 < k < 0 && \\at(m + k,G) == 0", + 41); + } + /*@ assert + ∃ ℤ u; + 9 ≤ u < 21 ∧ + (∀ ℤ v; -5 < v ≤ (u < 15? u + 6: 3) ⇒ \at((n + u) + v > 0,K)); + */ + { + int __gen_e_acsl_exists_4; + int __gen_e_acsl_u_3; + __gen_e_acsl_exists_4 = 0; + __gen_e_acsl_u_3 = 9; + while (1) { + if (__gen_e_acsl_u_3 < 21) ; else break; + { + int __gen_e_acsl_forall_2; + int __gen_e_acsl_v_3; + __gen_e_acsl_forall_2 = 1; + __gen_e_acsl_v_3 = -5 + 1; + while (1) { + { + int __gen_e_acsl_if_3; + if (__gen_e_acsl_u_3 < 15) __gen_e_acsl_if_3 = __gen_e_acsl_u_3 + 6; + else __gen_e_acsl_if_3 = 3; + if (__gen_e_acsl_v_3 <= __gen_e_acsl_if_3) ; else break; + } + { + int __gen_e_acsl_valid_read_6; + __gen_e_acsl_valid_read_6 = __e_acsl_valid_read((void *)( + __gen_e_acsl_at_6 + (int)( + (long)((int)( + (long)((int)( + __gen_e_acsl_u_3 - 9L)) * 32L)) + (int)( + (int)(__gen_e_acsl_v_3 - -5L) - 1))), + sizeof(int), + (void *)__gen_e_acsl_at_6, + (void *)(& __gen_e_acsl_at_6)); + __e_acsl_assert(__gen_e_acsl_valid_read_6,(char *)"RTE", + (char *)"main", + (char *)"mem_access:\n \\valid_read(__gen_e_acsl_at_6 +\n (int)((int)((int)(__gen_e_acsl_u_3 - 9) * 32) +\n (int)((int)(__gen_e_acsl_v_3 - -5) - 1)))", + 45); + /*@ assert + Eva: initialization: + \initialized(__gen_e_acsl_at_6 + + ((__gen_e_acsl_u_3 - 9) * 32 + + ((__gen_e_acsl_v_3 - -5) - 1))); + */ + if (*(__gen_e_acsl_at_6 + ((__gen_e_acsl_u_3 - 9) * 32 + ( + (__gen_e_acsl_v_3 - -5) - 1)))) + ; + else { + __gen_e_acsl_forall_2 = 0; + goto e_acsl_end_loop6; + } + } + __gen_e_acsl_v_3 ++; + } + e_acsl_end_loop6: ; + if (! __gen_e_acsl_forall_2) ; + else { + __gen_e_acsl_exists_4 = 1; + goto e_acsl_end_loop7; + } + } + __gen_e_acsl_u_3 ++; + } + e_acsl_end_loop7: ; + __e_acsl_assert(__gen_e_acsl_exists_4,(char *)"Assertion",(char *)"main", + (char *)"\\exists integer u;\n 9 <= u < 21 &&\n (\\forall integer v; -5 < v <= (u < 15? u + 6: 3) ==> \\at((n + u) + v > 0,K))", + 43); + } + int t[5] = {9, 12, 12, 12, -4}; + __e_acsl_store_block((void *)(t),(size_t)20); + __e_acsl_full_init((void *)(& t)); + __gen_e_acsl_f(t); + g(); + /*@ assert + ∃ ℤ u; + 10 ≤ u < 20 ∧ + (∃ ℤ v; + -10 < v ≤ -5 + (\let u = -2; u) ∧ + (∃ ℤ w; + 100 < w ≤ 200 ∧ + \at((((n - u) + (\let u = 42; u)) + v) + w > 0,K))); + */ + { + int __gen_e_acsl_exists_5; + int __gen_e_acsl_u_5; + __gen_e_acsl_exists_5 = 0; + __gen_e_acsl_u_5 = 10; + while (1) { + if (__gen_e_acsl_u_5 < 20) ; else break; + { + int __gen_e_acsl_exists_6; + int __gen_e_acsl_v_5; + __gen_e_acsl_exists_6 = 0; + __gen_e_acsl_v_5 = -10 + 1; + while (1) { + { + int __gen_e_acsl_u_9; + __gen_e_acsl_u_9 = -2; + if (__gen_e_acsl_v_5 <= -5 + __gen_e_acsl_u_9) ; else break; + } + { + int __gen_e_acsl_exists_7; + int __gen_e_acsl_w; + __gen_e_acsl_exists_7 = 0; + __gen_e_acsl_w = 100 + 1; + while (1) { + if (__gen_e_acsl_w <= 200) ; else break; + { + int __gen_e_acsl_valid_read_7; + __gen_e_acsl_valid_read_7 = __e_acsl_valid_read((void *)( + __gen_e_acsl_at_7 + (int)( + (long)((int)( + (long)((int)( + __gen_e_acsl_u_5 - 10L)) * 300L)) + (int)( + (long)((int)( + (long)((int)( + (int)( + __gen_e_acsl_v_5 - -10L) - 1)) * 100L)) + (int)( + (long)((int)( + __gen_e_acsl_w - 100L)) - 1L)))), + sizeof(int), + (void *)__gen_e_acsl_at_7, + (void *)(& __gen_e_acsl_at_7)); + __e_acsl_assert(__gen_e_acsl_valid_read_7,(char *)"RTE", + (char *)"main", + (char *)"mem_access:\n \\valid_read(__gen_e_acsl_at_7 +\n (int)((int)((int)(__gen_e_acsl_u_5 - 10) * 300) +\n (int)((int)((int)((int)(__gen_e_acsl_v_5 - -10) - 1) *\n 100)\n + (int)((int)(__gen_e_acsl_w - 100) - 1))))", + 57); + /*@ assert + Eva: initialization: + \initialized(__gen_e_acsl_at_7 + + ((__gen_e_acsl_u_5 - 10) * 300 + + (((__gen_e_acsl_v_5 - -10) - 1) * 100 + + ((__gen_e_acsl_w - 100) - 1)))); + */ + if (! *(__gen_e_acsl_at_7 + ((__gen_e_acsl_u_5 - 10) * 300 + ( + ((__gen_e_acsl_v_5 - -10) - 1) * 100 + ( + (__gen_e_acsl_w - 100) - 1))))) + ; + else { + __gen_e_acsl_exists_7 = 1; + goto e_acsl_end_loop8; + } + } + __gen_e_acsl_w ++; + } + e_acsl_end_loop8: ; + if (! __gen_e_acsl_exists_7) ; + else { + __gen_e_acsl_exists_6 = 1; + goto e_acsl_end_loop9; + } + } + __gen_e_acsl_v_5 ++; + } + e_acsl_end_loop9: ; + if (! __gen_e_acsl_exists_6) ; + else { + __gen_e_acsl_exists_5 = 1; + goto e_acsl_end_loop10; + } + } + __gen_e_acsl_u_5 ++; + } + e_acsl_end_loop10: ; + __e_acsl_assert(__gen_e_acsl_exists_5,(char *)"Assertion",(char *)"main", + (char *)"\\exists integer u;\n 10 <= u < 20 &&\n (\\exists integer v;\n -10 < v <= -5 + (\\let u = -2; u) &&\n (\\exists integer w;\n 100 < w <= 200 && \\at((((n - u) + (\\let u = 42; u)) + v) + w > 0,K)))", + 54); + } + /*@ assert ∃ ℤ j; 2 ≤ j < 10000000000000000 ∧ \at(n + j ≡ 11,L); + */ + ; + /*@ assert \let i = n; \at(n + i ≡ 10,L); */ ; + __retres = 0; + __e_acsl_delete_block((void *)(t)); + __e_acsl_delete_block((void *)(& n)); + free((void *)__gen_e_acsl_at_7); + free((void *)__gen_e_acsl_at_6); + free((void *)__gen_e_acsl_at_5); + free((void *)__gen_e_acsl_at_4); + free((void *)__gen_e_acsl_at_3); + free((void *)__gen_e_acsl_at_2); + free((void *)__gen_e_acsl_at); + __e_acsl_memory_clean(); + return __retres; +} + +/*@ ensures + ∀ ℤ n; + 1 < n ≤ 3 ⇒ \old(*(t + n) ≡ 12) ∧ \old(*(t + (n - 1)) > 5); + ensures \let m = 4; \old(*(t + m) ≡ -4) ∧ \old(*(t + (m - 4))) ≡ 9; + */ +void __gen_e_acsl_f(int *t) +{ + int *__gen_e_acsl_at_4; + int *__gen_e_acsl_at_3; + int *__gen_e_acsl_at_2; + int *__gen_e_acsl_at; + __gen_e_acsl_at_4 = (int *)malloc((size_t)4); + __gen_e_acsl_at_3 = (int *)malloc((size_t)4); + __gen_e_acsl_at_2 = (int *)malloc((size_t)8); + __gen_e_acsl_at = (int *)malloc((size_t)8); + { + int __gen_e_acsl_m_3; + __gen_e_acsl_m_3 = 4; + *(__gen_e_acsl_at_4 + 0) = *(t + (__gen_e_acsl_m_3 - 4)); + } + { + int __gen_e_acsl_m_2; + __gen_e_acsl_m_2 = 4; + *(__gen_e_acsl_at_3 + 0) = *(t + __gen_e_acsl_m_2) == -4; + } + { + int __gen_e_acsl_n_3; + __gen_e_acsl_n_3 = 1 + 1; + while (1) { + if (__gen_e_acsl_n_3 <= 3) ; else break; + *(__gen_e_acsl_at_2 + ((__gen_e_acsl_n_3 - 1) - 1)) = *(t + (__gen_e_acsl_n_3 - 1)) > 5; + __gen_e_acsl_n_3 ++; + } + } + { + int __gen_e_acsl_n_2; + __gen_e_acsl_n_2 = 1 + 1; + while (1) { + if (__gen_e_acsl_n_2 <= 3) ; else break; + *(__gen_e_acsl_at + ((__gen_e_acsl_n_2 - 1) - 1)) = *(t + __gen_e_acsl_n_2) == 12; + __gen_e_acsl_n_2 ++; + } + } + __e_acsl_store_block((void *)(& t),(size_t)8); + f(t); + { + int __gen_e_acsl_forall; + int __gen_e_acsl_n; + int __gen_e_acsl_m; + int __gen_e_acsl_valid_read_3; + int __gen_e_acsl_and_2; + __gen_e_acsl_forall = 1; + __gen_e_acsl_n = 1 + 1; + while (1) { + if (__gen_e_acsl_n <= 3) ; else break; + { + int __gen_e_acsl_valid_read; + int __gen_e_acsl_and; + __gen_e_acsl_valid_read = __e_acsl_valid_read((void *)(__gen_e_acsl_at + (int)( + (long)((int)( + __gen_e_acsl_n - 1L)) - 1L)), + sizeof(int), + (void *)__gen_e_acsl_at, + (void *)(& __gen_e_acsl_at)); + __e_acsl_assert(__gen_e_acsl_valid_read,(char *)"RTE",(char *)"f", + (char *)"mem_access:\n \\valid_read(__gen_e_acsl_at + (int)((int)(__gen_e_acsl_n - 1) - 1))", + 7); + /*@ assert + Eva: initialization: + \initialized(__gen_e_acsl_at + ((__gen_e_acsl_n - 1) - 1)); + */ + if (*(__gen_e_acsl_at + ((__gen_e_acsl_n - 1) - 1))) { + int __gen_e_acsl_valid_read_2; + __gen_e_acsl_valid_read_2 = __e_acsl_valid_read((void *)(__gen_e_acsl_at_2 + (int)( + (long)((int)( + __gen_e_acsl_n - 1L)) - 1L)), + sizeof(int), + (void *)__gen_e_acsl_at_2, + (void *)(& __gen_e_acsl_at_2)); + __e_acsl_assert(__gen_e_acsl_valid_read_2,(char *)"RTE", + (char *)"f", + (char *)"mem_access:\n \\valid_read(__gen_e_acsl_at_2 + (int)((int)(__gen_e_acsl_n - 1) - 1))", + 7); + /*@ assert + Eva: initialization: + \initialized(__gen_e_acsl_at_2 + ((__gen_e_acsl_n - 1) - 1)); + */ + __gen_e_acsl_and = *(__gen_e_acsl_at_2 + ((__gen_e_acsl_n - 1) - 1)); + } + else __gen_e_acsl_and = 0; + if (__gen_e_acsl_and) ; + else { + __gen_e_acsl_forall = 0; + goto e_acsl_end_loop11; + } + } + __gen_e_acsl_n ++; + } + e_acsl_end_loop11: ; + __e_acsl_assert(__gen_e_acsl_forall,(char *)"Postcondition",(char *)"f", + (char *)"\\forall integer n;\n 1 < n <= 3 ==> \\old(*(t + n) == 12) && \\old(*(t + (n - 1)) > 5)", + 6); + __gen_e_acsl_m = 4; + __gen_e_acsl_valid_read_3 = __e_acsl_valid_read((void *)(__gen_e_acsl_at_3 + 0), + sizeof(int), + (void *)__gen_e_acsl_at_3, + (void *)(& __gen_e_acsl_at_3)); + __e_acsl_assert(__gen_e_acsl_valid_read_3,(char *)"RTE",(char *)"f", + (char *)"mem_access: \\valid_read(__gen_e_acsl_at_3 + 0)", + 8); + if (*(__gen_e_acsl_at_3 + 0)) { + int __gen_e_acsl_valid_read_4; + __gen_e_acsl_valid_read_4 = __e_acsl_valid_read((void *)(__gen_e_acsl_at_4 + 0), + sizeof(int), + (void *)__gen_e_acsl_at_4, + (void *)(& __gen_e_acsl_at_4)); + __e_acsl_assert(__gen_e_acsl_valid_read_4,(char *)"RTE",(char *)"f", + (char *)"mem_access: \\valid_read(__gen_e_acsl_at_4 + 0)", + 8); + __gen_e_acsl_and_2 = *(__gen_e_acsl_at_4 + 0) == 9; + } + else __gen_e_acsl_and_2 = 0; + __e_acsl_assert(__gen_e_acsl_and_2,(char *)"Postcondition",(char *)"f", + (char *)"\\let m = 4; \\old(*(t + m) == -4) && \\old(*(t + (m - 4))) == 9", + 8); + __e_acsl_delete_block((void *)(& t)); + free((void *)__gen_e_acsl_at_4); + free((void *)__gen_e_acsl_at_3); + free((void *)__gen_e_acsl_at_2); + free((void *)__gen_e_acsl_at); + return; + } +} + + diff --git a/src/plugins/e-acsl/tests/arith/oracle_ci/gen_cast.c b/src/plugins/e-acsl/tests/arith/oracle_ci/gen_cast.c new file mode 100644 index 0000000000000000000000000000000000000000..b11e400d36273bd589a8df0d920843dcbb5ed67a --- /dev/null +++ b/src/plugins/e-acsl/tests/arith/oracle_ci/gen_cast.c @@ -0,0 +1,36 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +int main(void) +{ + int __retres; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + long x = (long)0; + int y = 0; + /*@ assert (int)x ≡ y; */ + __e_acsl_assert((int)x == y,(char *)"Assertion",(char *)"main", + (char *)"(int)x == y",9); + /*@ assert x ≡ (long)y; */ + __e_acsl_assert(x == (long)y,(char *)"Assertion",(char *)"main", + (char *)"x == (long)y",10); + /*@ assert y ≡ (int)0; */ + __e_acsl_assert(y == 0,(char *)"Assertion",(char *)"main", + (char *)"y == (int)0",12); + /*@ assert (unsigned int)y ≡ (unsigned int)0; */ + __e_acsl_assert((unsigned int)y == 0U,(char *)"Assertion",(char *)"main", + (char *)"(unsigned int)y == (unsigned int)0",13); + /*@ assert y ≢ (int)0xfffffffffffffff; */ + __e_acsl_assert(y != -1,(char *)"Assertion",(char *)"main", + (char *)"y != (int)0xfffffffffffffff",16); + /*@ assert (unsigned int)y ≢ (unsigned int)0xfffffffffffffff; */ + __e_acsl_assert((unsigned int)y != 4294967295U,(char *)"Assertion", + (char *)"main", + (char *)"(unsigned int)y != (unsigned int)0xfffffffffffffff", + 17); + int t[2] = {0, 1}; + /*@ assert (float)x ≡ t[(int)0.1]; */ ; + __retres = 0; + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/arith/oracle_ci/gen_comparison.c b/src/plugins/e-acsl/tests/arith/oracle_ci/gen_comparison.c new file mode 100644 index 0000000000000000000000000000000000000000..b0c1147dfc2bad4102f5be378ccadab1d4d94c96 --- /dev/null +++ b/src/plugins/e-acsl/tests/arith/oracle_ci/gen_comparison.c @@ -0,0 +1,57 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +int main(void) +{ + int __retres; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + int x = 0; + int y = 1; + /*@ assert x < y; */ + __e_acsl_assert(x < y,(char *)"Assertion",(char *)"main",(char *)"x < y",7); + /*@ assert y > x; */ + __e_acsl_assert(y > x,(char *)"Assertion",(char *)"main",(char *)"y > x",8); + /*@ assert x ≤ 0; */ + __e_acsl_assert(x <= 0,(char *)"Assertion",(char *)"main",(char *)"x <= 0", + 9); + /*@ assert y ≥ 1; */ + __e_acsl_assert(y >= 1,(char *)"Assertion",(char *)"main",(char *)"y >= 1", + 10); + char *s = (char *)"toto"; + /*@ assert s ≡ s; */ + __e_acsl_assert(s == s,(char *)"Assertion",(char *)"main",(char *)"s == s", + 12); + /*@ assert 5 < 18; */ + __e_acsl_assert(1,(char *)"Assertion",(char *)"main",(char *)"5 < 18",15); + /*@ assert 32 > 3; */ + __e_acsl_assert(1,(char *)"Assertion",(char *)"main",(char *)"32 > 3",16); + /*@ assert 12 ≤ 13; */ + __e_acsl_assert(1,(char *)"Assertion",(char *)"main",(char *)"12 <= 13",17); + /*@ assert 123 ≥ 12; */ + __e_acsl_assert(1,(char *)"Assertion",(char *)"main",(char *)"123 >= 12", + 18); + /*@ assert 0xff ≡ 0xff; */ + __e_acsl_assert(1,(char *)"Assertion",(char *)"main", + (char *)"0xff == 0xff",19); + /*@ assert 1 ≢ 2; */ + __e_acsl_assert(1,(char *)"Assertion",(char *)"main",(char *)"1 != 2",20); + /*@ assert -5 < 18; */ + __e_acsl_assert(1,(char *)"Assertion",(char *)"main",(char *)"-5 < 18",22); + /*@ assert 32 > -3; */ + __e_acsl_assert(1,(char *)"Assertion",(char *)"main",(char *)"32 > -3",23); + /*@ assert -12 ≤ 13; */ + __e_acsl_assert(1,(char *)"Assertion",(char *)"main",(char *)"-12 <= 13", + 24); + /*@ assert 123 ≥ -12; */ + __e_acsl_assert(1,(char *)"Assertion",(char *)"main",(char *)"123 >= -12", + 25); + /*@ assert -0xff ≡ -0xff; */ + __e_acsl_assert(1,(char *)"Assertion",(char *)"main", + (char *)"-0xff == -0xff",26); + /*@ assert 1 ≢ -2; */ + __e_acsl_assert(1,(char *)"Assertion",(char *)"main",(char *)"1 != -2",27); + __retres = 0; + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/arith/oracle_ci/gen_functions.c b/src/plugins/e-acsl/tests/arith/oracle_ci/gen_functions.c new file mode 100644 index 0000000000000000000000000000000000000000..5137def7dd44ac3e15ab034d4680e7e1b3c29759 --- /dev/null +++ b/src/plugins/e-acsl/tests/arith/oracle_ci/gen_functions.c @@ -0,0 +1,385 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +extern int __e_acsl_sound_verdict; + +struct mystruct { + int k ; + int l ; +}; +typedef struct mystruct mystruct; +/*@ predicate p1(int x, int y) = x + y > 0; + */ +int __gen_e_acsl_p1(int x, int y); + +/*@ predicate p2(ℤ x, ℤ y) = x + y > 0; + +*/ +int __gen_e_acsl_p2(int x, int y); + +int __gen_e_acsl_p2_3(int x, __e_acsl_mpz_struct * y); + +int __gen_e_acsl_p2_5(int x, long y); + +/*@ logic ℤ f1(ℤ x, ℤ y) = x + y; + +*/ +long __gen_e_acsl_f1(int x, int y); + +void __gen_e_acsl_f1_5(__e_acsl_mpz_t *__retres_arg, int x, + __e_acsl_mpz_struct * y); + +void __gen_e_acsl_f1_7(__e_acsl_mpz_t *__retres_arg, __e_acsl_mpz_struct * x, + __e_acsl_mpz_struct * y); + +/*@ logic char h_char(char c) = c; + */ +int __gen_e_acsl_h_char(int c); + +/*@ logic short h_short(short s) = s; + */ +int __gen_e_acsl_h_short(int s); + +/*@ logic int g_hidden(int x) = x; + */ +int __gen_e_acsl_g_hidden(int x); + +/*@ logic int g(int x) = g_hidden(x); + */ +int __gen_e_acsl_g(int x); + +/*@ logic mystruct t1(mystruct m) = m; + */ +mystruct __gen_e_acsl_t1(mystruct m); + +/*@ logic ℤ t2(mystruct m) = m.k + m.l; + */ +long __gen_e_acsl_t2(mystruct m); + +/*@ predicate k_pred(ℤ x) = x > 0; + +*/ +int __gen_e_acsl_k_pred(int x); + +/*@ requires k_pred(x); */ +void __gen_e_acsl_k(int x); + +void k(int x) +{ + return; +} + +int glob = 5; +/*@ predicate never_called(int x) = x ≡ x; + */ +/*@ logic double f2(double x) = (double)(1 / x); + */ +double __gen_e_acsl_f2(double x); + +/*@ predicate p_notyet{L}(ℤ x) = x > 0; + */ +/*@ logic ℤ f_notyet{L}(ℤ x) = x; + +*/ +int main(void) +{ + int __retres; + mystruct m; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + int x = 1; + int y = 2; + /*@ assert p1(x, y); */ + { + int __gen_e_acsl_p1_2; + __gen_e_acsl_p1_2 = __gen_e_acsl_p1(x,y); + __e_acsl_assert(__gen_e_acsl_p1_2,(char *)"Assertion",(char *)"main", + (char *)"p1(x, y)",42); + } + /*@ assert p2(3, 4); */ + { + int __gen_e_acsl_p2_2; + __gen_e_acsl_p2_2 = __gen_e_acsl_p2(3,4); + __e_acsl_assert(__gen_e_acsl_p2_2,(char *)"Assertion",(char *)"main", + (char *)"p2(3, 4)",43); + } + /*@ assert p2(5, 99999999999999999999999999999); */ + { + __e_acsl_mpz_t __gen_e_acsl_; + int __gen_e_acsl_p2_4; + __gmpz_init_set_str(__gen_e_acsl_,"99999999999999999999999999999",10); + __gen_e_acsl_p2_4 = __gen_e_acsl_p2_3(5, + (__e_acsl_mpz_struct *)__gen_e_acsl_); + __e_acsl_assert(__gen_e_acsl_p2_4,(char *)"Assertion",(char *)"main", + (char *)"p2(5, 99999999999999999999999999999)",44); + __gmpz_clear(__gen_e_acsl_); + } + /*@ assert f1(x, y) ≡ 3; */ + { + long __gen_e_acsl_f1_2; + __gen_e_acsl_f1_2 = __gen_e_acsl_f1(x,y); + __e_acsl_assert(__gen_e_acsl_f1_2 == 3L,(char *)"Assertion", + (char *)"main",(char *)"f1(x, y) == 3",46); + } + /*@ assert p2(x, f1(3, 4)); */ + { + long __gen_e_acsl_f1_4; + int __gen_e_acsl_p2_6; + __gen_e_acsl_f1_4 = __gen_e_acsl_f1(3,4); + __gen_e_acsl_p2_6 = __gen_e_acsl_p2_5(x,__gen_e_acsl_f1_4); + __e_acsl_assert(__gen_e_acsl_p2_6,(char *)"Assertion",(char *)"main", + (char *)"p2(x, f1(3, 4))",47); + } + /*@ assert f1(9, 99999999999999999999999999999) > 0; */ + { + __e_acsl_mpz_t __gen_e_acsl__4; + __e_acsl_mpz_t __gen_e_acsl_f1_6; + __e_acsl_mpz_t __gen_e_acsl__5; + int __gen_e_acsl_gt_3; + __gmpz_init_set_str(__gen_e_acsl__4,"99999999999999999999999999999",10); + __gen_e_acsl_f1_5(& __gen_e_acsl_f1_6,9, + (__e_acsl_mpz_struct *)__gen_e_acsl__4); + __gmpz_init_set_si(__gen_e_acsl__5,0L); + __gen_e_acsl_gt_3 = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_f1_6), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__5)); + __e_acsl_assert(__gen_e_acsl_gt_3 > 0,(char *)"Assertion",(char *)"main", + (char *)"f1(9, 99999999999999999999999999999) > 0",48); + __gmpz_clear(__gen_e_acsl__4); + __gmpz_clear(__gen_e_acsl_f1_6); + __gmpz_clear(__gen_e_acsl__5); + } + /*@ assert + f1(99999999999999999999999999999, 99999999999999999999999999999) ≡ + 199999999999999999999999999998; + */ + { + __e_acsl_mpz_t __gen_e_acsl__6; + __e_acsl_mpz_t __gen_e_acsl_f1_8; + __e_acsl_mpz_t __gen_e_acsl__7; + int __gen_e_acsl_eq; + __gmpz_init_set_str(__gen_e_acsl__6,"99999999999999999999999999999",10); + __gen_e_acsl_f1_7(& __gen_e_acsl_f1_8, + (__e_acsl_mpz_struct *)__gen_e_acsl__6, + (__e_acsl_mpz_struct *)__gen_e_acsl__6); + __gmpz_init_set_str(__gen_e_acsl__7,"199999999999999999999999999998",10); + __gen_e_acsl_eq = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_f1_8), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__7)); + __e_acsl_assert(__gen_e_acsl_eq == 0,(char *)"Assertion",(char *)"main", + (char *)"f1(99999999999999999999999999999, 99999999999999999999999999999) ==\n199999999999999999999999999998", + 49); + __gmpz_clear(__gen_e_acsl__6); + __gmpz_clear(__gen_e_acsl_f1_8); + __gmpz_clear(__gen_e_acsl__7); + } + /*@ assert g(x) ≡ x; */ + { + int __gen_e_acsl_g_2; + __gen_e_acsl_g_2 = __gen_e_acsl_g(x); + __e_acsl_assert(__gen_e_acsl_g_2 == x,(char *)"Assertion",(char *)"main", + (char *)"g(x) == x",53); + } + char c = (char)'c'; + /*@ assert h_char(c) ≡ c; */ + { + int __gen_e_acsl_h_char_2; + __gen_e_acsl_h_char_2 = __gen_e_acsl_h_char((int)c); + __e_acsl_assert(__gen_e_acsl_h_char_2 == (int)c,(char *)"Assertion", + (char *)"main",(char *)"h_char(c) == c",56); + } + short s = (short)1; + /*@ assert h_short(s) ≡ s; */ + { + int __gen_e_acsl_h_short_2; + __gen_e_acsl_h_short_2 = __gen_e_acsl_h_short((int)s); + __e_acsl_assert(__gen_e_acsl_h_short_2 == (int)s,(char *)"Assertion", + (char *)"main",(char *)"h_short(s) == s",58); + } + m.k = 8; + m.l = 9; + /*@ assert t2(t1(m)) ≡ 17; */ + { + mystruct __gen_e_acsl_t1_2; + long __gen_e_acsl_t2_2; + __gen_e_acsl_t1_2 = __gen_e_acsl_t1(m); + __gen_e_acsl_t2_2 = __gen_e_acsl_t2(__gen_e_acsl_t1_2); + __e_acsl_assert(__gen_e_acsl_t2_2 == 17L,(char *)"Assertion", + (char *)"main",(char *)"t2(t1(m)) == 17",63); + } + __gen_e_acsl_k(9); + double d = 2.0; + /*@ assert f2(d) > 0; */ + { + double __gen_e_acsl_f2_2; + __gen_e_acsl_f2_2 = __gen_e_acsl_f2(d); + __e_acsl_assert(__gen_e_acsl_f2_2 > 0.,(char *)"Assertion", + (char *)"main",(char *)"f2(d) > 0",68); + } + __retres = 0; + return __retres; +} + +/*@ requires k_pred(x); */ +void __gen_e_acsl_k(int x) +{ + { + int __gen_e_acsl_k_pred_2; + __gen_e_acsl_k_pred_2 = __gen_e_acsl_k_pred(x); + __e_acsl_assert(__gen_e_acsl_k_pred_2,(char *)"Precondition",(char *)"k", + (char *)"k_pred(x)",25); + } + k(x); + return; +} + +int __gen_e_acsl_h_char(int c) +{ + return c; +} + +int __gen_e_acsl_h_short(int s) +{ + return s; +} + +int __gen_e_acsl_g_hidden(int x) +{ + return x; +} + +double __gen_e_acsl_f2(double x) +{ + __e_acsl_mpq_t __gen_e_acsl__8; + __e_acsl_mpq_t __gen_e_acsl__9; + __e_acsl_mpq_t __gen_e_acsl_div; + double __gen_e_acsl__10; + __gmpq_init(__gen_e_acsl__8); + __gmpq_set_str(__gen_e_acsl__8,"1",10); + __gmpq_init(__gen_e_acsl__9); + __gmpq_set_d(__gen_e_acsl__9,x); + __gmpq_init(__gen_e_acsl_div); + __gmpq_div(__gen_e_acsl_div,(__e_acsl_mpq_struct const *)(__gen_e_acsl__8), + (__e_acsl_mpq_struct const *)(__gen_e_acsl__9)); + __gen_e_acsl__10 = __gmpq_get_d((__e_acsl_mpq_struct const *)(__gen_e_acsl_div)); + __gmpq_clear(__gen_e_acsl__8); + __gmpq_clear(__gen_e_acsl__9); + __gmpq_clear(__gen_e_acsl_div); + /*@ assert Eva: is_nan_or_infinite: \is_finite(__gen_e_acsl__10); */ + return __gen_e_acsl__10; +} + +int __gen_e_acsl_g(int x) +{ + int __gen_e_acsl_g_hidden_2; + __gen_e_acsl_g_hidden_2 = __gen_e_acsl_g_hidden(x); + return __gen_e_acsl_g_hidden_2; +} + +mystruct __gen_e_acsl_t1(mystruct m) +{ + return m; +} + +int __gen_e_acsl_p1(int x, int y) +{ + int __retres = x + (long)y > 0L; + return __retres; +} + +long __gen_e_acsl_t2(mystruct m) +{ + long __retres = m.k + (long)m.l; + return __retres; +} + +int __gen_e_acsl_p2(int x, int y) +{ + int __retres = x + (long)y > 0L; + return __retres; +} + +int __gen_e_acsl_p2_3(int x, __e_acsl_mpz_struct * y) +{ + __e_acsl_mpz_t __gen_e_acsl_x; + __e_acsl_mpz_t __gen_e_acsl_add; + __e_acsl_mpz_t __gen_e_acsl__2; + int __gen_e_acsl_gt; + __gmpz_init_set_si(__gen_e_acsl_x,(long)x); + __gmpz_init(__gen_e_acsl_add); + __gmpz_add(__gen_e_acsl_add,(__e_acsl_mpz_struct const *)(__gen_e_acsl_x), + (__e_acsl_mpz_struct const *)(y)); + __gmpz_init_set_si(__gen_e_acsl__2,0L); + __gen_e_acsl_gt = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_add), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__2)); + int __retres = __gen_e_acsl_gt > 0; + __gmpz_clear(__gen_e_acsl_x); + __gmpz_clear(__gen_e_acsl_add); + __gmpz_clear(__gen_e_acsl__2); + return __retres; +} + +int __gen_e_acsl_p2_5(int x, long y) +{ + __e_acsl_mpz_t __gen_e_acsl_x_2; + __e_acsl_mpz_t __gen_e_acsl_y; + __e_acsl_mpz_t __gen_e_acsl_add_2; + __e_acsl_mpz_t __gen_e_acsl__3; + int __gen_e_acsl_gt_2; + __gmpz_init_set_si(__gen_e_acsl_x_2,(long)x); + __gmpz_init_set_si(__gen_e_acsl_y,y); + __gmpz_init(__gen_e_acsl_add_2); + __gmpz_add(__gen_e_acsl_add_2, + (__e_acsl_mpz_struct const *)(__gen_e_acsl_x_2), + (__e_acsl_mpz_struct const *)(__gen_e_acsl_y)); + __gmpz_init_set_si(__gen_e_acsl__3,0L); + __gen_e_acsl_gt_2 = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_add_2), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__3)); + int __retres = __gen_e_acsl_gt_2 > 0; + __gmpz_clear(__gen_e_acsl_x_2); + __gmpz_clear(__gen_e_acsl_y); + __gmpz_clear(__gen_e_acsl_add_2); + __gmpz_clear(__gen_e_acsl__3); + return __retres; +} + +int __gen_e_acsl_k_pred(int x) +{ + int __retres = x > 0; + return __retres; +} + +long __gen_e_acsl_f1(int x, int y) +{ + long __retres = x + (long)y; + return __retres; +} + +void __gen_e_acsl_f1_5(__e_acsl_mpz_t *__retres_arg, int x, + __e_acsl_mpz_struct * y) +{ + __e_acsl_mpz_t __gen_e_acsl_x_3; + __e_acsl_mpz_t __gen_e_acsl_add_3; + __gmpz_init_set_si(__gen_e_acsl_x_3,(long)x); + __gmpz_init(__gen_e_acsl_add_3); + __gmpz_add(__gen_e_acsl_add_3, + (__e_acsl_mpz_struct const *)(__gen_e_acsl_x_3), + (__e_acsl_mpz_struct const *)(y)); + __gmpz_init_set(*__retres_arg, + (__e_acsl_mpz_struct const *)(__gen_e_acsl_add_3)); + __gmpz_clear(__gen_e_acsl_x_3); + __gmpz_clear(__gen_e_acsl_add_3); + return; +} + +void __gen_e_acsl_f1_7(__e_acsl_mpz_t *__retres_arg, __e_acsl_mpz_struct * x, + __e_acsl_mpz_struct * y) +{ + __e_acsl_mpz_t __gen_e_acsl_add_4; + __gmpz_init(__gen_e_acsl_add_4); + __gmpz_add(__gen_e_acsl_add_4,(__e_acsl_mpz_struct const *)(x), + (__e_acsl_mpz_struct const *)(y)); + __gmpz_init_set(*__retres_arg, + (__e_acsl_mpz_struct const *)(__gen_e_acsl_add_4)); + __gmpz_clear(__gen_e_acsl_add_4); + return; +} + + diff --git a/src/plugins/e-acsl/tests/arith/oracle_ci/gen_functions_rec.c b/src/plugins/e-acsl/tests/arith/oracle_ci/gen_functions_rec.c new file mode 100644 index 0000000000000000000000000000000000000000..cbed6cde4bbd135b2cea1b8f75cc2466cfb41af6 --- /dev/null +++ b/src/plugins/e-acsl/tests/arith/oracle_ci/gen_functions_rec.c @@ -0,0 +1,319 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +/*@ logic ℤ f1(ℤ n) = n ≤ 0? 0: f1(n - 1) + n; + +*/ +void __gen_e_acsl_f1(__e_acsl_mpz_t *__retres_arg, int n); + +void __gen_e_acsl_f1_2(__e_acsl_mpz_t *__retres_arg, long n); + +/*@ logic ℤ f2(ℤ n) = n < 0? 1: (f2(n - 1) * f2(n - 2)) / f2(n - 3); + */ +int __gen_e_acsl_f2(int n); + +int __gen_e_acsl_f2_2(long n); + +/*@ logic ℤ g(ℤ n) = 0; + */ +int __gen_e_acsl_g(int n); + +int __gen_e_acsl_g_5(long n); + +/*@ logic ℤ f3(ℤ n) = n > 0? g(n) * f3(n - 1) - 5: g(n + 1); + */ +int __gen_e_acsl_f3(int n); + +int __gen_e_acsl_f3_2(long n); + +/*@ +logic ℤ f4(ℤ n) = + n < 100? f4(n + 1): (n < 0x7fffffffffffffffL? 0x7fffffffffffffffL: 6); + +*/ +unsigned long __gen_e_acsl_f4(int n); + +unsigned long __gen_e_acsl_f4_2(long n); + +int main(void) +{ + int __retres; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + /*@ assert f1(0) ≡ 0; */ + { + __e_acsl_mpz_t __gen_e_acsl_f1_6; + __e_acsl_mpz_t __gen_e_acsl__3; + int __gen_e_acsl_eq; + __gen_e_acsl_f1(& __gen_e_acsl_f1_6,0); + __gmpz_init_set_si(__gen_e_acsl__3,0L); + __gen_e_acsl_eq = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_f1_6), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__3)); + __e_acsl_assert(__gen_e_acsl_eq == 0,(char *)"Assertion",(char *)"main", + (char *)"f1(0) == 0",22); + __gmpz_clear(__gen_e_acsl_f1_6); + __gmpz_clear(__gen_e_acsl__3); + } + /*@ assert f1(1) ≡ 1; */ + { + __e_acsl_mpz_t __gen_e_acsl_f1_8; + __e_acsl_mpz_t __gen_e_acsl__4; + int __gen_e_acsl_eq_2; + __gen_e_acsl_f1(& __gen_e_acsl_f1_8,1); + __gmpz_init_set_si(__gen_e_acsl__4,1L); + __gen_e_acsl_eq_2 = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_f1_8), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__4)); + __e_acsl_assert(__gen_e_acsl_eq_2 == 0,(char *)"Assertion", + (char *)"main",(char *)"f1(1) == 1",23); + __gmpz_clear(__gen_e_acsl_f1_8); + __gmpz_clear(__gen_e_acsl__4); + } + /*@ assert f1(100) ≡ 5050; */ + { + __e_acsl_mpz_t __gen_e_acsl_f1_10; + __e_acsl_mpz_t __gen_e_acsl__5; + int __gen_e_acsl_eq_3; + __gen_e_acsl_f1(& __gen_e_acsl_f1_10,100); + __gmpz_init_set_si(__gen_e_acsl__5,5050L); + __gen_e_acsl_eq_3 = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_f1_10), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__5)); + __e_acsl_assert(__gen_e_acsl_eq_3 == 0,(char *)"Assertion", + (char *)"main",(char *)"f1(100) == 5050",24); + __gmpz_clear(__gen_e_acsl_f1_10); + __gmpz_clear(__gen_e_acsl__5); + } + /*@ assert f2(7) ≡ 1; */ + { + int __gen_e_acsl_f2_14; + __gen_e_acsl_f2_14 = __gen_e_acsl_f2(7); + __e_acsl_assert(__gen_e_acsl_f2_14 == 1,(char *)"Assertion", + (char *)"main",(char *)"f2(7) == 1",26); + } + /*@ assert f3(6) ≡ -5; */ + { + int __gen_e_acsl_f3_6; + __gen_e_acsl_f3_6 = __gen_e_acsl_f3(6); + __e_acsl_assert(__gen_e_acsl_f3_6 == -5,(char *)"Assertion", + (char *)"main",(char *)"f3(6) == -5",28); + } + /*@ assert f4(9) > 0; */ + { + unsigned long __gen_e_acsl_f4_6; + __gen_e_acsl_f4_6 = __gen_e_acsl_f4(9); + __e_acsl_assert(__gen_e_acsl_f4_6 > 0UL,(char *)"Assertion", + (char *)"main",(char *)"f4(9) > 0",30); + } + __retres = 0; + return __retres; +} + +void __gen_e_acsl_f1(__e_acsl_mpz_t *__retres_arg, int n) +{ + __e_acsl_mpz_t __gen_e_acsl_if_2; + if (n <= 0) { + __e_acsl_mpz_t __gen_e_acsl_; + __gmpz_init_set_si(__gen_e_acsl_,0L); + __gmpz_init_set(__gen_e_acsl_if_2, + (__e_acsl_mpz_struct const *)(__gen_e_acsl_)); + __gmpz_clear(__gen_e_acsl_); + } + else { + __e_acsl_mpz_t __gen_e_acsl_f1_5; + __e_acsl_mpz_t __gen_e_acsl_n_2; + __e_acsl_mpz_t __gen_e_acsl_add_2; + __gen_e_acsl_f1_2(& __gen_e_acsl_f1_5,n - 1L); + __gmpz_init_set_si(__gen_e_acsl_n_2,(long)n); + __gmpz_init(__gen_e_acsl_add_2); + __gmpz_add(__gen_e_acsl_add_2, + (__e_acsl_mpz_struct const *)(__gen_e_acsl_f1_5), + (__e_acsl_mpz_struct const *)(__gen_e_acsl_n_2)); + __gmpz_init_set(__gen_e_acsl_if_2, + (__e_acsl_mpz_struct const *)(__gen_e_acsl_add_2)); + __gmpz_clear(__gen_e_acsl_f1_5); + __gmpz_clear(__gen_e_acsl_n_2); + __gmpz_clear(__gen_e_acsl_add_2); + } + __gmpz_init_set(*__retres_arg, + (__e_acsl_mpz_struct const *)(__gen_e_acsl_if_2)); + __gmpz_clear(__gen_e_acsl_if_2); + return; +} + +void __gen_e_acsl_f1_2(__e_acsl_mpz_t *__retres_arg, long n) +{ + __e_acsl_mpz_t __gen_e_acsl_if; + if (n <= 0L) { + __e_acsl_mpz_t __gen_e_acsl__2; + __gmpz_init_set_si(__gen_e_acsl__2,0L); + __gmpz_init_set(__gen_e_acsl_if, + (__e_acsl_mpz_struct const *)(__gen_e_acsl__2)); + __gmpz_clear(__gen_e_acsl__2); + } + else { + __e_acsl_mpz_t __gen_e_acsl_f1_4; + __e_acsl_mpz_t __gen_e_acsl_n; + __e_acsl_mpz_t __gen_e_acsl_add; + __gen_e_acsl_f1_2(& __gen_e_acsl_f1_4,n - 1L); + __gmpz_init_set_si(__gen_e_acsl_n,n); + __gmpz_init(__gen_e_acsl_add); + __gmpz_add(__gen_e_acsl_add, + (__e_acsl_mpz_struct const *)(__gen_e_acsl_f1_4), + (__e_acsl_mpz_struct const *)(__gen_e_acsl_n)); + __gmpz_init_set(__gen_e_acsl_if, + (__e_acsl_mpz_struct const *)(__gen_e_acsl_add)); + __gmpz_clear(__gen_e_acsl_f1_4); + __gmpz_clear(__gen_e_acsl_n); + __gmpz_clear(__gen_e_acsl_add); + } + __gmpz_init_set(*__retres_arg, + (__e_acsl_mpz_struct const *)(__gen_e_acsl_if)); + __gmpz_clear(__gen_e_acsl_if); + return; +} + +int __gen_e_acsl_f2(int n) +{ + int __gen_e_acsl_if_4; + if (n < 0) __gen_e_acsl_if_4 = 1; + else { + int __gen_e_acsl_f2_9; + int __gen_e_acsl_f2_11; + int __gen_e_acsl_f2_13; + __gen_e_acsl_f2_9 = __gen_e_acsl_f2_2(n - 1L); + __gen_e_acsl_f2_11 = __gen_e_acsl_f2_2(n - 2L); + __gen_e_acsl_f2_13 = __gen_e_acsl_f2_2(n - 3L); + __e_acsl_assert(__gen_e_acsl_f2_13 != 0,(char *)"RTE",(char *)"f2", + (char *)"division_by_zero: __gen_e_acsl_f2_13 != 0",10); + /*@ assert Eva: division_by_zero: __gen_e_acsl_f2_13 ≢ 0; */ + /*@ assert + Eva: signed_overflow: + -2147483648 ≤ __gen_e_acsl_f2_9 * __gen_e_acsl_f2_11; + */ + /*@ assert + Eva: signed_overflow: + __gen_e_acsl_f2_9 * __gen_e_acsl_f2_11 ≤ 2147483647; + */ + /*@ assert + Eva: signed_overflow: + (int)(__gen_e_acsl_f2_9 * __gen_e_acsl_f2_11) / __gen_e_acsl_f2_13 + ≤ 2147483647; + */ + __gen_e_acsl_if_4 = (__gen_e_acsl_f2_9 * __gen_e_acsl_f2_11) / __gen_e_acsl_f2_13; + } + return __gen_e_acsl_if_4; +} + +int __gen_e_acsl_f2_2(long n) +{ + int __gen_e_acsl_if_3; + if (n < 0L) __gen_e_acsl_if_3 = 1; + else { + int __gen_e_acsl_f2_4; + int __gen_e_acsl_f2_6; + int __gen_e_acsl_f2_8; + __gen_e_acsl_f2_4 = __gen_e_acsl_f2_2(n - 1L); + __gen_e_acsl_f2_6 = __gen_e_acsl_f2_2(n - 2L); + __gen_e_acsl_f2_8 = __gen_e_acsl_f2_2(n - 3L); + __e_acsl_assert(__gen_e_acsl_f2_8 != 0,(char *)"RTE",(char *)"f2_2", + (char *)"division_by_zero: __gen_e_acsl_f2_8 != 0",10); + /*@ assert Eva: division_by_zero: __gen_e_acsl_f2_8 ≢ 0; */ + /*@ assert + Eva: signed_overflow: + -2147483648 ≤ __gen_e_acsl_f2_4 * __gen_e_acsl_f2_6; + */ + /*@ assert + Eva: signed_overflow: + __gen_e_acsl_f2_4 * __gen_e_acsl_f2_6 ≤ 2147483647; + */ + /*@ assert + Eva: signed_overflow: + (int)(__gen_e_acsl_f2_4 * __gen_e_acsl_f2_6) / __gen_e_acsl_f2_8 + ≤ 2147483647; + */ + __gen_e_acsl_if_3 = (__gen_e_acsl_f2_4 * __gen_e_acsl_f2_6) / __gen_e_acsl_f2_8; + } + return __gen_e_acsl_if_3; +} + +int __gen_e_acsl_g(int n) +{ + int __retres = 0; + return __retres; +} + +int __gen_e_acsl_g_5(long n) +{ + int __retres = 0; + return __retres; +} + +int __gen_e_acsl_f3(int n) +{ + int __gen_e_acsl_if_6; + if (n > 0) { + int __gen_e_acsl_g_2; + int __gen_e_acsl_f3_5; + __gen_e_acsl_g_2 = __gen_e_acsl_g(n); + __gen_e_acsl_f3_5 = __gen_e_acsl_f3_2(n - 1L); + __gen_e_acsl_if_6 = __gen_e_acsl_g_2 * __gen_e_acsl_f3_5 - 5; + } + else { + int __gen_e_acsl_g_8; + __gen_e_acsl_g_8 = __gen_e_acsl_g_5(n + 1L); + __gen_e_acsl_if_6 = __gen_e_acsl_g_8; + } + return __gen_e_acsl_if_6; +} + +int __gen_e_acsl_f3_2(long n) +{ + int __gen_e_acsl_if_5; + if (n > 0L) { + int __gen_e_acsl_g_4; + int __gen_e_acsl_f3_4; + __gen_e_acsl_g_4 = __gen_e_acsl_g((int)n); + __gen_e_acsl_f3_4 = __gen_e_acsl_f3_2(n - 1L); + __gen_e_acsl_if_5 = __gen_e_acsl_g_4 * __gen_e_acsl_f3_4 - 5; + } + else { + int __gen_e_acsl_g_6; + __gen_e_acsl_g_6 = __gen_e_acsl_g_5(n + 1L); + __gen_e_acsl_if_5 = __gen_e_acsl_g_6; + } + return __gen_e_acsl_if_5; +} + +unsigned long __gen_e_acsl_f4(int n) +{ + unsigned long __gen_e_acsl_if_10; + if (n < 100) { + unsigned long __gen_e_acsl_f4_5; + __gen_e_acsl_f4_5 = __gen_e_acsl_f4_2(n + 1L); + __gen_e_acsl_if_10 = __gen_e_acsl_f4_5; + } + else { + unsigned long __gen_e_acsl_if_9; + if ((long)n < 9223372036854775807L) __gen_e_acsl_if_9 = 9223372036854775807UL; + else __gen_e_acsl_if_9 = 6UL; + __gen_e_acsl_if_10 = __gen_e_acsl_if_9; + } + return __gen_e_acsl_if_10; +} + +unsigned long __gen_e_acsl_f4_2(long n) +{ + unsigned long __gen_e_acsl_if_8; + if (n < 100L) { + unsigned long __gen_e_acsl_f4_4; + __gen_e_acsl_f4_4 = __gen_e_acsl_f4_2(n + 1L); + __gen_e_acsl_if_8 = __gen_e_acsl_f4_4; + } + else { + unsigned long __gen_e_acsl_if_7; + if (n < 9223372036854775807L) __gen_e_acsl_if_7 = 9223372036854775807UL; + else __gen_e_acsl_if_7 = 6UL; + __gen_e_acsl_if_8 = __gen_e_acsl_if_7; + } + return __gen_e_acsl_if_8; +} + + diff --git a/src/plugins/e-acsl/tests/arith/oracle_ci/gen_integer_constant.c b/src/plugins/e-acsl/tests/arith/oracle_ci/gen_integer_constant.c new file mode 100644 index 0000000000000000000000000000000000000000..8c665a18a4dc57fe8f21e2f1aec23f78335fb14f --- /dev/null +++ b/src/plugins/e-acsl/tests/arith/oracle_ci/gen_integer_constant.c @@ -0,0 +1,38 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +int main(void) +{ + int __retres; + int x; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + /*@ assert 0 ≡ 0; */ + __e_acsl_assert(1,(char *)"Assertion",(char *)"main",(char *)"0 == 0",6); + x = 0; + x ++; + /*@ assert 0 ≢ 1; */ + __e_acsl_assert(1,(char *)"Assertion",(char *)"main",(char *)"0 != 1",8); + /*@ assert 1152921504606846975 ≡ 0xfffffffffffffff; */ + __e_acsl_assert(1,(char *)"Assertion",(char *)"main", + (char *)"1152921504606846975 == 0xfffffffffffffff",9); + /*@ assert + 0xffffffffffffffffffffffffffffffff ≡ + 0xffffffffffffffffffffffffffffffff; + */ + { + __e_acsl_mpz_t __gen_e_acsl_; + int __gen_e_acsl_eq; + __gmpz_init_set_str(__gen_e_acsl_, + "340282366920938463463374607431768211455",10); + __gen_e_acsl_eq = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_), + (__e_acsl_mpz_struct const *)(__gen_e_acsl_)); + __e_acsl_assert(__gen_e_acsl_eq == 0,(char *)"Assertion",(char *)"main", + (char *)"0xffffffffffffffffffffffffffffffff == 0xffffffffffffffffffffffffffffffff", + 11); + __gmpz_clear(__gen_e_acsl_); + } + __retres = 0; + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/arith/oracle_ci/gen_let.c b/src/plugins/e-acsl/tests/arith/oracle_ci/gen_let.c new file mode 100644 index 0000000000000000000000000000000000000000..33945c99959a19ca4e19697417b5ab475b0bf7d6 --- /dev/null +++ b/src/plugins/e-acsl/tests/arith/oracle_ci/gen_let.c @@ -0,0 +1,141 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +struct __anonstruct_r_1 { + int x ; + int y ; +}; +union __anonunion_s_2 { + int x ; + char *y ; +}; +int main(void) +{ + int __retres; + union __anonunion_s_2 s; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + int n = -2; + /*@ assert \let u = n * n; u ≥ 0; */ + { + long __gen_e_acsl_u; + __gen_e_acsl_u = n * (long)n; + __e_acsl_assert(__gen_e_acsl_u >= 0L,(char *)"Assertion",(char *)"main", + (char *)"\\let u = n * n; u >= 0",7); + } + /*@ assert \let u = n * n; \let v = u + 1; u > 0; */ + { + long __gen_e_acsl_u_2; + long __gen_e_acsl_v; + __gen_e_acsl_u_2 = n * (long)n; + __gen_e_acsl_v = __gen_e_acsl_u_2 + 1L; + __e_acsl_assert(__gen_e_acsl_u_2 > 0L,(char *)"Assertion",(char *)"main", + (char *)"\\let u = n * n;\n\\let v = u + 1; u > 0",9); + } + /*@ assert (\let u = 1; u) + 1 ≡ 2; */ + { + int __gen_e_acsl_u_3; + __gen_e_acsl_u_3 = 1; + __e_acsl_assert(__gen_e_acsl_u_3 + 1 == 2,(char *)"Assertion", + (char *)"main",(char *)"(\\let u = 1; u) + 1 == 2",12); + } + /*@ assert \let u = 1; (\let v = u + 1; v) ≡ 2; */ + { + int __gen_e_acsl_u_4; + int __gen_e_acsl_v_2; + __gen_e_acsl_u_4 = 1; + __gen_e_acsl_v_2 = __gen_e_acsl_u_4 + 1; + __e_acsl_assert(__gen_e_acsl_v_2 == 2,(char *)"Assertion",(char *)"main", + (char *)"\\let u = 1; (\\let v = u + 1; v) == 2",14); + } + /*@ assert \let u = 1; (\let u = u + 1; u) ≡ 2; */ + { + int __gen_e_acsl_u_5; + int __gen_e_acsl_u_6; + __gen_e_acsl_u_5 = 1; + __gen_e_acsl_u_6 = __gen_e_acsl_u_5 + 1; + __e_acsl_assert(__gen_e_acsl_u_6 == 2,(char *)"Assertion",(char *)"main", + (char *)"\\let u = 1; (\\let u = u + 1; u) == 2",17); + } + long m = 0x7fffffffffffffffL; + /*@ assert (\let u = m; u * u) > m; */ + { + long __gen_e_acsl_u_7; + __e_acsl_mpz_t __gen_e_acsl_u_8; + __e_acsl_mpz_t __gen_e_acsl_mul; + __e_acsl_mpz_t __gen_e_acsl_m; + int __gen_e_acsl_gt; + __gen_e_acsl_u_7 = m; + __gmpz_init_set_si(__gen_e_acsl_u_8,__gen_e_acsl_u_7); + __gmpz_init(__gen_e_acsl_mul); + __gmpz_mul(__gen_e_acsl_mul, + (__e_acsl_mpz_struct const *)(__gen_e_acsl_u_8), + (__e_acsl_mpz_struct const *)(__gen_e_acsl_u_8)); + __gmpz_init_set_si(__gen_e_acsl_m,m); + __gen_e_acsl_gt = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_mul), + (__e_acsl_mpz_struct const *)(__gen_e_acsl_m)); + __e_acsl_assert(__gen_e_acsl_gt > 0,(char *)"Assertion",(char *)"main", + (char *)"(\\let u = m; u * u) > m",21); + __gmpz_clear(__gen_e_acsl_u_8); + __gmpz_clear(__gen_e_acsl_mul); + __gmpz_clear(__gen_e_acsl_m); + } + char c = (char)'a'; + /*@ assert \let u = 'b'; c < u; */ + { + int __gen_e_acsl_u_9; + __gen_e_acsl_u_9 = 'b'; + __e_acsl_assert((int)c < __gen_e_acsl_u_9,(char *)"Assertion", + (char *)"main",(char *)"\\let u = \'b\'; c < u",24); + } + float f = 1.0f; + __e_acsl_store_block((void *)(& f),(size_t)4); + __e_acsl_full_init((void *)(& f)); + /*@ assert \let u = f; u ≡ f; */ + { + float __gen_e_acsl_u_10; + __gen_e_acsl_u_10 = f; + __e_acsl_assert(__gen_e_acsl_u_10 == f,(char *)"Assertion", + (char *)"main",(char *)"\\let u = f; u == f",27); + } + int t[4] = {1, 2, 3, 4}; + /*@ assert \let u = &t[1]; 1 ≡ 1; */ + { + int * /*[4]*/ __gen_e_acsl_u_11; + __gen_e_acsl_u_11 = & t[1]; + __e_acsl_assert(1,(char *)"Assertion",(char *)"main", + (char *)"\\let u = &t[1]; 1 == 1",30); + } + /*@ assert (\let u = &t[1]; 1) ≡ 1; */ + { + int * /*[4]*/ __gen_e_acsl_u_12; + __gen_e_acsl_u_12 = & t[1]; + __e_acsl_assert(1,(char *)"Assertion",(char *)"main", + (char *)"(\\let u = &t[1]; 1) == 1",32); + } + struct __anonstruct_r_1 r = {.x = 1, .y = 2}; + __e_acsl_store_block((void *)(& r),(size_t)8); + __e_acsl_full_init((void *)(& r)); + /*@ assert \let u = r; u.x + u.y ≡ 3; */ + { + struct __anonstruct_r_1 __gen_e_acsl_u_13; + __gen_e_acsl_u_13 = r; + __e_acsl_assert(__gen_e_acsl_u_13.x + (long)__gen_e_acsl_u_13.y == 3L, + (char *)"Assertion",(char *)"main", + (char *)"\\let u = r; u.x + u.y == 3",35); + } + s.x = 5; + /*@ assert (\let u = s; u.x) > 0; */ + { + union __anonunion_s_2 __gen_e_acsl_u_14; + __gen_e_acsl_u_14 = s; + __e_acsl_assert(__gen_e_acsl_u_14.x > 0,(char *)"Assertion", + (char *)"main",(char *)"(\\let u = s; u.x) > 0",39); + } + __retres = 0; + __e_acsl_delete_block((void *)(& r)); + __e_acsl_delete_block((void *)(& f)); + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/arith/oracle_ci/gen_longlong.c b/src/plugins/e-acsl/tests/arith/oracle_ci/gen_longlong.c new file mode 100644 index 0000000000000000000000000000000000000000..fb9c180c46dfceede209d330ed3a35eb3b270354 --- /dev/null +++ b/src/plugins/e-acsl/tests/arith/oracle_ci/gen_longlong.c @@ -0,0 +1,79 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +unsigned long long my_pow(unsigned int x, unsigned int n) +{ + unsigned long long __retres; + int tmp; + unsigned long long tmp_0; + if (n <= (unsigned int)1) { + __retres = (unsigned long long)1; + goto return_label; + } + tmp_0 = my_pow(x,n / (unsigned int)2); + tmp = (int)tmp_0; + /*@ assert Eva: signed_overflow: -2147483648 ≤ tmp * tmp; */ + /*@ assert Eva: signed_overflow: tmp * tmp ≤ 2147483647; */ + tmp *= tmp; + if (n % (unsigned int)2 == (unsigned int)0) { + __retres = (unsigned long long)tmp; + goto return_label; + } + __retres = (unsigned long long)(x * (unsigned int)tmp); + return_label: return __retres; +} + +int main(void) +{ + int __retres; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + unsigned long long x = my_pow((unsigned int)2,(unsigned int)63); + /*@ assert (2 * x + 1) % 2 ≡ 1; */ + { + __e_acsl_mpz_t __gen_e_acsl_; + __e_acsl_mpz_t __gen_e_acsl_x; + __e_acsl_mpz_t __gen_e_acsl_mul; + __e_acsl_mpz_t __gen_e_acsl__2; + __e_acsl_mpz_t __gen_e_acsl_add; + __e_acsl_mpz_t __gen_e_acsl__3; + int __gen_e_acsl_mod_guard; + __e_acsl_mpz_t __gen_e_acsl_mod; + long __gen_e_acsl__4; + __gmpz_init_set_si(__gen_e_acsl_,2L); + __gmpz_init(__gen_e_acsl_x); + __gmpz_import(__gen_e_acsl_x,(size_t)1,1,(size_t)8,0,(size_t)0, + (void const *)(& x)); + __gmpz_init(__gen_e_acsl_mul); + __gmpz_mul(__gen_e_acsl_mul,(__e_acsl_mpz_struct const *)(__gen_e_acsl_), + (__e_acsl_mpz_struct const *)(__gen_e_acsl_x)); + __gmpz_init_set_si(__gen_e_acsl__2,1L); + __gmpz_init(__gen_e_acsl_add); + __gmpz_add(__gen_e_acsl_add, + (__e_acsl_mpz_struct const *)(__gen_e_acsl_mul), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__2)); + __gmpz_init_set_si(__gen_e_acsl__3,0L); + __gen_e_acsl_mod_guard = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__3)); + __gmpz_init(__gen_e_acsl_mod); + /*@ assert E_ACSL: 2 ≢ 0; */ + __e_acsl_assert(! (__gen_e_acsl_mod_guard == 0),(char *)"Assertion", + (char *)"main",(char *)"2 == 0",17); + __gmpz_tdiv_r(__gen_e_acsl_mod, + (__e_acsl_mpz_struct const *)(__gen_e_acsl_add), + (__e_acsl_mpz_struct const *)(__gen_e_acsl_)); + __gen_e_acsl__4 = __gmpz_get_si((__e_acsl_mpz_struct const *)(__gen_e_acsl_mod)); + __e_acsl_assert(__gen_e_acsl__4 == 1L,(char *)"Assertion",(char *)"main", + (char *)"(2 * x + 1) % 2 == 1",17); + __gmpz_clear(__gen_e_acsl_); + __gmpz_clear(__gen_e_acsl_x); + __gmpz_clear(__gen_e_acsl_mul); + __gmpz_clear(__gen_e_acsl__2); + __gmpz_clear(__gen_e_acsl_add); + __gmpz_clear(__gen_e_acsl__3); + __gmpz_clear(__gen_e_acsl_mod); + } + __retres = 0; + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/arith/oracle_ci/gen_not.c b/src/plugins/e-acsl/tests/arith/oracle_ci/gen_not.c new file mode 100644 index 0000000000000000000000000000000000000000..1877976693a0dde54384cfc75b3b11ec60884c1b --- /dev/null +++ b/src/plugins/e-acsl/tests/arith/oracle_ci/gen_not.c @@ -0,0 +1,20 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +int main(void) +{ + int __retres; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + int x = 0; + /*@ assert x ≡ 0; */ + __e_acsl_assert(x == 0,(char *)"Assertion",(char *)"main",(char *)"x == 0", + 6); + if (x) + /*@ assert x ≢ 0; */ + __e_acsl_assert(x != 0,(char *)"Assertion",(char *)"main", + (char *)"x != 0",7); + __retres = 0; + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/arith/oracle_ci/gen_quantif.c b/src/plugins/e-acsl/tests/arith/oracle_ci/gen_quantif.c new file mode 100644 index 0000000000000000000000000000000000000000..3da7cdb090e6b8e569de946962bc57cd73f1657c --- /dev/null +++ b/src/plugins/e-acsl/tests/arith/oracle_ci/gen_quantif.c @@ -0,0 +1,340 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +int main(void) +{ + int __retres; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + /*@ assert ∀ ℤ x; 0 ≤ x ≤ 1 ⇒ x ≡ 0 ∨ x ≡ 1; */ + { + int __gen_e_acsl_forall; + int __gen_e_acsl_x; + __gen_e_acsl_forall = 1; + __gen_e_acsl_x = 0; + while (1) { + if (__gen_e_acsl_x <= 1) ; else break; + { + int __gen_e_acsl_or; + if (__gen_e_acsl_x == 0) __gen_e_acsl_or = 1; + else __gen_e_acsl_or = __gen_e_acsl_x == 1; + if (__gen_e_acsl_or) ; + else { + __gen_e_acsl_forall = 0; + goto e_acsl_end_loop1; + } + } + __gen_e_acsl_x ++; + } + e_acsl_end_loop1: ; + __e_acsl_assert(__gen_e_acsl_forall,(char *)"Assertion",(char *)"main", + (char *)"\\forall integer x; 0 <= x <= 1 ==> x == 0 || x == 1", + 9); + } + /*@ assert ∀ ℤ x; 0 < x ≤ 1 ⇒ x ≡ 1; */ + { + int __gen_e_acsl_forall_2; + int __gen_e_acsl_x_2; + __gen_e_acsl_forall_2 = 1; + __gen_e_acsl_x_2 = 0 + 1; + while (1) { + if (__gen_e_acsl_x_2 <= 1) ; else break; + if (__gen_e_acsl_x_2 == 1) ; + else { + __gen_e_acsl_forall_2 = 0; + goto e_acsl_end_loop2; + } + __gen_e_acsl_x_2 ++; + } + e_acsl_end_loop2: ; + __e_acsl_assert(__gen_e_acsl_forall_2,(char *)"Assertion",(char *)"main", + (char *)"\\forall integer x; 0 < x <= 1 ==> x == 1",10); + } + /*@ assert ∀ ℤ x; 0 ≤ x < 1 ⇒ x ≡ 0; */ + { + int __gen_e_acsl_forall_3; + int __gen_e_acsl_x_3; + __gen_e_acsl_forall_3 = 1; + __gen_e_acsl_x_3 = 0; + while (1) { + if (__gen_e_acsl_x_3 < 1) ; else break; + if (__gen_e_acsl_x_3 == 0) ; + else { + __gen_e_acsl_forall_3 = 0; + goto e_acsl_end_loop3; + } + __gen_e_acsl_x_3 ++; + } + e_acsl_end_loop3: ; + __e_acsl_assert(__gen_e_acsl_forall_3,(char *)"Assertion",(char *)"main", + (char *)"\\forall integer x; 0 <= x < 1 ==> x == 0",11); + } + /*@ assert + ∀ ℤ x, ℤ y, ℤ z; + 0 ≤ x < 2 ∧ 0 ≤ y < 5 ∧ 0 ≤ z ≤ y ⇒ x + z ≤ y + 1; + */ + { + int __gen_e_acsl_forall_4; + int __gen_e_acsl_x_4; + int __gen_e_acsl_y; + int __gen_e_acsl_z; + __gen_e_acsl_forall_4 = 1; + __gen_e_acsl_x_4 = 0; + while (1) { + if (__gen_e_acsl_x_4 < 2) ; else break; + __gen_e_acsl_y = 0; + while (1) { + if (__gen_e_acsl_y < 5) ; else break; + __gen_e_acsl_z = 0; + while (1) { + if (__gen_e_acsl_z <= __gen_e_acsl_y) ; else break; + if (__gen_e_acsl_x_4 + __gen_e_acsl_z <= __gen_e_acsl_y + 1) + ; + else { + __gen_e_acsl_forall_4 = 0; + goto e_acsl_end_loop4; + } + __gen_e_acsl_z ++; + } + __gen_e_acsl_y ++; + } + __gen_e_acsl_x_4 ++; + } + e_acsl_end_loop4: ; + __e_acsl_assert(__gen_e_acsl_forall_4,(char *)"Assertion",(char *)"main", + (char *)"\\forall integer x, integer y, integer z;\n 0 <= x < 2 && 0 <= y < 5 && 0 <= z <= y ==> x + z <= y + 1", + 15); + } + /*@ assert ∃ int x; 0 ≤ x < 10 ∧ x ≡ 5; */ + { + int __gen_e_acsl_exists; + int __gen_e_acsl_x_5; + __gen_e_acsl_exists = 0; + __gen_e_acsl_x_5 = 0; + while (1) { + if (__gen_e_acsl_x_5 < 10) ; else break; + if (! (__gen_e_acsl_x_5 == 5)) ; + else { + __gen_e_acsl_exists = 1; + goto e_acsl_end_loop5; + } + __gen_e_acsl_x_5 ++; + } + e_acsl_end_loop5: ; + __e_acsl_assert(__gen_e_acsl_exists,(char *)"Assertion",(char *)"main", + (char *)"\\exists int x; 0 <= x < 10 && x == 5",20); + } + /*@ assert + ∀ int x; + 0 ≤ x < 10 ⇒ + x % 2 ≡ 0 ⇒ (∃ ℤ y; 0 ≤ y ≤ x / 2 ∧ x ≡ 2 * y); + */ + { + int __gen_e_acsl_forall_5; + int __gen_e_acsl_x_6; + __gen_e_acsl_forall_5 = 1; + __gen_e_acsl_x_6 = 0; + while (1) { + if (__gen_e_acsl_x_6 < 10) ; else break; + { + int __gen_e_acsl_implies; + if (! (__gen_e_acsl_x_6 % 2 == 0)) __gen_e_acsl_implies = 1; + else { + int __gen_e_acsl_exists_2; + int __gen_e_acsl_y_2; + __gen_e_acsl_exists_2 = 0; + __gen_e_acsl_y_2 = 0; + while (1) { + if (__gen_e_acsl_y_2 <= __gen_e_acsl_x_6 / 2) ; else break; + if (! (__gen_e_acsl_x_6 == 2 * __gen_e_acsl_y_2)) ; + else { + __gen_e_acsl_exists_2 = 1; + goto e_acsl_end_loop6; + } + __gen_e_acsl_y_2 ++; + } + e_acsl_end_loop6: ; + __gen_e_acsl_implies = __gen_e_acsl_exists_2; + } + if (__gen_e_acsl_implies) ; + else { + __gen_e_acsl_forall_5 = 0; + goto e_acsl_end_loop7; + } + } + __gen_e_acsl_x_6 ++; + } + e_acsl_end_loop7: ; + __e_acsl_assert(__gen_e_acsl_forall_5,(char *)"Assertion",(char *)"main", + (char *)"\\forall int x;\n 0 <= x < 10 ==>\n x % 2 == 0 ==> (\\exists integer y; 0 <= y <= x / 2 && x == 2 * y)", + 24); + } + { + int buf[10]; + __e_acsl_store_block((void *)(buf),(size_t)40); + unsigned long len = (unsigned long)9; + /*@ assert ∀ ℤ i; 0 ≤ i < 10 ⇒ \valid(&buf[i]); */ + { + int __gen_e_acsl_forall_6; + int __gen_e_acsl_i; + __gen_e_acsl_forall_6 = 1; + __gen_e_acsl_i = 0; + while (1) { + if (__gen_e_acsl_i < 10) ; else break; + { + int __gen_e_acsl_valid; + __gen_e_acsl_valid = __e_acsl_valid((void *)(& buf[__gen_e_acsl_i]), + sizeof(int), + (void *)(& buf[__gen_e_acsl_i]), + (void *)0); + if (__gen_e_acsl_valid) ; + else { + __gen_e_acsl_forall_6 = 0; + goto e_acsl_end_loop8; + } + } + __gen_e_acsl_i ++; + } + e_acsl_end_loop8: ; + __e_acsl_assert(__gen_e_acsl_forall_6,(char *)"Assertion", + (char *)"main", + (char *)"\\forall integer i; 0 <= i < 10 ==> \\valid(&buf[i])", + 30); + } + /*@ assert ∀ char i; 0 ≤ i < 10 ⇒ \valid(&buf[i]); */ + { + int __gen_e_acsl_forall_7; + int __gen_e_acsl_i_2; + __gen_e_acsl_forall_7 = 1; + __gen_e_acsl_i_2 = (char)0; + while (1) { + if (__gen_e_acsl_i_2 < 10) ; else break; + { + int __gen_e_acsl_valid_2; + __gen_e_acsl_valid_2 = __e_acsl_valid((void *)(& buf[__gen_e_acsl_i_2]), + sizeof(int), + (void *)(& buf[__gen_e_acsl_i_2]), + (void *)0); + if (__gen_e_acsl_valid_2) ; + else { + __gen_e_acsl_forall_7 = 0; + goto e_acsl_end_loop9; + } + } + __gen_e_acsl_i_2 ++; + } + e_acsl_end_loop9: ; + __e_acsl_assert(__gen_e_acsl_forall_7,(char *)"Assertion", + (char *)"main", + (char *)"\\forall char i; 0 <= i < 10 ==> \\valid(&buf[i])", + 31); + } + /*@ assert ∀ ℤ i; 0 ≤ i < len ⇒ \valid(&buf[i]); */ + { + int __gen_e_acsl_forall_8; + unsigned long __gen_e_acsl_i_3; + __gen_e_acsl_forall_8 = 1; + __gen_e_acsl_i_3 = 0UL; + while (1) { + if (__gen_e_acsl_i_3 < len) ; else break; + { + int __gen_e_acsl_valid_3; + __gen_e_acsl_valid_3 = __e_acsl_valid((void *)(& buf[__gen_e_acsl_i_3]), + sizeof(int), + (void *)(& buf[__gen_e_acsl_i_3]), + (void *)0); + if (__gen_e_acsl_valid_3) ; + else { + __gen_e_acsl_forall_8 = 0; + goto e_acsl_end_loop10; + } + } + __gen_e_acsl_i_3 ++; + } + e_acsl_end_loop10: ; + __e_acsl_assert(__gen_e_acsl_forall_8,(char *)"Assertion", + (char *)"main", + (char *)"\\forall integer i; 0 <= i < len ==> \\valid(&buf[i])", + 32); + } + /*@ assert ∀ ℤ i; 0 ≤ i ≤ len ⇒ \valid(&buf[i]); */ + { + int __gen_e_acsl_forall_9; + __e_acsl_mpz_t __gen_e_acsl_i_4; + __gen_e_acsl_forall_9 = 1; + __gmpz_init(__gen_e_acsl_i_4); + { + __e_acsl_mpz_t __gen_e_acsl_; + __gmpz_init_set_si(__gen_e_acsl_,0L); + __gmpz_set(__gen_e_acsl_i_4, + (__e_acsl_mpz_struct const *)(__gen_e_acsl_)); + __gmpz_clear(__gen_e_acsl_); + } + while (1) { + { + __e_acsl_mpz_t __gen_e_acsl_len; + int __gen_e_acsl_le; + __gmpz_init_set_ui(__gen_e_acsl_len,len); + __gen_e_acsl_le = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_i_4), + (__e_acsl_mpz_struct const *)(__gen_e_acsl_len)); + if (__gen_e_acsl_le <= 0) ; else break; + __gmpz_clear(__gen_e_acsl_len); + } + { + long __gen_e_acsl_i_5; + int __gen_e_acsl_valid_4; + __gen_e_acsl_i_5 = __gmpz_get_si((__e_acsl_mpz_struct const *)(__gen_e_acsl_i_4)); + __gen_e_acsl_valid_4 = __e_acsl_valid((void *)(& buf[__gen_e_acsl_i_5]), + sizeof(int), + (void *)(& buf[__gen_e_acsl_i_5]), + (void *)0); + if (__gen_e_acsl_valid_4) ; + else { + __gen_e_acsl_forall_9 = 0; + goto e_acsl_end_loop11; + } + } + { + __e_acsl_mpz_t __gen_e_acsl__2; + __e_acsl_mpz_t __gen_e_acsl_add; + __gmpz_init_set_ui(__gen_e_acsl__2,1UL); + __gmpz_init(__gen_e_acsl_add); + __gmpz_add(__gen_e_acsl_add, + (__e_acsl_mpz_struct const *)(__gen_e_acsl_i_4), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__2)); + __gmpz_set(__gen_e_acsl_i_4, + (__e_acsl_mpz_struct const *)(__gen_e_acsl_add)); + __gmpz_clear(__gen_e_acsl__2); + __gmpz_clear(__gen_e_acsl_add); + } + } + e_acsl_end_loop11: ; + __e_acsl_assert(__gen_e_acsl_forall_9,(char *)"Assertion", + (char *)"main", + (char *)"\\forall integer i; 0 <= i <= len ==> \\valid(&buf[i])", + 33); + __gmpz_clear(__gen_e_acsl_i_4); + __e_acsl_delete_block((void *)(buf)); + } + } + /*@ assert ∀ ℤ x; 0 < x < 1 ⇒ \false; */ + __e_acsl_assert(1,(char *)"Assertion",(char *)"main", + (char *)"\\forall integer x; 0 < x < 1 ==> \\false",37); + /*@ assert ¬(∃ char c; 10 ≤ c < 10 ∧ c ≡ 10); */ + __e_acsl_assert(! 0,(char *)"Assertion",(char *)"main", + (char *)"!(\\exists char c; 10 <= c < 10 && c == 10)",38); + /*@ assert \let u = 5; + ∀ ℤ x, ℤ y; 0 ≤ x < 2 ∧ 4 < y < u ⇒ \false; + */ + { + int __gen_e_acsl_u; + __gen_e_acsl_u = 5; + __e_acsl_assert(1,(char *)"Assertion",(char *)"main", + (char *)"\\let u = 5;\n\\forall integer x, integer y; 0 <= x < 2 && 4 < y < u ==> \\false", + 40); + } + __retres = 0; + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/arith/oracle_ci/gen_rationals.c b/src/plugins/e-acsl/tests/arith/oracle_ci/gen_rationals.c new file mode 100644 index 0000000000000000000000000000000000000000..64dac120aa8e21333408cfabc5b3f3bc898ef69a --- /dev/null +++ b/src/plugins/e-acsl/tests/arith/oracle_ci/gen_rationals.c @@ -0,0 +1,328 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +extern int __e_acsl_sound_verdict; + +/*@ ensures \let delta = 1; + \let avg_real = (\old(a) + \old(b)) / 2; + avg_real - delta < \result < avg_real + delta; + */ +double __gen_e_acsl_avg(double a, double b); + +double avg(double a, double b) +{ + double __retres; + __retres = (a + b) / (double)2; + return __retres; +} + +int main(void) +{ + int __retres; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + /*@ assert 3 ≢ 1.5; */ + __e_acsl_assert(3. != 1.5,(char *)"Assertion",(char *)"main", + (char *)"3 != 1.5",12); + /*@ assert 3 ≡ 1.5 + 1.5; */ + { + __e_acsl_mpq_t __gen_e_acsl_; + __e_acsl_mpq_t __gen_e_acsl__2; + __e_acsl_mpq_t __gen_e_acsl__3; + __e_acsl_mpq_t __gen_e_acsl_add; + int __gen_e_acsl_eq; + __gmpq_init(__gen_e_acsl_); + __gmpq_set_str(__gen_e_acsl_,"3",10); + __gmpq_init(__gen_e_acsl__2); + __gmpq_set_d(__gen_e_acsl__2,1.5); + __gmpq_init(__gen_e_acsl__3); + __gmpq_set_d(__gen_e_acsl__3,1.5); + __gmpq_init(__gen_e_acsl_add); + __gmpq_add(__gen_e_acsl_add, + (__e_acsl_mpq_struct const *)(__gen_e_acsl__2), + (__e_acsl_mpq_struct const *)(__gen_e_acsl__3)); + __gen_e_acsl_eq = __gmpq_cmp((__e_acsl_mpq_struct const *)(__gen_e_acsl_), + (__e_acsl_mpq_struct const *)(__gen_e_acsl_add)); + __e_acsl_assert(__gen_e_acsl_eq == 0,(char *)"Assertion",(char *)"main", + (char *)"3 == 1.5 + 1.5",13); + __gmpq_clear(__gen_e_acsl_); + __gmpq_clear(__gen_e_acsl__2); + __gmpq_clear(__gen_e_acsl__3); + __gmpq_clear(__gen_e_acsl_add); + } + /*@ assert 0.1 ≡ 0.1; */ + { + __e_acsl_mpq_t __gen_e_acsl__4; + int __gen_e_acsl_eq_2; + __gmpq_init(__gen_e_acsl__4); + __gmpq_set_str(__gen_e_acsl__4,"01/10",10); + __gen_e_acsl_eq_2 = __gmpq_cmp((__e_acsl_mpq_struct const *)(__gen_e_acsl__4), + (__e_acsl_mpq_struct const *)(__gen_e_acsl__4)); + __e_acsl_assert(__gen_e_acsl_eq_2 == 0,(char *)"Assertion", + (char *)"main",(char *)"0.1 == 0.1",14); + __gmpq_clear(__gen_e_acsl__4); + } + /*@ assert (double)1.0 ≡ 1.0; */ + __e_acsl_assert(1. == 1.,(char *)"Assertion",(char *)"main", + (char *)"(double)1.0 == 1.0",15); + /*@ assert (double)0.1 ≢ 0.1; */ + { + __e_acsl_mpq_t __gen_e_acsl__5; + double __gen_e_acsl__6; + __e_acsl_mpq_t __gen_e_acsl__7; + int __gen_e_acsl_ne; + __gmpq_init(__gen_e_acsl__5); + __gmpq_set_str(__gen_e_acsl__5,"01/10",10); + __gen_e_acsl__6 = __gmpq_get_d((__e_acsl_mpq_struct const *)(__gen_e_acsl__5)); + __gmpq_init(__gen_e_acsl__7); + /*@ assert Eva: is_nan_or_infinite: \is_finite(__gen_e_acsl__6); */ + __gmpq_set_d(__gen_e_acsl__7,__gen_e_acsl__6); + __gen_e_acsl_ne = __gmpq_cmp((__e_acsl_mpq_struct const *)(__gen_e_acsl__7), + (__e_acsl_mpq_struct const *)(__gen_e_acsl__5)); + __e_acsl_assert(__gen_e_acsl_ne != 0,(char *)"Assertion",(char *)"main", + (char *)"(double)0.1 != 0.1",16); + __gmpq_clear(__gen_e_acsl__5); + __gmpq_clear(__gen_e_acsl__7); + } + /*@ assert (float)0.1 ≢ (double)0.1; */ + { + __e_acsl_mpq_t __gen_e_acsl__8; + double __gen_e_acsl__9; + double __gen_e_acsl__10; + __gmpq_init(__gen_e_acsl__8); + __gmpq_set_str(__gen_e_acsl__8,"01/10",10); + __gen_e_acsl__9 = __gmpq_get_d((__e_acsl_mpq_struct const *)(__gen_e_acsl__8)); + __gen_e_acsl__10 = __gmpq_get_d((__e_acsl_mpq_struct const *)(__gen_e_acsl__8)); + /*@ assert Eva: is_nan_or_infinite: \is_finite(__gen_e_acsl__9); */ + /*@ assert Eva: is_nan_or_infinite: \is_finite(__gen_e_acsl__10); */ + /*@ assert Eva: is_nan_or_infinite: \is_finite((float)__gen_e_acsl__9); + */ + __e_acsl_assert((double)((float)__gen_e_acsl__9) != __gen_e_acsl__10, + (char *)"Assertion",(char *)"main", + (char *)"(float)0.1 != (double)0.1",17); + __gmpq_clear(__gen_e_acsl__8); + } + /*@ assert (double)1.1 ≢ 1 + 0.1; */ + { + __e_acsl_mpq_t __gen_e_acsl__11; + double __gen_e_acsl__12; + __e_acsl_mpq_t __gen_e_acsl__13; + __e_acsl_mpq_t __gen_e_acsl__14; + __e_acsl_mpq_t __gen_e_acsl_add_2; + __e_acsl_mpq_t __gen_e_acsl__15; + int __gen_e_acsl_ne_2; + __gmpq_init(__gen_e_acsl__11); + __gmpq_set_str(__gen_e_acsl__11,"11/10",10); + __gen_e_acsl__12 = __gmpq_get_d((__e_acsl_mpq_struct const *)(__gen_e_acsl__11)); + __gmpq_init(__gen_e_acsl__13); + __gmpq_set_str(__gen_e_acsl__13,"1",10); + __gmpq_init(__gen_e_acsl__14); + __gmpq_set_str(__gen_e_acsl__14,"01/10",10); + __gmpq_init(__gen_e_acsl_add_2); + __gmpq_add(__gen_e_acsl_add_2, + (__e_acsl_mpq_struct const *)(__gen_e_acsl__13), + (__e_acsl_mpq_struct const *)(__gen_e_acsl__14)); + __gmpq_init(__gen_e_acsl__15); + /*@ assert Eva: is_nan_or_infinite: \is_finite(__gen_e_acsl__12); */ + __gmpq_set_d(__gen_e_acsl__15,__gen_e_acsl__12); + __gen_e_acsl_ne_2 = __gmpq_cmp((__e_acsl_mpq_struct const *)(__gen_e_acsl__15), + (__e_acsl_mpq_struct const *)(__gen_e_acsl_add_2)); + __e_acsl_assert(__gen_e_acsl_ne_2 != 0,(char *)"Assertion", + (char *)"main",(char *)"(double)1.1 != 1 + 0.1",18); + __gmpq_clear(__gen_e_acsl__11); + __gmpq_clear(__gen_e_acsl__13); + __gmpq_clear(__gen_e_acsl__14); + __gmpq_clear(__gen_e_acsl_add_2); + __gmpq_clear(__gen_e_acsl__15); + } + /*@ assert 1 + 0.1 ≡ 2 - 0.9; */ + { + __e_acsl_mpq_t __gen_e_acsl__16; + __e_acsl_mpq_t __gen_e_acsl__17; + __e_acsl_mpq_t __gen_e_acsl_add_3; + __e_acsl_mpq_t __gen_e_acsl__18; + __e_acsl_mpq_t __gen_e_acsl__19; + __e_acsl_mpq_t __gen_e_acsl_sub; + int __gen_e_acsl_eq_3; + __gmpq_init(__gen_e_acsl__16); + __gmpq_set_str(__gen_e_acsl__16,"1",10); + __gmpq_init(__gen_e_acsl__17); + __gmpq_set_str(__gen_e_acsl__17,"01/10",10); + __gmpq_init(__gen_e_acsl_add_3); + __gmpq_add(__gen_e_acsl_add_3, + (__e_acsl_mpq_struct const *)(__gen_e_acsl__16), + (__e_acsl_mpq_struct const *)(__gen_e_acsl__17)); + __gmpq_init(__gen_e_acsl__18); + __gmpq_set_str(__gen_e_acsl__18,"2",10); + __gmpq_init(__gen_e_acsl__19); + __gmpq_set_str(__gen_e_acsl__19,"09/10",10); + __gmpq_init(__gen_e_acsl_sub); + __gmpq_sub(__gen_e_acsl_sub, + (__e_acsl_mpq_struct const *)(__gen_e_acsl__18), + (__e_acsl_mpq_struct const *)(__gen_e_acsl__19)); + __gen_e_acsl_eq_3 = __gmpq_cmp((__e_acsl_mpq_struct const *)(__gen_e_acsl_add_3), + (__e_acsl_mpq_struct const *)(__gen_e_acsl_sub)); + __e_acsl_assert(__gen_e_acsl_eq_3 == 0,(char *)"Assertion", + (char *)"main",(char *)"1 + 0.1 == 2 - 0.9",19); + __gmpq_clear(__gen_e_acsl__16); + __gmpq_clear(__gen_e_acsl__17); + __gmpq_clear(__gen_e_acsl_add_3); + __gmpq_clear(__gen_e_acsl__18); + __gmpq_clear(__gen_e_acsl__19); + __gmpq_clear(__gen_e_acsl_sub); + } + float x = 0.2f; + float y = 0.3f; + float sum = x + y; + /*@ assert sum ≢ x * y; */ + { + __e_acsl_mpq_t __gen_e_acsl_y; + __e_acsl_mpq_t __gen_e_acsl__20; + __e_acsl_mpq_t __gen_e_acsl_mul; + __e_acsl_mpq_t __gen_e_acsl__21; + int __gen_e_acsl_ne_3; + __gmpq_init(__gen_e_acsl_y); + __gmpq_set_d(__gen_e_acsl_y,(double)y); + __gmpq_init(__gen_e_acsl__20); + __gmpq_set_d(__gen_e_acsl__20,(double)x); + __gmpq_init(__gen_e_acsl_mul); + __gmpq_mul(__gen_e_acsl_mul, + (__e_acsl_mpq_struct const *)(__gen_e_acsl__20), + (__e_acsl_mpq_struct const *)(__gen_e_acsl_y)); + __gmpq_init(__gen_e_acsl__21); + __gmpq_set_d(__gen_e_acsl__21,(double)sum); + __gen_e_acsl_ne_3 = __gmpq_cmp((__e_acsl_mpq_struct const *)(__gen_e_acsl__21), + (__e_acsl_mpq_struct const *)(__gen_e_acsl_mul)); + __e_acsl_assert(__gen_e_acsl_ne_3 != 0,(char *)"Assertion", + (char *)"main",(char *)"sum != x * y",23); + __gmpq_clear(__gen_e_acsl_y); + __gmpq_clear(__gen_e_acsl__20); + __gmpq_clear(__gen_e_acsl_mul); + __gmpq_clear(__gen_e_acsl__21); + } + double d = 0.1; + __gen_e_acsl_avg(4.3,11.7); + /*@ assert 1.1d ≢ 1 + 0.1; */ + { + __e_acsl_mpq_t __gen_e_acsl__22; + __e_acsl_mpq_t __gen_e_acsl__23; + __e_acsl_mpq_t __gen_e_acsl_add_4; + __e_acsl_mpq_t __gen_e_acsl__24; + int __gen_e_acsl_ne_4; + __gmpq_init(__gen_e_acsl__22); + __gmpq_set_str(__gen_e_acsl__22,"1",10); + __gmpq_init(__gen_e_acsl__23); + __gmpq_set_str(__gen_e_acsl__23,"01/10",10); + __gmpq_init(__gen_e_acsl_add_4); + __gmpq_add(__gen_e_acsl_add_4, + (__e_acsl_mpq_struct const *)(__gen_e_acsl__22), + (__e_acsl_mpq_struct const *)(__gen_e_acsl__23)); + __gmpq_init(__gen_e_acsl__24); + __gmpq_set_d(__gen_e_acsl__24,1.1); + __gen_e_acsl_ne_4 = __gmpq_cmp((__e_acsl_mpq_struct const *)(__gen_e_acsl__24), + (__e_acsl_mpq_struct const *)(__gen_e_acsl_add_4)); + __e_acsl_assert(__gen_e_acsl_ne_4 != 0,(char *)"Assertion", + (char *)"main",(char *)"1.1d != 1 + 0.1",30); + __gmpq_clear(__gen_e_acsl__22); + __gmpq_clear(__gen_e_acsl__23); + __gmpq_clear(__gen_e_acsl_add_4); + __gmpq_clear(__gen_e_acsl__24); + } + __retres = 0; + return __retres; +} + +/*@ ensures \let delta = 1; + \let avg_real = (\old(a) + \old(b)) / 2; + avg_real - delta < \result < avg_real + delta; + */ +double __gen_e_acsl_avg(double a, double b) +{ + double __gen_e_acsl_at_2; + __e_acsl_mpq_t __gen_e_acsl_at; + double __retres; + __gen_e_acsl_at_2 = b; + { + __e_acsl_mpq_t __gen_e_acsl_a; + __gmpq_init(__gen_e_acsl_a); + __gmpq_set_d(__gen_e_acsl_a,a); + __gmpq_init(__gen_e_acsl_at); + __gmpq_set(__gen_e_acsl_at,(__e_acsl_mpq_struct const *)(__gen_e_acsl_a)); + __gmpq_clear(__gen_e_acsl_a); + } + __retres = avg(a,b); + { + int __gen_e_acsl_delta; + __e_acsl_mpq_t __gen_e_acsl_avg_real; + __e_acsl_mpq_t __gen_e_acsl_; + __e_acsl_mpq_t __gen_e_acsl_add; + __e_acsl_mpq_t __gen_e_acsl__2; + __e_acsl_mpq_t __gen_e_acsl_div; + __e_acsl_mpq_t __gen_e_acsl_delta_2; + __e_acsl_mpq_t __gen_e_acsl_sub; + __e_acsl_mpq_t __gen_e_acsl__3; + int __gen_e_acsl_lt; + int __gen_e_acsl_and; + __gen_e_acsl_delta = 1; + __gmpq_init(__gen_e_acsl_); + __gmpq_set_d(__gen_e_acsl_,__gen_e_acsl_at_2); + __gmpq_init(__gen_e_acsl_add); + __gmpq_add(__gen_e_acsl_add, + (__e_acsl_mpq_struct const *)(__gen_e_acsl_at), + (__e_acsl_mpq_struct const *)(__gen_e_acsl_)); + __gmpq_init(__gen_e_acsl__2); + __gmpq_set_str(__gen_e_acsl__2,"2",10); + __gmpq_init(__gen_e_acsl_div); + __gmpq_div(__gen_e_acsl_div, + (__e_acsl_mpq_struct const *)(__gen_e_acsl_add), + (__e_acsl_mpq_struct const *)(__gen_e_acsl__2)); + __gmpq_init(__gen_e_acsl_avg_real); + __gmpq_set(__gen_e_acsl_avg_real, + (__e_acsl_mpq_struct const *)(__gen_e_acsl_div)); + __gmpq_init(__gen_e_acsl_delta_2); + __gmpq_set_si(__gen_e_acsl_delta_2,(long)__gen_e_acsl_delta); + __gmpq_init(__gen_e_acsl_sub); + __gmpq_sub(__gen_e_acsl_sub, + (__e_acsl_mpq_struct const *)(__gen_e_acsl_avg_real), + (__e_acsl_mpq_struct const *)(__gen_e_acsl_delta_2)); + __gmpq_init(__gen_e_acsl__3); + __gmpq_set_d(__gen_e_acsl__3,__retres); + __gen_e_acsl_lt = __gmpq_cmp((__e_acsl_mpq_struct const *)(__gen_e_acsl_sub), + (__e_acsl_mpq_struct const *)(__gen_e_acsl__3)); + if (__gen_e_acsl_lt < 0) { + __e_acsl_mpq_t __gen_e_acsl_delta_3; + __e_acsl_mpq_t __gen_e_acsl_add_2; + __e_acsl_mpq_t __gen_e_acsl__4; + int __gen_e_acsl_lt_2; + __gmpq_init(__gen_e_acsl_delta_3); + __gmpq_set_si(__gen_e_acsl_delta_3,(long)__gen_e_acsl_delta); + __gmpq_init(__gen_e_acsl_add_2); + __gmpq_add(__gen_e_acsl_add_2, + (__e_acsl_mpq_struct const *)(__gen_e_acsl_avg_real), + (__e_acsl_mpq_struct const *)(__gen_e_acsl_delta_3)); + __gmpq_init(__gen_e_acsl__4); + __gmpq_set_d(__gen_e_acsl__4,__retres); + __gen_e_acsl_lt_2 = __gmpq_cmp((__e_acsl_mpq_struct const *)(__gen_e_acsl__4), + (__e_acsl_mpq_struct const *)(__gen_e_acsl_add_2)); + __gen_e_acsl_and = __gen_e_acsl_lt_2 < 0; + __gmpq_clear(__gen_e_acsl_delta_3); + __gmpq_clear(__gen_e_acsl_add_2); + __gmpq_clear(__gen_e_acsl__4); + } + else __gen_e_acsl_and = 0; + __e_acsl_assert(__gen_e_acsl_and,(char *)"Postcondition",(char *)"avg", + (char *)"\\let delta = 1;\n\\let avg_real = (\\old(a) + \\old(b)) / 2;\n avg_real - delta < \\result < avg_real + delta", + 4); + __gmpq_clear(__gen_e_acsl_avg_real); + __gmpq_clear(__gen_e_acsl_); + __gmpq_clear(__gen_e_acsl_add); + __gmpq_clear(__gen_e_acsl__2); + __gmpq_clear(__gen_e_acsl_div); + __gmpq_clear(__gen_e_acsl_delta_2); + __gmpq_clear(__gen_e_acsl_sub); + __gmpq_clear(__gen_e_acsl__3); + __gmpq_clear(__gen_e_acsl_at); + return __retres; + } +} + + diff --git a/src/plugins/e-acsl/tests/arith/oracle_ci/integer_constant.res.oracle b/src/plugins/e-acsl/tests/arith/oracle_ci/integer_constant.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..6b57e2f2567a73c9c0cecf048b1085a58562d64c --- /dev/null +++ b/src/plugins/e-acsl/tests/arith/oracle_ci/integer_constant.res.oracle @@ -0,0 +1,4 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". +[eva:alarm] tests/arith/integer_constant.i:11: Warning: + function __e_acsl_assert: precondition got status unknown. diff --git a/src/plugins/e-acsl/tests/arith/oracle_ci/let.res.oracle b/src/plugins/e-acsl/tests/arith/oracle_ci/let.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..ca9d6da56ba3a181b86474b0bc1a30698b36e61c --- /dev/null +++ b/src/plugins/e-acsl/tests/arith/oracle_ci/let.res.oracle @@ -0,0 +1,19 @@ +[e-acsl] beginning translation. +[e-acsl] tests/arith/let.c:30: Warning: + E-ACSL construct `let-binding on array or pointer' is not yet supported. + Ignoring annotation. +[e-acsl] translation done in project "e-acsl". +[eva:alarm] tests/arith/let.c:7: Warning: assertion got status unknown. +[eva:alarm] tests/arith/let.c:9: Warning: assertion got status unknown. +[eva:alarm] tests/arith/let.c:12: Warning: assertion got status unknown. +[eva:alarm] tests/arith/let.c:14: Warning: assertion got status unknown. +[eva:alarm] tests/arith/let.c:17: Warning: assertion got status unknown. +[eva:alarm] tests/arith/let.c:21: Warning: assertion got status unknown. +[eva:alarm] tests/arith/let.c:21: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/arith/let.c:24: Warning: assertion got status unknown. +[eva:alarm] tests/arith/let.c:27: Warning: assertion got status unknown. +[eva:alarm] tests/arith/let.c:30: Warning: assertion got status unknown. +[eva:alarm] tests/arith/let.c:32: Warning: assertion got status unknown. +[eva:alarm] tests/arith/let.c:35: Warning: assertion got status unknown. +[eva:alarm] tests/arith/let.c:39: Warning: assertion got status unknown. diff --git a/src/plugins/e-acsl/tests/arith/oracle_ci/longlong.res.oracle b/src/plugins/e-acsl/tests/arith/oracle_ci/longlong.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..124461612b970a0ba6842a2ef51aec04edd861ba --- /dev/null +++ b/src/plugins/e-acsl/tests/arith/oracle_ci/longlong.res.oracle @@ -0,0 +1,14 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". +[eva] tests/arith/longlong.i:9: Warning: + recursive call during value analysis + of my_pow (my_pow <- my_pow :: tests/arith/longlong.i:16 <- main). Assuming + the call has no effect. The analysis will be unsound. +[eva:alarm] tests/arith/longlong.i:10: Warning: + signed overflow. assert -2147483648 ≤ tmp * tmp; +[eva:alarm] tests/arith/longlong.i:10: Warning: + signed overflow. assert tmp * tmp ≤ 2147483647; +[eva:alarm] tests/arith/longlong.i:17: Warning: + function __gmpz_import: precondition got status unknown. +[eva:alarm] tests/arith/longlong.i:17: Warning: + function __e_acsl_assert: precondition got status unknown. diff --git a/src/plugins/e-acsl/tests/arith/oracle_ci/not.res.oracle b/src/plugins/e-acsl/tests/arith/oracle_ci/not.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..efd026311297e55d8fefb674326118e6ece88624 --- /dev/null +++ b/src/plugins/e-acsl/tests/arith/oracle_ci/not.res.oracle @@ -0,0 +1,2 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". diff --git a/src/plugins/e-acsl/tests/arith/oracle_ci/quantif.res.oracle b/src/plugins/e-acsl/tests/arith/oracle_ci/quantif.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..e34fffe72687422b0029223b19570a7b4c0d0f3c --- /dev/null +++ b/src/plugins/e-acsl/tests/arith/oracle_ci/quantif.res.oracle @@ -0,0 +1,25 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". +[eva:alarm] tests/arith/quantif.i:9: Warning: assertion got status unknown. +[eva:alarm] tests/arith/quantif.i:10: Warning: assertion got status unknown. +[eva:alarm] tests/arith/quantif.i:11: Warning: assertion got status unknown. +[eva:alarm] tests/arith/quantif.i:15: Warning: assertion got status unknown. +[eva:alarm] tests/arith/quantif.i:15: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/arith/quantif.i:20: Warning: assertion got status unknown. +[eva:alarm] tests/arith/quantif.i:24: Warning: assertion got status unknown. +[eva:alarm] tests/arith/quantif.i:24: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/arith/quantif.i:30: Warning: assertion got status unknown. +[eva:alarm] tests/arith/quantif.i:30: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/arith/quantif.i:31: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/arith/quantif.i:32: Warning: assertion got status unknown. +[eva:alarm] tests/arith/quantif.i:32: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/arith/quantif.i:33: Warning: assertion got status unknown. +[eva:alarm] tests/arith/quantif.i:33: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/arith/quantif.i:37: Warning: assertion got status unknown. +[eva:alarm] tests/arith/quantif.i:40: Warning: assertion got status unknown. diff --git a/src/plugins/e-acsl/tests/arith/oracle_ci/rationals.res.oracle b/src/plugins/e-acsl/tests/arith/oracle_ci/rationals.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..0f4b10fa65e7af752e46e48f474503dc2b38b725 --- /dev/null +++ b/src/plugins/e-acsl/tests/arith/oracle_ci/rationals.res.oracle @@ -0,0 +1,45 @@ +[kernel:parser:decimal-float] tests/arith/rationals.c:20: Warning: + Floating-point constant 0.2f is not represented exactly. Will use 0x1.99999a0000000p-3. + (warn-once: no further messages from category 'parser:decimal-float' will be emitted) +[e-acsl] beginning translation. +[e-acsl] Warning: R to float: double rounding might cause unsoundness +[e-acsl] tests/arith/rationals.c:17: Warning: + E-ACSL construct `predicate with no definition nor reads clause' + is not yet supported. + Ignoring annotation. +[e-acsl] translation done in project "e-acsl". +[eva:alarm] tests/arith/rationals.c:13: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/arith/rationals.c:14: Warning: assertion got status unknown. +[eva:alarm] tests/arith/rationals.c:14: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/arith/rationals.c:16: Warning: assertion got status unknown. +[eva:alarm] tests/arith/rationals.c:16: Warning: + non-finite double value. assert \is_finite(__gen_e_acsl__6); +[eva:alarm] tests/arith/rationals.c:16: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/arith/rationals.c:17: Warning: + non-finite double value. assert \is_finite(__gen_e_acsl__9); +[eva:alarm] tests/arith/rationals.c:17: Warning: + non-finite double value. assert \is_finite(__gen_e_acsl__10); +[eva:alarm] tests/arith/rationals.c:17: Warning: + non-finite float value. assert \is_finite((float)__gen_e_acsl__9); +[eva:alarm] tests/arith/rationals.c:17: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/arith/rationals.c:18: Warning: assertion got status unknown. +[eva:alarm] tests/arith/rationals.c:18: Warning: + non-finite double value. assert \is_finite(__gen_e_acsl__12); +[eva:alarm] tests/arith/rationals.c:18: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/arith/rationals.c:19: Warning: assertion got status unknown. +[eva:alarm] tests/arith/rationals.c:19: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/arith/rationals.c:23: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/arith/rationals.c:4: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/arith/rationals.c:4: Warning: + function __gen_e_acsl_avg: postcondition got status unknown. +[eva:alarm] tests/arith/rationals.c:30: Warning: assertion got status unknown. +[eva:alarm] tests/arith/rationals.c:30: Warning: + function __e_acsl_assert: precondition got status unknown. diff --git a/src/plugins/e-acsl/tests/arith/oracle_dev/arith.res.oracle b/src/plugins/e-acsl/tests/arith/oracle_dev/arith.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..bb570ee92a885dcd365840665e9b00de514a5dab --- /dev/null +++ b/src/plugins/e-acsl/tests/arith/oracle_dev/arith.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/arith/arith.i (no preprocessing) diff --git a/src/plugins/e-acsl/tests/arith/oracle_dev/array.res.oracle b/src/plugins/e-acsl/tests/arith/oracle_dev/array.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..5e053cab3c744e96f02ea58ddbfac726d008ca3f --- /dev/null +++ b/src/plugins/e-acsl/tests/arith/oracle_dev/array.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/arith/array.i (no preprocessing) diff --git a/src/plugins/e-acsl/tests/arith/oracle_dev/at.res.oracle b/src/plugins/e-acsl/tests/arith/oracle_dev/at.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..b42f8f987b3811fcd47315b45c397fc50c18ae68 --- /dev/null +++ b/src/plugins/e-acsl/tests/arith/oracle_dev/at.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/arith/at.i (no preprocessing) diff --git a/src/plugins/e-acsl/tests/arith/oracle_dev/at_on-purely-logic-variables.res.oracle b/src/plugins/e-acsl/tests/arith/oracle_dev/at_on-purely-logic-variables.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..63ab243f0f0ac90b52eb92796f458031b2f23bc9 --- /dev/null +++ b/src/plugins/e-acsl/tests/arith/oracle_dev/at_on-purely-logic-variables.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/arith/at_on-purely-logic-variables.c (with preprocessing) diff --git a/src/plugins/e-acsl/tests/arith/oracle_dev/cast.res.oracle b/src/plugins/e-acsl/tests/arith/oracle_dev/cast.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..4e888498a7d29bd018398fa488d5cd0bcd5d6caf --- /dev/null +++ b/src/plugins/e-acsl/tests/arith/oracle_dev/cast.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/arith/cast.i (no preprocessing) diff --git a/src/plugins/e-acsl/tests/arith/oracle_dev/comparison.res.oracle b/src/plugins/e-acsl/tests/arith/oracle_dev/comparison.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..8e470a21dcd8bc3a4fb7cbd653e6337840efddb5 --- /dev/null +++ b/src/plugins/e-acsl/tests/arith/oracle_dev/comparison.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/arith/comparison.i (no preprocessing) diff --git a/src/plugins/e-acsl/tests/arith/oracle_dev/functions.res.oracle b/src/plugins/e-acsl/tests/arith/oracle_dev/functions.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..26a62cddaa2b4afdf33d1692dae5a3a79c99e62c --- /dev/null +++ b/src/plugins/e-acsl/tests/arith/oracle_dev/functions.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/arith/functions.c (with preprocessing) diff --git a/src/plugins/e-acsl/tests/arith/oracle_dev/functions_rec.res.oracle b/src/plugins/e-acsl/tests/arith/oracle_dev/functions_rec.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..455ec56a835fd3d1536d3d10137cf67286160091 --- /dev/null +++ b/src/plugins/e-acsl/tests/arith/oracle_dev/functions_rec.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/arith/functions_rec.c (with preprocessing) diff --git a/src/plugins/e-acsl/tests/arith/oracle_dev/integer_constant.res.oracle b/src/plugins/e-acsl/tests/arith/oracle_dev/integer_constant.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..1b7f30270118bd782618efb4910af0ce98954bd0 --- /dev/null +++ b/src/plugins/e-acsl/tests/arith/oracle_dev/integer_constant.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/arith/integer_constant.i (no preprocessing) diff --git a/src/plugins/e-acsl/tests/arith/oracle_dev/let.res.oracle b/src/plugins/e-acsl/tests/arith/oracle_dev/let.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..803e26e12bb488545504f8066fe36c9f59a6de14 --- /dev/null +++ b/src/plugins/e-acsl/tests/arith/oracle_dev/let.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/arith/let.c (with preprocessing) diff --git a/src/plugins/e-acsl/tests/arith/oracle_dev/longlong.res.oracle b/src/plugins/e-acsl/tests/arith/oracle_dev/longlong.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..7e06012b6641a71b7d86732ac93f9801f42f1f5a --- /dev/null +++ b/src/plugins/e-acsl/tests/arith/oracle_dev/longlong.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/arith/longlong.i (no preprocessing) diff --git a/src/plugins/e-acsl/tests/arith/oracle_dev/not.res.oracle b/src/plugins/e-acsl/tests/arith/oracle_dev/not.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..58a67ef052fb929bfd6e270717f18174ad1403fe --- /dev/null +++ b/src/plugins/e-acsl/tests/arith/oracle_dev/not.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/arith/not.i (no preprocessing) diff --git a/src/plugins/e-acsl/tests/arith/oracle_dev/quantif.res.oracle b/src/plugins/e-acsl/tests/arith/oracle_dev/quantif.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..912f940b8d7f93255e66171733e59b74f0fb30ce --- /dev/null +++ b/src/plugins/e-acsl/tests/arith/oracle_dev/quantif.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/arith/quantif.i (no preprocessing) diff --git a/src/plugins/e-acsl/tests/arith/oracle_dev/rationals.res.oracle b/src/plugins/e-acsl/tests/arith/oracle_dev/rationals.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..ab4a875d1ad88731e1251bb3bf2f3097a47a32ea --- /dev/null +++ b/src/plugins/e-acsl/tests/arith/oracle_dev/rationals.res.oracle @@ -0,0 +1,4 @@ +[kernel] Parsing tests/arith/rationals.c (with preprocessing) +[kernel:parser:decimal-float] tests/arith/rationals.c:20: Warning: + Floating-point constant 0.2f is not represented exactly. Will use 0x1.99999a0000000p-3. + (warn-once: no further messages from category 'parser:decimal-float' will be emitted) diff --git a/src/plugins/e-acsl/tests/arith/quantif.i b/src/plugins/e-acsl/tests/arith/quantif.i new file mode 100644 index 0000000000000000000000000000000000000000..e7b792fd139adc9a46457206b7c2239ca6782e5c --- /dev/null +++ b/src/plugins/e-acsl/tests/arith/quantif.i @@ -0,0 +1,44 @@ +/* run.config + COMMENT: quantifiers +*/ + +int main(void) { + + // simple universal quantifications + + /*@ assert \forall integer x; 0 <= x <= 1 ==> x == 0 || x == 1; */ + /*@ assert \forall integer x; 0 < x <= 1 ==> x == 1; */ + /*@ assert \forall integer x; 0 <= x < 1 ==> x == 0; */ + + /* // multiple universal quantifications */ + + /*@ assert \forall integer x,y,z; 0 <= x < 2 && 0 <= y < 5 && 0 <= z <= y + ==> x+z <= y+1; */ + + // simple existential quantification + + /*@ assert \exists int x; 0 <= x < 10 && x == 5; */ + + // mixed universal and existential quantifications + + /*@ assert \forall int x; 0 <= x < 10 + ==> x % 2 == 0 ==> \exists integer y; 0 <= y <= x/2 && x == 2 * y; */ + + { // Gitlab issue #42 + int buf[10]; + unsigned long len = 9; + /*@ assert \forall integer i; 0 <= i < 10 ==> \valid(buf+i); */ + /*@ assert \forall char i; 0 <= i < 10 ==> \valid(buf+i); */ + /*@ assert \forall integer i; 0 <= i < len ==> \valid(buf+i); */ + /*@ assert \forall integer i; 0 <= i <= len ==> \valid(buf+i); */ + } + + // Empty quantifications + /*@ assert \forall integer x; 0 < x < 1 ==> \false; */ + /*@ assert ! \exists char c; 10 <= c < 10 && c == 10; */ ; + /*@ assert + \let u = 5; + \forall integer x,y; 0 <= x < 2 && 4 < y < u ==> \false; */ ; + + return 0; +} diff --git a/src/plugins/e-acsl/tests/arith/rationals.c b/src/plugins/e-acsl/tests/arith/rationals.c new file mode 100644 index 0000000000000000000000000000000000000000..84c8b0949b4d44178f43101ad840b05ad734d50e --- /dev/null +++ b/src/plugins/e-acsl/tests/arith/rationals.c @@ -0,0 +1,38 @@ +/* real numbers */ + +/*@ ensures + \let delta = 1; + \let avg_real = (a+b)/2; + avg_real - delta < \result < avg_real + delta; */ +double avg(double a, double b) { + return (a+b)/2; +} + +int main(void) { + /*@ assert 3 != 1.5; */ ; + /*@ assert 3 == 1.5 + 1.5; */ ; + /*@ assert 0.1 == 0.1; */ ; + /*@ assert (double)1.0 == 1.0; */ ; + /*@ assert (double)0.1 != 0.1; */ ; + /*@ assert (float)0.1 != (double)0.1; */ ; + /*@ assert (double)1.1 != 1 + 0.1 ;*/ ; + /*@ assert 1 + 0.1 == 2 - 0.9; */ ; + float x = 0.2f, + y = 0.3f, + sum = x + y; + /*@ assert sum != x * y; */ ; + /* @ assert \let n = 1; 4 == n + 3.0; */ ; // TODO: fail at runtime, I don't know why + + double d = 0.1; + + avg(4.3, 11.7); + + /*@ assert 1.1d != 1 + 0.1; */ ; + + // Not yet: + // long double ld = 0.1l; + // /*@ assert d + 1 != ld + 1; */ ; // long double + // /*@ assert 3 != 1e5; */ ; // number not written in decimal expansion form + ///*@ assert \let n = 99999999999999999999999999; + // 4 != n + 3.7; */ ; // creating Q from Z +} diff --git a/src/plugins/e-acsl/tests/arith/result_ci/.gitkeep b/src/plugins/e-acsl/tests/arith/result_ci/.gitkeep new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/plugins/e-acsl/tests/bts/bts1304.i b/src/plugins/e-acsl/tests/bts/bts1304.i new file mode 100644 index 0000000000000000000000000000000000000000..d133368666af220af85ad3152209a9ace9aa2470 --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/bts1304.i @@ -0,0 +1,25 @@ +/* run.config + COMMENT: argument of functions must be kept, so keep its parameter +*/ + +struct msgA { int type; int a[2]; }; +struct msgB { int type; double x; }; +union msg { + struct { int type; } T; + struct msgA A; + struct msgB B; +}; + +void read_sensor_4(unsigned* m) { + /* put 4 bytes from sensors into m */ + *m = 0; +} + +int main(void) { + unsigned char buf[sizeof(union msg)]; + int i; + for(i = 0; i < sizeof(buf)/4; i++) + read_sensor_4((unsigned*)buf+i); + /*@ assert \initialized((union msg*)buf); */ + return 0; +} diff --git a/src/plugins/e-acsl/tests/bts/bts1307.i b/src/plugins/e-acsl/tests/bts/bts1307.i new file mode 100644 index 0000000000000000000000000000000000000000..2932f7253cf920f4546e25badf495df2c1e7b384 --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/bts1307.i @@ -0,0 +1,37 @@ +/* run.config + COMMENT: spec with floats and reals +*/ + +/*@ requires \valid(Mtmax_in); + @ requires \valid(Mwmax); + @ requires \valid(Mtmax_out); + + @ behavior OverEstimate_Motoring: + @ assumes \true; + @ ensures *Mtmax_out != *Mtmax_in + (5 - (((5 / 80) * *Mwmax) * 0.4)); + @*/ +void foo(float* Mtmax_in, float* Mwmax, float* Mtmax_out) { + /* Real semantics and floating-point semantics give different results because: + 1) Mtmax_out is 5.975 is in R + 2) The float closest to 5.975 is 5.97499999999999964472863211995 */ + *Mtmax_out = *Mtmax_in + (5 - (((5 / 80) * *Mwmax) * 0.4)); +} + +/*@ requires \valid(Mtmin_in); + @ requires \valid(Mwmin); + @ requires \valid(Mtmin_out); + @ + @ behavior UnderEstimate_Motoring: + @ assumes \true; + @ ensures *Mtmin_out == *Mtmin_in < 0.85 * *Mwmin ? *Mtmin_in : 0.85 * *Mwmin; + @*/ +void bar(float* Mtmin_in, float* Mwmin, float* Mtmin_out) { + *Mtmin_out = 0.85 * *Mwmin; +} + +int main(void) { + float f = 1.0, g = 1.0, h; + foo(&f, &g, &h); + bar(&f, &g, &h); + return 0; +} diff --git a/src/plugins/e-acsl/tests/bts/bts1324.i b/src/plugins/e-acsl/tests/bts/bts1324.i new file mode 100644 index 0000000000000000000000000000000000000000..690b29043baca4b8e32f5c69afd63f00caa10df0 --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/bts1324.i @@ -0,0 +1,25 @@ +/* run.config + COMMENT: fixed bug with typing of universal quantification +*/ + +/*@ behavior yes: + @ assumes \forall int i; 0 < i < n ==> t[i-1] <= t[i]; + @ ensures \result == 1; + @*/ +int sorted(int * t, int n) { + int b = 1; + if(n <= 1) + return 1; + for(b = 1; b < n; b++) { + if(t[b-1] > t[b]) + return 0; + } + return 1; +} + +int main(void) { + int t[7] = { 1, 4, 4, 5, 5, 5, 7 }; + int n = sorted(t, 7); + /*@ assert n == 1; */ + return 0; +} diff --git a/src/plugins/e-acsl/tests/bts/bts1326.i b/src/plugins/e-acsl/tests/bts/bts1326.i new file mode 100644 index 0000000000000000000000000000000000000000..c8e7429eefcca32ce60658c4a83bbd0223216dcb --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/bts1326.i @@ -0,0 +1,21 @@ +/* run.config + COMMENT: complex term left-values +*/ + +typedef int ArrayInt[5]; + +/*@ ensures + *AverageAccel == + ((*Accel)[4] + (*Accel)[3] + (*Accel)[2] + (*Accel)[1] + (*Accel)[0]) / 5; @*/ +void atp_NORMAL_computeAverageAccel(ArrayInt* Accel,int* AverageAccel) +{ + *AverageAccel = + ((*Accel)[4] + (*Accel)[3] + (*Accel)[2] + (*Accel)[1] + (*Accel)[0]) / 5; +} + +int main(void) { + ArrayInt Accel = { 1, 2, 3, 4, 5 }; + int av; + atp_NORMAL_computeAverageAccel(&Accel, &av); + return 0; +} diff --git a/src/plugins/e-acsl/tests/bts/bts1390.c b/src/plugins/e-acsl/tests/bts/bts1390.c new file mode 100644 index 0000000000000000000000000000000000000000..74cba86cdbefc49eb207bda3bdbe6f3178c5f15c --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/bts1390.c @@ -0,0 +1,27 @@ +/* run.config + COMMENT: bts #1390, issue with typing of quantified variables +*/ + +#include "stdlib.h" + +/*@behavior exists: + assumes \exists integer i; 0 <= i < (int)n && ((char*)buf)[i] == c; + ensures \forall int j; 0 <= j < (int)\offset((char*)\result) ==> ((char*)buf)[j] != c; + behavior not_exists: + assumes \forall integer k; 0 <= k < (int)n ==> ((char*)buf)[k] != c; + ensures \result == (void*) 0; */ +void *memchr(const void *buf, int c, size_t n) { + int i; + char *s = buf; + for(i = 0; i < n; i++) { + if(*s == c) return s; + s++; + } + return (void*)0; +} + +int main(void) { + memchr("toto", 'o', 4); + memchr("tata", 'o', 4); + return 0; +} diff --git a/src/plugins/e-acsl/tests/bts/bts1395.i b/src/plugins/e-acsl/tests/bts/bts1395.i new file mode 100644 index 0000000000000000000000000000000000000000..ef01c83d78b3a55f12e943321f73fdc7567fe102 --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/bts1395.i @@ -0,0 +1,16 @@ +/* run.config_ci + COMMENT: recursive function + STDOPT: +"-eva-ignore-recursive-calls" +*/ + +/*@ requires n > 0; */ +int fact(int n) { + if (n == 1) return 1; + return n * fact(n - 1); +} + +int main() { + int x = fact(5); + /*@ assert x == 120; */ + return 0; +} diff --git a/src/plugins/e-acsl/tests/bts/bts1398.c b/src/plugins/e-acsl/tests/bts/bts1398.c new file mode 100644 index 0000000000000000000000000000000000000000..9d299958c7e22790f9e6d218fc4343816a2bcebe --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/bts1398.c @@ -0,0 +1,13 @@ +/* run.config + COMMENT: variadic function call +*/ + +#include "stdio.h" + +int main(void) { + int x = 0, t[2]; + int i = 1; + t[0] = 1; + t[1] = 2; + printf("X=%d, t[0]=%d, t[1]=%d\n", x, t[0], t[i]); +} diff --git a/src/plugins/e-acsl/tests/bts/bts1399.c b/src/plugins/e-acsl/tests/bts/bts1399.c new file mode 100644 index 0000000000000000000000000000000000000000..4e2266935d9412df8b276bbcf2706953c3fb3bba --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/bts1399.c @@ -0,0 +1,25 @@ +/* run.config + COMMENT: complex fields and indexes + potential RTE in \initialized +*/ + +#include "stdlib.h" + +struct spongeStateStruct { + unsigned char __attribute__((__aligned__(32))) state[1600 / 8] ; + unsigned char __attribute__((__aligned__(32))) dataQueue[1536 / 8] ; + unsigned int bitsInQueue ; +} __attribute__((__aligned__(32))); +typedef struct spongeStateStruct spongeState; + +int main(void) { + spongeState* state = (spongeState*) malloc(sizeof(spongeState)); + state->bitsInQueue = 16; + + /*@ assert + ! \initialized(&state->dataQueue[state->bitsInQueue/(unsigned int)8]); + */ + + free(state); + return 0; +} + diff --git a/src/plugins/e-acsl/tests/bts/bts1478.c b/src/plugins/e-acsl/tests/bts/bts1478.c new file mode 100644 index 0000000000000000000000000000000000000000..b949470b2d922eef32802141472f23a9c8bc42ab --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/bts1478.c @@ -0,0 +1,17 @@ +/* run.config + COMMENT: bts #1478 about wrong detection of initializers in pre-analysis +*/ + +int global_i; +int* global_i_ptr = &global_i; +int global_i = 0; + +/*@ requires global_i == 0; + requires \valid(global_i_ptr); + requires global_i_ptr == &global_i; */ +void loop(void) { } + +int main(void) { + loop(); + return 0; +} diff --git a/src/plugins/e-acsl/tests/bts/bts1700.i b/src/plugins/e-acsl/tests/bts/bts1700.i new file mode 100644 index 0000000000000000000000000000000000000000..efd10126c2c6b7b7ca9b9c8a4d80659fee75d2fe --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/bts1700.i @@ -0,0 +1,14 @@ +/* run.config + COMMENT: pointer to an empty struct +*/ + +struct toto {}; + +int main() { + struct toto s; + //@ assert \valid(&s); + struct toto *p; + p = &s; + //@ assert \valid(p); + return 0; +} diff --git a/src/plugins/e-acsl/tests/bts/bts1717.i b/src/plugins/e-acsl/tests/bts/bts1717.i new file mode 100644 index 0000000000000000000000000000000000000000..71ce1f22484e46ae5c111ff9ba9692ed1a647d31 --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/bts1717.i @@ -0,0 +1,16 @@ +/* run.config + COMMENT: bts #1717, issue with labels on memory-related statements +*/ + +int main(void) { + int a = 10, *p; + goto lbl_1; + + lbl_2: + /*@ assert \valid(p); */ + return 0; + + lbl_1: + p = &a; + goto lbl_2; +} diff --git a/src/plugins/e-acsl/tests/bts/bts1718.i b/src/plugins/e-acsl/tests/bts/bts1718.i new file mode 100644 index 0000000000000000000000000000000000000000..2434f530b8607ff42c7032f45f1ed70bd1029cd9 --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/bts1718.i @@ -0,0 +1,19 @@ +/* run.config + COMMENT: bts #1718, issue regarding incorrect initialization of literal strings in global arrays with compound initializers + COMMENT: no diff + COMMENT: no diff + COMMENT: no diff +*/ + +int main(void) { + int a = 10, *p; + goto lbl_1; + + lbl_2: + /*@ assert \valid(p); */ + return 0; + + lbl_1: + p = &a; + goto lbl_2; +} diff --git a/src/plugins/e-acsl/tests/bts/bts1740.i b/src/plugins/e-acsl/tests/bts/bts1740.i new file mode 100644 index 0000000000000000000000000000000000000000..98e99dc7358c69c4d66e322b75829050a4dacb71 --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/bts1740.i @@ -0,0 +1,18 @@ +/* run.config + COMMENT: bts #1740, about failure to correctly track local variables + in presence of goto +*/ + +int main(void) { + int *p; + { + int a = 0; + p = &a; + /*@ assert \valid(p); */ + goto L; + } + + L: + /*@ assert ! \valid(p); */ + return 0; +} diff --git a/src/plugins/e-acsl/tests/bts/bts1837.i b/src/plugins/e-acsl/tests/bts/bts1837.i new file mode 100644 index 0000000000000000000000000000000000000000..dc481afd0ee374231db5d9429b0f29316cbebdee --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/bts1837.i @@ -0,0 +1,24 @@ +/* run.config + COMMENT: bts #1837, about initialization of literal strings +*/ + +char *S = "foo"; + +int f(void) { + char *s1 = "foo"; + char *s2 = "bar"; + /*@ assert \valid_read(S); */ + /*@ assert \valid_read(s1); */ + /*@ assert \valid_read(s2); */ + return 0; +} + +int main(void) { + int i = 4; + while (i--) { + char *s = "toto"; + /*@ assert \valid_read(s) ; */ + /*@ assert !\valid(s) ; */ + } + f(); +} diff --git a/src/plugins/e-acsl/tests/bts/bts2191.c b/src/plugins/e-acsl/tests/bts/bts2191.c new file mode 100644 index 0000000000000000000000000000000000000000..8ce8acf7fa83169d40763aed125cca1b7817f8a8 --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/bts2191.c @@ -0,0 +1,24 @@ +/* run.config + COMMENT: bts #2191, issue with unrolling types of struct members +*/ + +struct ST { + char *str; + int num; +}; + +struct ST _G[] = { + { + .str = "Struct_G[0]", + .num = 99 + }, + { + .str = "Struct_G[1]", + .num = 147 + } +}; + +int main(int argc, char **argv) { + /*@ assert \valid_read(_G[0].str); */ + return 0; +} diff --git a/src/plugins/e-acsl/tests/bts/bts2192.c b/src/plugins/e-acsl/tests/bts/bts2192.c new file mode 100644 index 0000000000000000000000000000000000000000..89fdf25dae7c6b6d6b4d689aed8290c512d03591 --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/bts2192.c @@ -0,0 +1,11 @@ +/* run.config + COMMENT: bts #2292, failures due to unregistered RTL functions +*/ + +#include <stdlib.h> + +int a; +char *n = "134"; +int main(int argc, char **argv) { + a = argc = atoi(n); +} diff --git a/src/plugins/e-acsl/tests/bts/bts2231.i b/src/plugins/e-acsl/tests/bts/bts2231.i new file mode 100644 index 0000000000000000000000000000000000000000..8040723e115afb78b9ed45da517570e2231b4c18 --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/bts2231.i @@ -0,0 +1,10 @@ +/* run.config + COMMENT: bts #2231, issue with typing of casts +*/ + +long A = 0; + +int main(void) { + /*@ assert A + (long)((long)(3 * A) - 1) == -1; */ + return 0; +} diff --git a/src/plugins/e-acsl/tests/bts/bts2252.c b/src/plugins/e-acsl/tests/bts/bts2252.c new file mode 100644 index 0000000000000000000000000000000000000000..c52b56d04f0cd46500998328172f2f3c9d3c43a3 --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/bts2252.c @@ -0,0 +1,25 @@ +/* run.config + COMMENT: bts #2252, failures due to typing of offsets +*/ + +#include <stdlib.h> + +int main() { + char* srcbuf = "Test Code"; + int i, loc = 1; + + char * destbuf = (char*)malloc(10*sizeof(char)); + char ch = 'o'; + + if (destbuf != NULL) { + for (i = -1; i < 0; i++) { + /*@ assert ! \valid_read(srcbuf + i); */ + if (srcbuf[i] == ch) { /* ERROR: Buffer Underrun */ + loc = i; + } + } + + strncpy (&destbuf[loc], &srcbuf[loc], 1); + free(destbuf); + } +} diff --git a/src/plugins/e-acsl/tests/bts/bts2305.c b/src/plugins/e-acsl/tests/bts/bts2305.c new file mode 100644 index 0000000000000000000000000000000000000000..4b35e986c7601c42f74cd6e44841c2f8e9cfef3a --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/bts2305.c @@ -0,0 +1,24 @@ +/* run.config + COMMENT: bts #2305, taking the address of a bitfield +*/ + +#include <stdbool.h> + +struct bitfields { + int i : 2; + bool j : 1; +} t; + +int test(struct bitfields *a) +{ + return a->i; +} + +int main(int argc, char **argv) +{ + //@ assert \valid_read(&(t.j)); + //@ assert \valid_read(&(t.j) + (1..3)); + t.j = 1; + //@ assert \initialized(&(t.j)); + return test(&t); +} diff --git a/src/plugins/e-acsl/tests/bts/bts2386.c b/src/plugins/e-acsl/tests/bts/bts2386.c new file mode 100644 index 0000000000000000000000000000000000000000..007b5c1523db429bdd25baee480d4ccb1fdfcd97 --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/bts2386.c @@ -0,0 +1,15 @@ +/* run.config, run.config_2 + COMMENT: pointer substraction +*/ + +void f(const void *s, int c, unsigned long n) { + const unsigned char *p = s; + /*@ assert p - s == n - n; */ + /*@ assert p - s == 0; */ +} + +int main() { + const char *s = "1234567890"; + f(s, '0', 11); + return 0; +} diff --git a/src/plugins/e-acsl/tests/bts/bts2406.c b/src/plugins/e-acsl/tests/bts/bts2406.c new file mode 100644 index 0000000000000000000000000000000000000000..30c52958e421f3d6cb4e2b49561a4b28456620e6 --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/bts2406.c @@ -0,0 +1,13 @@ +/* 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; +} diff --git a/src/plugins/e-acsl/tests/bts/issue69.c b/src/plugins/e-acsl/tests/bts/issue69.c new file mode 100644 index 0000000000000000000000000000000000000000..c571c92c749ba327e179f07346aa802a0092f204 --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/issue69.c @@ -0,0 +1,12 @@ +/* run.config + COMMENT: typing bug of Issue 69 +*/ + +int main(void) { + /*@ assert \forall unsigned char c; 4 <= c <= 300 ==> 0 <= c <= 255; */ ; + + int n = 5; + /*@ assert + \let m = n > 0 ? 4 : 341; + \forall char u; 1 < u < m ==> u > 0; */ ; +} diff --git a/src/plugins/e-acsl/tests/bts/oracle_ci/bts1304.res.oracle b/src/plugins/e-acsl/tests/bts/oracle_ci/bts1304.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..7ed893863acfe028294169a16128b821cd57ca15 --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/oracle_ci/bts1304.res.oracle @@ -0,0 +1,3 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". +[eva:alarm] tests/bts/bts1304.i:23: Warning: assertion got status unknown. diff --git a/src/plugins/e-acsl/tests/bts/oracle_ci/bts1307.res.oracle b/src/plugins/e-acsl/tests/bts/oracle_ci/bts1307.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..0491679011cca98bc2b52203673139ae77988bd6 --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/oracle_ci/bts1307.res.oracle @@ -0,0 +1,9 @@ +[kernel:parser:decimal-float] tests/bts/bts1307.i:17: Warning: + Floating-point constant 0.4 is not represented exactly. Will use 0x1.999999999999ap-2. + (warn-once: no further messages from category 'parser:decimal-float' will be emitted) +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". +[eva:alarm] tests/bts/bts1307.i:11: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/bts/bts1307.i:11: Warning: + function __gen_e_acsl_foo, behavior OverEstimate_Motoring: postcondition got status invalid. diff --git a/src/plugins/e-acsl/tests/bts/oracle_ci/bts1324.res.oracle b/src/plugins/e-acsl/tests/bts/oracle_ci/bts1324.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..8a979d24b47fbca95ad85e05fbdfd4446a7fd8eb --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/oracle_ci/bts1324.res.oracle @@ -0,0 +1,4 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". +[eva:alarm] tests/bts/bts1324.i:6: Warning: + function __e_acsl_assert: precondition got status unknown. diff --git a/src/plugins/e-acsl/tests/bts/oracle_ci/bts1326.res.oracle b/src/plugins/e-acsl/tests/bts/oracle_ci/bts1326.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..efd026311297e55d8fefb674326118e6ece88624 --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/oracle_ci/bts1326.res.oracle @@ -0,0 +1,2 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". diff --git a/src/plugins/e-acsl/tests/bts/oracle_ci/bts1390.res.oracle b/src/plugins/e-acsl/tests/bts/oracle_ci/bts1390.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..929213a9cd28be0c159806a3a650b1cf7b651dfe --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/oracle_ci/bts1390.res.oracle @@ -0,0 +1,12 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". +[eva:builtins:missing-spec] tests/bts/bts1390.c:13: Warning: + The builtin for function memchr will not be used, as its frama-c libc specification is not available. +[eva:alarm] tests/bts/bts1390.c:11: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/bts/bts1390.c:8: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/bts/bts1390.c:12: Warning: + function __gen_e_acsl_memchr, behavior not_exists: postcondition got status unknown. (Behavior may be inactive, no reduction performed.) +[eva:alarm] tests/bts/bts1390.c:17: Warning: + out of bounds read. assert \valid_read(s); diff --git a/src/plugins/e-acsl/tests/bts/oracle_ci/bts1395.res.oracle b/src/plugins/e-acsl/tests/bts/oracle_ci/bts1395.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..ea1cf8d1c6a78f3d1b0e3848de85ba662f87849f --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/oracle_ci/bts1395.res.oracle @@ -0,0 +1,15 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". +[eva] tests/bts/bts1395.i:9: Warning: + recursive call during value analysis + of __gen_e_acsl_fact (__gen_e_acsl_fact <- fact :: tests/bts/bts1395.i:7 <- + __gen_e_acsl_fact :: tests/bts/bts1395.i:13 <- + main). + Assuming the call has no effect. The analysis will be unsound. +[eva:alarm] tests/bts/bts1395.i:9: Warning: + signed overflow. assert -2147483648 ≤ n * tmp; + (tmp from fact(n - 1)) +[eva:alarm] tests/bts/bts1395.i:9: Warning: + signed overflow. assert n * tmp ≤ 2147483647; + (tmp from fact(n - 1)) +[eva:alarm] tests/bts/bts1395.i:14: Warning: assertion got status unknown. diff --git a/src/plugins/e-acsl/tests/bts/oracle_ci/bts1398.res.oracle b/src/plugins/e-acsl/tests/bts/oracle_ci/bts1398.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..9811cdbf49f1324c0f4cffd3aed7d450deac04cb --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/oracle_ci/bts1398.res.oracle @@ -0,0 +1,4 @@ +[e-acsl] beginning translation. +[kernel:annot:missing-spec] FRAMAC_SHARE/libc/stdio.h:169: Warning: + Neither code nor specification for function printf, generating default assigns from the prototype +[e-acsl] translation done in project "e-acsl". diff --git a/src/plugins/e-acsl/tests/bts/oracle_ci/bts1399.res.oracle b/src/plugins/e-acsl/tests/bts/oracle_ci/bts1399.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..efd026311297e55d8fefb674326118e6ece88624 --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/oracle_ci/bts1399.res.oracle @@ -0,0 +1,2 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". diff --git a/src/plugins/e-acsl/tests/bts/oracle_ci/bts1478.res.oracle b/src/plugins/e-acsl/tests/bts/oracle_ci/bts1478.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..efd026311297e55d8fefb674326118e6ece88624 --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/oracle_ci/bts1478.res.oracle @@ -0,0 +1,2 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". diff --git a/src/plugins/e-acsl/tests/bts/oracle_ci/bts1700.res.oracle b/src/plugins/e-acsl/tests/bts/oracle_ci/bts1700.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..efd026311297e55d8fefb674326118e6ece88624 --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/oracle_ci/bts1700.res.oracle @@ -0,0 +1,2 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". diff --git a/src/plugins/e-acsl/tests/bts/oracle_ci/bts1717.res.oracle b/src/plugins/e-acsl/tests/bts/oracle_ci/bts1717.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..efd026311297e55d8fefb674326118e6ece88624 --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/oracle_ci/bts1717.res.oracle @@ -0,0 +1,2 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". diff --git a/src/plugins/e-acsl/tests/bts/oracle_ci/bts1718.res.oracle b/src/plugins/e-acsl/tests/bts/oracle_ci/bts1718.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..efd026311297e55d8fefb674326118e6ece88624 --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/oracle_ci/bts1718.res.oracle @@ -0,0 +1,2 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". diff --git a/src/plugins/e-acsl/tests/bts/oracle_ci/bts1740.res.oracle b/src/plugins/e-acsl/tests/bts/oracle_ci/bts1740.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..120779645cf314b1e6e1d9272bf454d1899ca0f5 --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/oracle_ci/bts1740.res.oracle @@ -0,0 +1,7 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". +[eva:locals-escaping] tests/bts/bts1740.i:12: Warning: + locals {a} escaping the scope of a block of main through p +[eva:alarm] tests/bts/bts1740.i:16: Warning: + accessing left-value that contains escaping addresses. + assert ¬\dangling(&p); diff --git a/src/plugins/e-acsl/tests/bts/oracle_ci/bts1837.res.oracle b/src/plugins/e-acsl/tests/bts/oracle_ci/bts1837.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..165ce48945b89f9838d52d8a96bbaf8ffd461004 --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/oracle_ci/bts1837.res.oracle @@ -0,0 +1,4 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". +[eva:alarm] tests/bts/bts1837.i:18: Warning: + signed overflow. assert -2147483648 ≤ i - 1; diff --git a/src/plugins/e-acsl/tests/bts/oracle_ci/bts2191.res.oracle b/src/plugins/e-acsl/tests/bts/oracle_ci/bts2191.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..efd026311297e55d8fefb674326118e6ece88624 --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/oracle_ci/bts2191.res.oracle @@ -0,0 +1,2 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". diff --git a/src/plugins/e-acsl/tests/bts/oracle_ci/bts2192.res.oracle b/src/plugins/e-acsl/tests/bts/oracle_ci/bts2192.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..f96be2395e669ee4f969c86a91991270c922660a --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/oracle_ci/bts2192.res.oracle @@ -0,0 +1,8 @@ +[e-acsl] beginning translation. +[e-acsl] Warning: annotating undefined function `atoi': + the generated program may miss memory instrumentation + if there are memory-related annotations. +[e-acsl] FRAMAC_SHARE/libc/stdlib.h:78: Warning: + E-ACSL construct `assigns clause in behavior' is not yet supported. + Ignoring annotation. +[e-acsl] translation done in project "e-acsl". diff --git a/src/plugins/e-acsl/tests/bts/oracle_ci/bts2231.res.oracle b/src/plugins/e-acsl/tests/bts/oracle_ci/bts2231.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..c9e73aad0c84090a1269e428a28da811ecc35f28 --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/oracle_ci/bts2231.res.oracle @@ -0,0 +1,6 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". +[eva:alarm] tests/bts/bts2231.i:8: Warning: + signed overflow. assert -9223372036854775808 ≤ __gen_e_acsl__2 - 1; +[eva:alarm] tests/bts/bts2231.i:8: Warning: + function __e_acsl_assert: precondition got status unknown. diff --git a/src/plugins/e-acsl/tests/bts/oracle_ci/bts2252.res.oracle b/src/plugins/e-acsl/tests/bts/oracle_ci/bts2252.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..f08bfb36ef3f54d6a5f260ea13b2b6c104d12aac --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/oracle_ci/bts2252.res.oracle @@ -0,0 +1,8 @@ +[kernel:typing:implicit-function-declaration] tests/bts/bts2252.c:22: Warning: + Calling undeclared function strncpy. Old style K&R code? +[e-acsl] beginning translation. +[kernel:annot:missing-spec] tests/bts/bts2252.c:22: Warning: + Neither code nor specification for function strncpy, generating default assigns from the prototype +[e-acsl] translation done in project "e-acsl". +[eva:alarm] tests/bts/bts2252.c:17: Warning: + out of bounds read. assert \valid_read(srcbuf + i); diff --git a/src/plugins/e-acsl/tests/bts/oracle_ci/bts2305.res.oracle b/src/plugins/e-acsl/tests/bts/oracle_ci/bts2305.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..d005b10c5ba8df208b3a3a00ecf0a0587370dd13 --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/oracle_ci/bts2305.res.oracle @@ -0,0 +1,11 @@ +[e-acsl] beginning translation. +[e-acsl] tests/bts/bts2305.c:19: Warning: + E-ACSL construct `bitfield pointer' is not yet supported. + Ignoring annotation. +[e-acsl] tests/bts/bts2305.c:20: Warning: + E-ACSL construct `bitfield pointer' is not yet supported. + Ignoring annotation. +[e-acsl] tests/bts/bts2305.c:22: Warning: + E-ACSL construct `bitfield pointer' is not yet supported. + Ignoring annotation. +[e-acsl] translation done in project "e-acsl". diff --git a/src/plugins/e-acsl/tests/bts/oracle_ci/bts2386.res.oracle b/src/plugins/e-acsl/tests/bts/oracle_ci/bts2386.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..46b9b8d4ff2388fc39a6e887bd54dbf9e3a4429b --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/oracle_ci/bts2386.res.oracle @@ -0,0 +1,4 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". +[eva:alarm] tests/bts/bts2386.c:7: Warning: + function __e_acsl_assert: precondition got status unknown. diff --git a/src/plugins/e-acsl/tests/bts/oracle_ci/bts2406.res.oracle b/src/plugins/e-acsl/tests/bts/oracle_ci/bts2406.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..7204dfeb385390bb901569f8c0105af8c35aa9f3 --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/oracle_ci/bts2406.res.oracle @@ -0,0 +1,5 @@ +[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.) diff --git a/src/plugins/e-acsl/tests/bts/oracle_ci/gen_bts1304.c b/src/plugins/e-acsl/tests/bts/oracle_ci/gen_bts1304.c new file mode 100644 index 0000000000000000000000000000000000000000..a663809e2501349e94ffd9d5bcc71daac8e1d104 --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/oracle_ci/gen_bts1304.c @@ -0,0 +1,57 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +struct msgA { + int type ; + int a[2] ; +}; +struct msgB { + int type ; + double x ; +}; +struct __anonstruct_T_1 { + int type ; +}; +union msg { + struct __anonstruct_T_1 T ; + struct msgA A ; + struct msgB B ; +}; +void read_sensor_4(unsigned int *m) +{ + __e_acsl_store_block((void *)(& m),(size_t)8); + __e_acsl_initialize((void *)m,sizeof(unsigned int)); + *m = (unsigned int)0; + __e_acsl_delete_block((void *)(& m)); + return; +} + +int main(void) +{ + int __retres; + unsigned char buf[sizeof(union msg)]; + int i; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + __e_acsl_store_block((void *)(buf),(size_t)16); + i = 0; + while ((unsigned long)i < sizeof(buf) / (unsigned long)4) { + read_sensor_4((unsigned int *)(buf) + i); + i ++; + } + /*@ assert \initialized((union msg *)((unsigned char *)buf)); */ + { + int __gen_e_acsl_initialized; + __gen_e_acsl_initialized = __e_acsl_initialized((void *)(buf), + sizeof(union msg)); + __e_acsl_assert(__gen_e_acsl_initialized,(char *)"Assertion", + (char *)"main", + (char *)"\\initialized((union msg *)((unsigned char *)buf))", + 23); + } + __retres = 0; + __e_acsl_delete_block((void *)(buf)); + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/bts/oracle_ci/gen_bts1307.c b/src/plugins/e-acsl/tests/bts/oracle_ci/gen_bts1307.c new file mode 100644 index 0000000000000000000000000000000000000000..c5ca246ce62c926a23616be2649c675d0a121fcf --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/oracle_ci/gen_bts1307.c @@ -0,0 +1,328 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +extern int __e_acsl_sound_verdict; + +/*@ requires \valid(Mtmax_in); + requires \valid(Mwmax); + requires \valid(Mtmax_out); + + behavior OverEstimate_Motoring: + assumes \true; + ensures + *\old(Mtmax_out) ≢ + *\old(Mtmax_in) + (5 - ((5 / 80) * *\old(Mwmax)) * 0.4); + */ +void __gen_e_acsl_foo(float *Mtmax_in, float *Mwmax, float *Mtmax_out); + +void foo(float *Mtmax_in, float *Mwmax, float *Mtmax_out) +{ + __e_acsl_store_block((void *)(& Mtmax_out),(size_t)8); + __e_acsl_store_block((void *)(& Mwmax),(size_t)8); + __e_acsl_store_block((void *)(& Mtmax_in),(size_t)8); + __e_acsl_initialize((void *)Mtmax_out,sizeof(float)); + *Mtmax_out = (float)((double)*Mtmax_in + ((double)5 - (double)((float)( + 5 / 80) * *Mwmax) * 0.4)); + __e_acsl_delete_block((void *)(& Mtmax_out)); + __e_acsl_delete_block((void *)(& Mwmax)); + __e_acsl_delete_block((void *)(& Mtmax_in)); + return; +} + +/*@ requires \valid(Mtmin_in); + requires \valid(Mwmin); + requires \valid(Mtmin_out); + + behavior UnderEstimate_Motoring: + assumes \true; + ensures + *\old(Mtmin_out) ≡ *\old(Mtmin_in) < 0.85 * *\old(Mwmin)? + *\old(Mtmin_in) ≢ 0.: + 0.85 * *\old(Mwmin) ≢ 0.; + */ +void __gen_e_acsl_bar(float *Mtmin_in, float *Mwmin, float *Mtmin_out); + +void bar(float *Mtmin_in, float *Mwmin, float *Mtmin_out) +{ + __e_acsl_store_block((void *)(& Mtmin_out),(size_t)8); + __e_acsl_store_block((void *)(& Mwmin),(size_t)8); + __e_acsl_store_block((void *)(& Mtmin_in),(size_t)8); + __e_acsl_initialize((void *)Mtmin_out,sizeof(float)); + *Mtmin_out = (float)(0.85 * (double)*Mwmin); + __e_acsl_delete_block((void *)(& Mtmin_out)); + __e_acsl_delete_block((void *)(& Mwmin)); + __e_acsl_delete_block((void *)(& Mtmin_in)); + return; +} + +int main(void) +{ + int __retres; + float h; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + __e_acsl_store_block((void *)(& h),(size_t)4); + float f = (float)1.0; + __e_acsl_store_block((void *)(& f),(size_t)4); + __e_acsl_full_init((void *)(& f)); + float g = (float)1.0; + __e_acsl_store_block((void *)(& g),(size_t)4); + __e_acsl_full_init((void *)(& g)); + __gen_e_acsl_foo(& f,& g,& h); + __gen_e_acsl_bar(& f,& g,& h); + __retres = 0; + __e_acsl_delete_block((void *)(& h)); + __e_acsl_delete_block((void *)(& g)); + __e_acsl_delete_block((void *)(& f)); + __e_acsl_memory_clean(); + return __retres; +} + +/*@ requires \valid(Mtmin_in); + requires \valid(Mwmin); + requires \valid(Mtmin_out); + + behavior UnderEstimate_Motoring: + assumes \true; + ensures + *\old(Mtmin_out) ≡ *\old(Mtmin_in) < 0.85 * *\old(Mwmin)? + *\old(Mtmin_in) ≢ 0.: + 0.85 * *\old(Mwmin) ≢ 0.; + */ +void __gen_e_acsl_bar(float *Mtmin_in, float *Mwmin, float *Mtmin_out) +{ + float *__gen_e_acsl_at_6; + float *__gen_e_acsl_at_5; + float *__gen_e_acsl_at_4; + float *__gen_e_acsl_at_3; + float *__gen_e_acsl_at_2; + float *__gen_e_acsl_at; + __gen_e_acsl_at_6 = Mwmin; + __gen_e_acsl_at_5 = Mtmin_in; + __gen_e_acsl_at_4 = Mwmin; + __gen_e_acsl_at_3 = Mtmin_in; + __gen_e_acsl_at_2 = Mtmin_in; + __gen_e_acsl_at = Mtmin_out; + { + int __gen_e_acsl_valid; + int __gen_e_acsl_valid_2; + int __gen_e_acsl_valid_3; + __e_acsl_store_block((void *)(& Mtmin_out),(size_t)8); + __e_acsl_store_block((void *)(& Mwmin),(size_t)8); + __e_acsl_store_block((void *)(& Mtmin_in),(size_t)8); + __gen_e_acsl_valid = __e_acsl_valid((void *)Mtmin_in,sizeof(float), + (void *)Mtmin_in, + (void *)(& Mtmin_in)); + __e_acsl_assert(__gen_e_acsl_valid,(char *)"Precondition",(char *)"bar", + (char *)"\\valid(Mtmin_in)",20); + __gen_e_acsl_valid_2 = __e_acsl_valid((void *)Mwmin,sizeof(float), + (void *)Mwmin,(void *)(& Mwmin)); + __e_acsl_assert(__gen_e_acsl_valid_2,(char *)"Precondition", + (char *)"bar",(char *)"\\valid(Mwmin)",21); + __gen_e_acsl_valid_3 = __e_acsl_valid((void *)Mtmin_out,sizeof(float), + (void *)Mtmin_out, + (void *)(& Mtmin_out)); + __e_acsl_assert(__gen_e_acsl_valid_3,(char *)"Precondition", + (char *)"bar",(char *)"\\valid(Mtmin_out)",22); + } + bar(Mtmin_in,Mwmin,Mtmin_out); + { + int __gen_e_acsl_valid_read; + int __gen_e_acsl_valid_read_2; + int __gen_e_acsl_and; + int __gen_e_acsl_if; + __gen_e_acsl_valid_read = __e_acsl_valid_read((void *)__gen_e_acsl_at_2, + sizeof(float), + (void *)__gen_e_acsl_at_2, + (void *)(& __gen_e_acsl_at_2)); + __e_acsl_assert(__gen_e_acsl_valid_read,(char *)"RTE",(char *)"bar", + (char *)"mem_access: \\valid_read(__gen_e_acsl_at_2)",26); + __gen_e_acsl_valid_read_2 = __e_acsl_valid_read((void *)__gen_e_acsl_at, + sizeof(float), + (void *)__gen_e_acsl_at, + (void *)(& __gen_e_acsl_at)); + __e_acsl_assert(__gen_e_acsl_valid_read_2,(char *)"RTE",(char *)"bar", + (char *)"mem_access: \\valid_read(__gen_e_acsl_at)",26); + if (*__gen_e_acsl_at == *__gen_e_acsl_at_2) { + __e_acsl_mpq_t __gen_e_acsl_; + __e_acsl_mpq_t __gen_e_acsl__2; + __e_acsl_mpq_t __gen_e_acsl_mul; + __e_acsl_mpq_t __gen_e_acsl__3; + int __gen_e_acsl_lt; + __gmpq_init(__gen_e_acsl_); + __gmpq_set_str(__gen_e_acsl_,"085/100",10); + __gmpq_init(__gen_e_acsl__2); + __gmpq_set_d(__gen_e_acsl__2,(double)*__gen_e_acsl_at_4); + __gmpq_init(__gen_e_acsl_mul); + __gmpq_mul(__gen_e_acsl_mul, + (__e_acsl_mpq_struct const *)(__gen_e_acsl_), + (__e_acsl_mpq_struct const *)(__gen_e_acsl__2)); + __gmpq_init(__gen_e_acsl__3); + __gmpq_set_d(__gen_e_acsl__3,(double)*__gen_e_acsl_at_3); + __gen_e_acsl_lt = __gmpq_cmp((__e_acsl_mpq_struct const *)(__gen_e_acsl__3), + (__e_acsl_mpq_struct const *)(__gen_e_acsl_mul)); + __gen_e_acsl_and = __gen_e_acsl_lt < 0; + __gmpq_clear(__gen_e_acsl_); + __gmpq_clear(__gen_e_acsl__2); + __gmpq_clear(__gen_e_acsl_mul); + __gmpq_clear(__gen_e_acsl__3); + } + else __gen_e_acsl_and = 0; + if (__gen_e_acsl_and) { + int __gen_e_acsl_valid_read_3; + __gen_e_acsl_valid_read_3 = __e_acsl_valid_read((void *)__gen_e_acsl_at_5, + sizeof(float), + (void *)__gen_e_acsl_at_5, + (void *)(& __gen_e_acsl_at_5)); + __e_acsl_assert(__gen_e_acsl_valid_read_3,(char *)"RTE",(char *)"bar", + (char *)"mem_access: \\valid_read(__gen_e_acsl_at_5)", + 26); + __gen_e_acsl_if = (double)*__gen_e_acsl_at_5 != 0.; + } + else { + __e_acsl_mpq_t __gen_e_acsl__4; + __e_acsl_mpq_t __gen_e_acsl__5; + __e_acsl_mpq_t __gen_e_acsl_mul_2; + __e_acsl_mpq_t __gen_e_acsl__6; + int __gen_e_acsl_ne; + __gmpq_init(__gen_e_acsl__4); + __gmpq_set_str(__gen_e_acsl__4,"085/100",10); + __gmpq_init(__gen_e_acsl__5); + __gmpq_set_d(__gen_e_acsl__5,(double)*__gen_e_acsl_at_6); + __gmpq_init(__gen_e_acsl_mul_2); + __gmpq_mul(__gen_e_acsl_mul_2, + (__e_acsl_mpq_struct const *)(__gen_e_acsl__4), + (__e_acsl_mpq_struct const *)(__gen_e_acsl__5)); + __gmpq_init(__gen_e_acsl__6); + __gmpq_set_d(__gen_e_acsl__6,0.); + __gen_e_acsl_ne = __gmpq_cmp((__e_acsl_mpq_struct const *)(__gen_e_acsl_mul_2), + (__e_acsl_mpq_struct const *)(__gen_e_acsl__6)); + __gen_e_acsl_if = __gen_e_acsl_ne != 0; + __gmpq_clear(__gen_e_acsl__4); + __gmpq_clear(__gen_e_acsl__5); + __gmpq_clear(__gen_e_acsl_mul_2); + __gmpq_clear(__gen_e_acsl__6); + } + __e_acsl_assert(__gen_e_acsl_if,(char *)"Postcondition",(char *)"bar", + (char *)"*\\old(Mtmin_out) == *\\old(Mtmin_in) < 0.85 * *\\old(Mwmin)?\n *\\old(Mtmin_in) != 0.:\n 0.85 * *\\old(Mwmin) != 0.", + 26); + __e_acsl_delete_block((void *)(& Mtmin_out)); + __e_acsl_delete_block((void *)(& Mwmin)); + __e_acsl_delete_block((void *)(& Mtmin_in)); + return; + } +} + +/*@ requires \valid(Mtmax_in); + requires \valid(Mwmax); + requires \valid(Mtmax_out); + + behavior OverEstimate_Motoring: + assumes \true; + ensures + *\old(Mtmax_out) ≢ + *\old(Mtmax_in) + (5 - ((5 / 80) * *\old(Mwmax)) * 0.4); + */ +void __gen_e_acsl_foo(float *Mtmax_in, float *Mwmax, float *Mtmax_out) +{ + float *__gen_e_acsl_at_3; + float *__gen_e_acsl_at_2; + float *__gen_e_acsl_at; + __gen_e_acsl_at_3 = Mwmax; + __gen_e_acsl_at_2 = Mtmax_in; + __gen_e_acsl_at = Mtmax_out; + { + int __gen_e_acsl_valid; + int __gen_e_acsl_valid_2; + int __gen_e_acsl_valid_3; + __e_acsl_store_block((void *)(& Mtmax_out),(size_t)8); + __e_acsl_store_block((void *)(& Mwmax),(size_t)8); + __e_acsl_store_block((void *)(& Mtmax_in),(size_t)8); + __gen_e_acsl_valid = __e_acsl_valid((void *)Mtmax_in,sizeof(float), + (void *)Mtmax_in, + (void *)(& Mtmax_in)); + __e_acsl_assert(__gen_e_acsl_valid,(char *)"Precondition",(char *)"foo", + (char *)"\\valid(Mtmax_in)",5); + __gen_e_acsl_valid_2 = __e_acsl_valid((void *)Mwmax,sizeof(float), + (void *)Mwmax,(void *)(& Mwmax)); + __e_acsl_assert(__gen_e_acsl_valid_2,(char *)"Precondition", + (char *)"foo",(char *)"\\valid(Mwmax)",6); + __gen_e_acsl_valid_3 = __e_acsl_valid((void *)Mtmax_out,sizeof(float), + (void *)Mtmax_out, + (void *)(& Mtmax_out)); + __e_acsl_assert(__gen_e_acsl_valid_3,(char *)"Precondition", + (char *)"foo",(char *)"\\valid(Mtmax_out)",7); + } + foo(Mtmax_in,Mwmax,Mtmax_out); + { + __e_acsl_mpq_t __gen_e_acsl_; + __e_acsl_mpq_t __gen_e_acsl__2; + __e_acsl_mpq_t __gen_e_acsl__3; + __e_acsl_mpq_t __gen_e_acsl_div; + __e_acsl_mpq_t __gen_e_acsl__4; + __e_acsl_mpq_t __gen_e_acsl_mul; + __e_acsl_mpq_t __gen_e_acsl__5; + __e_acsl_mpq_t __gen_e_acsl_mul_2; + __e_acsl_mpq_t __gen_e_acsl_sub; + __e_acsl_mpq_t __gen_e_acsl__6; + __e_acsl_mpq_t __gen_e_acsl_add; + __e_acsl_mpq_t __gen_e_acsl__7; + int __gen_e_acsl_ne; + __gmpq_init(__gen_e_acsl_); + __gmpq_set_str(__gen_e_acsl_,"5",10); + __gmpq_init(__gen_e_acsl__2); + __gmpq_set_si(__gen_e_acsl__2,5L); + __gmpq_init(__gen_e_acsl__3); + __gmpq_set_si(__gen_e_acsl__3,80L); + __gmpq_init(__gen_e_acsl_div); + __gmpq_div(__gen_e_acsl_div, + (__e_acsl_mpq_struct const *)(__gen_e_acsl__2), + (__e_acsl_mpq_struct const *)(__gen_e_acsl__3)); + __gmpq_init(__gen_e_acsl__4); + __gmpq_set_d(__gen_e_acsl__4,(double)*__gen_e_acsl_at_3); + __gmpq_init(__gen_e_acsl_mul); + __gmpq_mul(__gen_e_acsl_mul, + (__e_acsl_mpq_struct const *)(__gen_e_acsl_div), + (__e_acsl_mpq_struct const *)(__gen_e_acsl__4)); + __gmpq_init(__gen_e_acsl__5); + __gmpq_set_str(__gen_e_acsl__5,"04/10",10); + __gmpq_init(__gen_e_acsl_mul_2); + __gmpq_mul(__gen_e_acsl_mul_2, + (__e_acsl_mpq_struct const *)(__gen_e_acsl_mul), + (__e_acsl_mpq_struct const *)(__gen_e_acsl__5)); + __gmpq_init(__gen_e_acsl_sub); + __gmpq_sub(__gen_e_acsl_sub,(__e_acsl_mpq_struct const *)(__gen_e_acsl_), + (__e_acsl_mpq_struct const *)(__gen_e_acsl_mul_2)); + __gmpq_init(__gen_e_acsl__6); + __gmpq_set_d(__gen_e_acsl__6,(double)*__gen_e_acsl_at_2); + __gmpq_init(__gen_e_acsl_add); + __gmpq_add(__gen_e_acsl_add, + (__e_acsl_mpq_struct const *)(__gen_e_acsl__6), + (__e_acsl_mpq_struct const *)(__gen_e_acsl_sub)); + __gmpq_init(__gen_e_acsl__7); + __gmpq_set_d(__gen_e_acsl__7,(double)*__gen_e_acsl_at); + __gen_e_acsl_ne = __gmpq_cmp((__e_acsl_mpq_struct const *)(__gen_e_acsl__7), + (__e_acsl_mpq_struct const *)(__gen_e_acsl_add)); + __e_acsl_assert(__gen_e_acsl_ne != 0,(char *)"Postcondition", + (char *)"foo", + (char *)"*\\old(Mtmax_out) != *\\old(Mtmax_in) + (5 - ((5 / 80) * *\\old(Mwmax)) * 0.4)", + 11); + __e_acsl_delete_block((void *)(& Mtmax_out)); + __e_acsl_delete_block((void *)(& Mwmax)); + __e_acsl_delete_block((void *)(& Mtmax_in)); + __gmpq_clear(__gen_e_acsl_); + __gmpq_clear(__gen_e_acsl__2); + __gmpq_clear(__gen_e_acsl__3); + __gmpq_clear(__gen_e_acsl_div); + __gmpq_clear(__gen_e_acsl__4); + __gmpq_clear(__gen_e_acsl_mul); + __gmpq_clear(__gen_e_acsl__5); + __gmpq_clear(__gen_e_acsl_mul_2); + __gmpq_clear(__gen_e_acsl_sub); + __gmpq_clear(__gen_e_acsl__6); + __gmpq_clear(__gen_e_acsl_add); + __gmpq_clear(__gen_e_acsl__7); + return; + } +} + + diff --git a/src/plugins/e-acsl/tests/bts/oracle_ci/gen_bts1324.c b/src/plugins/e-acsl/tests/bts/oracle_ci/gen_bts1324.c new file mode 100644 index 0000000000000000000000000000000000000000..93ebe565d4808e16c97d05865ab5f6602818b39c --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/oracle_ci/gen_bts1324.c @@ -0,0 +1,109 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +extern int __e_acsl_sound_verdict; + +/*@ behavior yes: + assumes ∀ int i; 0 < i < n ⇒ *(t + (i - 1)) ≤ *(t + i); + ensures \result ≡ 1; + */ +int __gen_e_acsl_sorted(int *t, int n); + +int sorted(int *t, int n) +{ + int __retres; + int b = 1; + if (n <= 1) { + __retres = 1; + goto return_label; + } + b = 1; + while (b < n) { + if (*(t + (b - 1)) > *(t + b)) { + __retres = 0; + goto return_label; + } + b ++; + } + __retres = 1; + return_label: return __retres; +} + +int main(void) +{ + int __retres; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + int t[7] = {1, 4, 4, 5, 5, 5, 7}; + __e_acsl_store_block((void *)(t),(size_t)28); + __e_acsl_full_init((void *)(& t)); + int n = __gen_e_acsl_sorted(t,7); + /*@ assert n ≡ 1; */ + __e_acsl_assert(n == 1,(char *)"Assertion",(char *)"main",(char *)"n == 1", + 23); + __retres = 0; + __e_acsl_delete_block((void *)(t)); + __e_acsl_memory_clean(); + return __retres; +} + +/*@ behavior yes: + assumes ∀ int i; 0 < i < n ⇒ *(t + (i - 1)) ≤ *(t + i); + ensures \result ≡ 1; + */ +int __gen_e_acsl_sorted(int *t, int n) +{ + int __gen_e_acsl_at; + int __retres; + { + int __gen_e_acsl_forall; + int __gen_e_acsl_i; + __gen_e_acsl_forall = 1; + __gen_e_acsl_i = 0 + 1; + while (1) { + if (__gen_e_acsl_i < n) ; else break; + { + int __gen_e_acsl_valid_read; + int __gen_e_acsl_valid_read_2; + __gen_e_acsl_valid_read = __e_acsl_valid_read((void *)(t + __gen_e_acsl_i), + sizeof(int),(void *)t, + (void *)(& t)); + __e_acsl_assert(__gen_e_acsl_valid_read,(char *)"RTE", + (char *)"sorted", + (char *)"mem_access: \\valid_read(t + __gen_e_acsl_i)", + 6); + __gen_e_acsl_valid_read_2 = __e_acsl_valid_read((void *)(t + ( + __gen_e_acsl_i - 1L)), + sizeof(int), + (void *)t, + (void *)(& t)); + __e_acsl_assert(__gen_e_acsl_valid_read_2,(char *)"RTE", + (char *)"sorted", + (char *)"mem_access: \\valid_read(t + (long)(__gen_e_acsl_i - 1))", + 6); + if (*(t + (__gen_e_acsl_i - 1L)) <= *(t + __gen_e_acsl_i)) ; + else { + __gen_e_acsl_forall = 0; + goto e_acsl_end_loop1; + } + } + __gen_e_acsl_i ++; + } + e_acsl_end_loop1: ; + __gen_e_acsl_at = __gen_e_acsl_forall; + } + __e_acsl_store_block((void *)(& t),(size_t)8); + __retres = sorted(t,n); + { + int __gen_e_acsl_implies; + if (! __gen_e_acsl_at) __gen_e_acsl_implies = 1; + else __gen_e_acsl_implies = __retres == 1; + __e_acsl_assert(__gen_e_acsl_implies,(char *)"Postcondition", + (char *)"sorted", + (char *)"\\old(\\forall int i; 0 < i < n ==> *(t + (i - 1)) <= *(t + i)) ==>\n\\result == 1", + 7); + __e_acsl_delete_block((void *)(& t)); + return __retres; + } +} + + diff --git a/src/plugins/e-acsl/tests/bts/oracle_ci/gen_bts1326.c b/src/plugins/e-acsl/tests/bts/oracle_ci/gen_bts1326.c new file mode 100644 index 0000000000000000000000000000000000000000..febd8a6efa7f9936c01e7a7cb848a06549f93376 --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/oracle_ci/gen_bts1326.c @@ -0,0 +1,135 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +extern int __e_acsl_sound_verdict; + +typedef int ArrayInt[5]; +/*@ ensures + *\old(AverageAccel) ≡ + (((((*\old(Accel))[4] + (*\old(Accel))[3]) + (*\old(Accel))[2]) + + (*\old(Accel))[1]) + + (*\old(Accel))[0]) + / 5; + */ +void __gen_e_acsl_atp_NORMAL_computeAverageAccel(ArrayInt *Accel, + int *AverageAccel); + +void atp_NORMAL_computeAverageAccel(ArrayInt *Accel, int *AverageAccel) +{ + __e_acsl_store_block((void *)(& AverageAccel),(size_t)8); + __e_acsl_store_block((void *)(& Accel),(size_t)8); + __e_acsl_initialize((void *)AverageAccel,sizeof(int)); + *AverageAccel = (((((*Accel)[4] + (*Accel)[3]) + (*Accel)[2]) + (*Accel)[1]) + (*Accel)[0]) / 5; + __e_acsl_delete_block((void *)(& AverageAccel)); + __e_acsl_delete_block((void *)(& Accel)); + return; +} + +int main(void) +{ + int __retres; + int av; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + __e_acsl_store_block((void *)(& av),(size_t)4); + ArrayInt Accel = {1, 2, 3, 4, 5}; + __e_acsl_store_block((void *)(Accel),(size_t)20); + __e_acsl_full_init((void *)(& Accel)); + __gen_e_acsl_atp_NORMAL_computeAverageAccel(& Accel,& av); + __retres = 0; + __e_acsl_delete_block((void *)(& av)); + __e_acsl_delete_block((void *)(Accel)); + __e_acsl_memory_clean(); + return __retres; +} + +/*@ ensures + *\old(AverageAccel) ≡ + (((((*\old(Accel))[4] + (*\old(Accel))[3]) + (*\old(Accel))[2]) + + (*\old(Accel))[1]) + + (*\old(Accel))[0]) + / 5; + */ +void __gen_e_acsl_atp_NORMAL_computeAverageAccel(ArrayInt *Accel, + int *AverageAccel) +{ + ArrayInt *__gen_e_acsl_at_6; + ArrayInt *__gen_e_acsl_at_5; + ArrayInt *__gen_e_acsl_at_4; + ArrayInt *__gen_e_acsl_at_3; + ArrayInt *__gen_e_acsl_at_2; + int *__gen_e_acsl_at; + __gen_e_acsl_at_6 = Accel; + __gen_e_acsl_at_5 = Accel; + __gen_e_acsl_at_4 = Accel; + __gen_e_acsl_at_3 = Accel; + __gen_e_acsl_at_2 = Accel; + __gen_e_acsl_at = AverageAccel; + __e_acsl_store_block((void *)(& AverageAccel),(size_t)8); + __e_acsl_store_block((void *)(& Accel),(size_t)8); + atp_NORMAL_computeAverageAccel(Accel,AverageAccel); + { + int __gen_e_acsl_valid_read; + int __gen_e_acsl_valid_read_2; + int __gen_e_acsl_valid_read_3; + int __gen_e_acsl_valid_read_4; + int __gen_e_acsl_valid_read_5; + int __gen_e_acsl_valid_read_6; + __gen_e_acsl_valid_read = __e_acsl_valid_read((void *)(*__gen_e_acsl_at_6), + sizeof(int), + (void *)(*__gen_e_acsl_at_6), + (void *)(*__gen_e_acsl_at_6)); + __e_acsl_assert(__gen_e_acsl_valid_read,(char *)"RTE", + (char *)"atp_NORMAL_computeAverageAccel", + (char *)"mem_access: \\valid_read((int *)*__gen_e_acsl_at_6)", + 8); + __gen_e_acsl_valid_read_2 = __e_acsl_valid_read((void *)(& (*__gen_e_acsl_at_5)[1]), + sizeof(int), + (void *)(& (*__gen_e_acsl_at_5)[1]), + (void *)0); + __e_acsl_assert(__gen_e_acsl_valid_read_2,(char *)"RTE", + (char *)"atp_NORMAL_computeAverageAccel", + (char *)"mem_access: \\valid_read(&(*__gen_e_acsl_at_5)[1])", + 8); + __gen_e_acsl_valid_read_3 = __e_acsl_valid_read((void *)(& (*__gen_e_acsl_at_4)[2]), + sizeof(int), + (void *)(& (*__gen_e_acsl_at_4)[2]), + (void *)0); + __e_acsl_assert(__gen_e_acsl_valid_read_3,(char *)"RTE", + (char *)"atp_NORMAL_computeAverageAccel", + (char *)"mem_access: \\valid_read(&(*__gen_e_acsl_at_4)[2])", + 8); + __gen_e_acsl_valid_read_4 = __e_acsl_valid_read((void *)(& (*__gen_e_acsl_at_3)[3]), + sizeof(int), + (void *)(& (*__gen_e_acsl_at_3)[3]), + (void *)0); + __e_acsl_assert(__gen_e_acsl_valid_read_4,(char *)"RTE", + (char *)"atp_NORMAL_computeAverageAccel", + (char *)"mem_access: \\valid_read(&(*__gen_e_acsl_at_3)[3])", + 8); + __gen_e_acsl_valid_read_5 = __e_acsl_valid_read((void *)(& (*__gen_e_acsl_at_2)[4]), + sizeof(int), + (void *)(& (*__gen_e_acsl_at_2)[4]), + (void *)0); + __e_acsl_assert(__gen_e_acsl_valid_read_5,(char *)"RTE", + (char *)"atp_NORMAL_computeAverageAccel", + (char *)"mem_access: \\valid_read(&(*__gen_e_acsl_at_2)[4])", + 8); + __gen_e_acsl_valid_read_6 = __e_acsl_valid_read((void *)__gen_e_acsl_at, + sizeof(int), + (void *)__gen_e_acsl_at, + (void *)(& __gen_e_acsl_at)); + __e_acsl_assert(__gen_e_acsl_valid_read_6,(char *)"RTE", + (char *)"atp_NORMAL_computeAverageAccel", + (char *)"mem_access: \\valid_read(__gen_e_acsl_at)",8); + __e_acsl_assert(*__gen_e_acsl_at == (int)((((((*__gen_e_acsl_at_2)[4] + (long)(*__gen_e_acsl_at_3)[3]) + (*__gen_e_acsl_at_4)[2]) + (*__gen_e_acsl_at_5)[1]) + (*__gen_e_acsl_at_6)[0]) / 5L), + (char *)"Postcondition", + (char *)"atp_NORMAL_computeAverageAccel", + (char *)"*\\old(AverageAccel) ==\n(((((*\\old(Accel))[4] + (*\\old(Accel))[3]) + (*\\old(Accel))[2]) +\n (*\\old(Accel))[1])\n + (*\\old(Accel))[0])\n/ 5", + 8); + __e_acsl_delete_block((void *)(& AverageAccel)); + __e_acsl_delete_block((void *)(& Accel)); + return; + } +} + + diff --git a/src/plugins/e-acsl/tests/bts/oracle_ci/gen_bts1390.c b/src/plugins/e-acsl/tests/bts/oracle_ci/gen_bts1390.c new file mode 100644 index 0000000000000000000000000000000000000000..b45368fa2b43c132c377695f7ad6e9863033acb9 --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/oracle_ci/gen_bts1390.c @@ -0,0 +1,221 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +char *__gen_e_acsl_literal_string; +char *__gen_e_acsl_literal_string_2; +extern int __e_acsl_sound_verdict; + +/*@ behavior exists: + assumes ∃ ℤ i; 0 ≤ i < (int)n ∧ (int)*((char *)buf + i) ≡ c; + ensures + ∀ int j; + 0 ≤ j < (int)\offset((char *)\result) ⇒ + (int)*((char *)\old(buf) + j) ≢ \old(c); + + behavior not_exists: + assumes ∀ ℤ k; 0 ≤ k < (int)n ⇒ (int)*((char *)buf + k) ≢ c; + ensures \result ≡ (void *)0; + */ +void *__gen_e_acsl_memchr(void const *buf, int c, size_t n); + +void *memchr(void const *buf, int c, size_t n) +{ + void *__retres; + int i; + __e_acsl_store_block((void *)(& __retres),(size_t)8); + __e_acsl_store_block((void *)(& buf),(size_t)8); + char *s = (char *)buf; + __e_acsl_store_block((void *)(& s),(size_t)8); + __e_acsl_full_init((void *)(& s)); + i = 0; + while ((size_t)i < n) { + /*@ assert Eva: mem_access: \valid_read(s); */ + if ((int)*s == c) { + __e_acsl_full_init((void *)(& __retres)); + __retres = (void *)s; + goto return_label; + } + __e_acsl_full_init((void *)(& s)); + s ++; + i ++; + } + __e_acsl_full_init((void *)(& __retres)); + __retres = (void *)0; + return_label: + { + __e_acsl_delete_block((void *)(& buf)); + __e_acsl_delete_block((void *)(& s)); + __e_acsl_delete_block((void *)(& __retres)); + return __retres; + } +} + +/*@ behavior exists: + assumes ∃ ℤ i; 0 ≤ i < (int)n ∧ (int)*((char *)buf + i) ≡ c; + ensures + ∀ int j; + 0 ≤ j < (int)\offset((char *)\result) ⇒ + (int)*((char *)\old(buf) + j) ≢ \old(c); + + behavior not_exists: + assumes ∀ ℤ k; 0 ≤ k < (int)n ⇒ (int)*((char *)buf + k) ≢ c; + ensures \result ≡ (void *)0; + */ +void *__gen_e_acsl_memchr(void const *buf, int c, size_t n) +{ + int __gen_e_acsl_at_4; + int __gen_e_acsl_at_3; + void const *__gen_e_acsl_at_2; + int __gen_e_acsl_at; + void *__retres; + __e_acsl_store_block((void *)(& __retres),(size_t)8); + { + int __gen_e_acsl_forall_2; + unsigned int __gen_e_acsl_k; + __gen_e_acsl_forall_2 = 1; + __gen_e_acsl_k = 0U; + while (1) { + if (__gen_e_acsl_k < (unsigned int)((int)((unsigned int)n))) ; + else break; + { + int __gen_e_acsl_valid_read_3; + __gen_e_acsl_valid_read_3 = __e_acsl_valid_read((void *)((char *)buf + __gen_e_acsl_k), + sizeof(char), + (void *)buf, + (void *)(& buf)); + __e_acsl_assert(__gen_e_acsl_valid_read_3,(char *)"RTE", + (char *)"memchr", + (char *)"mem_access: \\valid_read((char *)buf + __gen_e_acsl_k)", + 11); + if ((int)*((char *)buf + __gen_e_acsl_k) != c) ; + else { + __gen_e_acsl_forall_2 = 0; + goto e_acsl_end_loop3; + } + } + __gen_e_acsl_k ++; + } + e_acsl_end_loop3: ; + __gen_e_acsl_at_4 = __gen_e_acsl_forall_2; + } + __gen_e_acsl_at_3 = c; + __gen_e_acsl_at_2 = buf; + { + int __gen_e_acsl_exists; + unsigned int __gen_e_acsl_i; + __gen_e_acsl_exists = 0; + __gen_e_acsl_i = 0U; + while (1) { + if (__gen_e_acsl_i < (unsigned int)((int)((unsigned int)n))) ; + else break; + { + int __gen_e_acsl_valid_read; + __gen_e_acsl_valid_read = __e_acsl_valid_read((void *)((char *)buf + __gen_e_acsl_i), + sizeof(char), + (void *)buf, + (void *)(& buf)); + __e_acsl_assert(__gen_e_acsl_valid_read,(char *)"RTE", + (char *)"memchr", + (char *)"mem_access: \\valid_read((char *)buf + __gen_e_acsl_i)", + 8); + if (! ((int)*((char *)buf + __gen_e_acsl_i) == c)) ; + else { + __gen_e_acsl_exists = 1; + goto e_acsl_end_loop1; + } + } + __gen_e_acsl_i ++; + } + e_acsl_end_loop1: ; + __gen_e_acsl_at = __gen_e_acsl_exists; + } + __e_acsl_store_block((void *)(& buf),(size_t)8); + __retres = memchr(buf,c,n); + { + int __gen_e_acsl_implies; + int __gen_e_acsl_implies_2; + if (! __gen_e_acsl_at) __gen_e_acsl_implies = 1; + else { + int __gen_e_acsl_forall; + unsigned int __gen_e_acsl_j; + __gen_e_acsl_forall = 1; + __gen_e_acsl_j = 0; + while (1) { + { + unsigned long __gen_e_acsl_offset; + __gen_e_acsl_offset = __e_acsl_offset(__retres); + if (__gen_e_acsl_j < (unsigned int)((int)((unsigned int)__gen_e_acsl_offset))) + ; + else break; + } + { + int __gen_e_acsl_valid_read_2; + __gen_e_acsl_valid_read_2 = __e_acsl_valid_read((void *)((char *)__gen_e_acsl_at_2 + __gen_e_acsl_j), + sizeof(char), + (void *)__gen_e_acsl_at_2, + (void *)(& __gen_e_acsl_at_2)); + __e_acsl_assert(__gen_e_acsl_valid_read_2,(char *)"RTE", + (char *)"memchr", + (char *)"mem_access: \\valid_read((char *)__gen_e_acsl_at_2 + __gen_e_acsl_j)", + 9); + if ((int)*((char *)__gen_e_acsl_at_2 + __gen_e_acsl_j) != __gen_e_acsl_at_3) + ; + else { + __gen_e_acsl_forall = 0; + goto e_acsl_end_loop2; + } + } + __gen_e_acsl_j ++; + } + e_acsl_end_loop2: ; + __gen_e_acsl_implies = __gen_e_acsl_forall; + } + __e_acsl_assert(__gen_e_acsl_implies,(char *)"Postcondition", + (char *)"memchr", + (char *)"\\old(\\exists integer i; 0 <= i < (int)n && (int)*((char *)buf + i) == c) ==>\n(\\forall int j;\n 0 <= j < (int)\\offset((char *)\\result) ==>\n (int)*((char *)\\old(buf) + j) != \\old(c))", + 9); + if (! __gen_e_acsl_at_4) __gen_e_acsl_implies_2 = 1; + else __gen_e_acsl_implies_2 = __retres == (void *)0; + __e_acsl_assert(__gen_e_acsl_implies_2,(char *)"Postcondition", + (char *)"memchr", + (char *)"\\old(\\forall integer k; 0 <= k < (int)n ==> (int)*((char *)buf + k) != c) ==>\n\\result == (void *)0", + 12); + __e_acsl_delete_block((void *)(& buf)); + __e_acsl_delete_block((void *)(& __retres)); + return __retres; + } +} + +void __e_acsl_globals_init(void) +{ + static char __e_acsl_already_run = 0; + if (! __e_acsl_already_run) { + __e_acsl_already_run = 1; + __gen_e_acsl_literal_string = "toto"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string,sizeof("toto")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string); + __gen_e_acsl_literal_string_2 = "tata"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_2, + sizeof("tata")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_2); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_2); + } + return; +} + +int main(void) +{ + int __retres; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + __e_acsl_globals_init(); + __gen_e_acsl_memchr((void const *)__gen_e_acsl_literal_string,'o', + (unsigned long)4); + __gen_e_acsl_memchr((void const *)__gen_e_acsl_literal_string_2,'o', + (unsigned long)4); + __retres = 0; + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/bts/oracle_ci/gen_bts1395.c b/src/plugins/e-acsl/tests/bts/oracle_ci/gen_bts1395.c new file mode 100644 index 0000000000000000000000000000000000000000..92921f36f74d174f417fe8a57b54c3ef9c871e96 --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/oracle_ci/gen_bts1395.c @@ -0,0 +1,47 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +extern int __e_acsl_sound_verdict; + +/*@ requires n > 0; */ +int __gen_e_acsl_fact(int n); + +int fact(int n) +{ + int __retres; + int tmp; + if (n == 1) { + __retres = 1; + goto return_label; + } + tmp = __gen_e_acsl_fact(n - 1); + ; + /*@ assert Eva: signed_overflow: -2147483648 ≤ n * tmp; */ + /*@ assert Eva: signed_overflow: n * tmp ≤ 2147483647; */ + __retres = n * tmp; + return_label: return __retres; +} + +int main(void) +{ + int __retres; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + int x = __gen_e_acsl_fact(5); + /*@ assert x ≡ 120; */ + __e_acsl_assert(x == 120,(char *)"Assertion",(char *)"main", + (char *)"x == 120",14); + __retres = 0; + return __retres; +} + +/*@ requires n > 0; */ +int __gen_e_acsl_fact(int n) +{ + int __retres; + __e_acsl_assert(n > 0,(char *)"Precondition",(char *)"fact", + (char *)"n > 0",6); + __retres = fact(n); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/bts/oracle_ci/gen_bts1398.c b/src/plugins/e-acsl/tests/bts/oracle_ci/gen_bts1398.c new file mode 100644 index 0000000000000000000000000000000000000000..6c992808644dc2b1a22a287bec261511fb770b8d --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/oracle_ci/gen_bts1398.c @@ -0,0 +1,35 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +char *__gen_e_acsl_literal_string; +void __e_acsl_globals_init(void) +{ + static char __e_acsl_already_run = 0; + if (! __e_acsl_already_run) { + __e_acsl_already_run = 1; + __gen_e_acsl_literal_string = "X=%d, t[0]=%d, t[1]=%d\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string, + sizeof("X=%d, t[0]=%d, t[1]=%d\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string); + } + return; +} + +int main(void) +{ + int __retres; + int t[2]; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + __e_acsl_globals_init(); + int x = 0; + int i = 1; + t[0] = 1; + t[1] = 2; + printf(__gen_e_acsl_literal_string,x,t[0],t[i]); + __retres = 0; + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/bts/oracle_ci/gen_bts1399.c b/src/plugins/e-acsl/tests/bts/oracle_ci/gen_bts1399.c new file mode 100644 index 0000000000000000000000000000000000000000..5b3967bd61db34e55b98d852c81c70181dbaee16 --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/oracle_ci/gen_bts1399.c @@ -0,0 +1,46 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +struct spongeStateStruct { + unsigned char __attribute__((__aligned__(32))) state[1600 / 8] ; + unsigned char __attribute__((__aligned__(32))) dataQueue[1536 / 8] ; + unsigned int bitsInQueue ; +} __attribute__((__aligned__(32))); +typedef struct spongeStateStruct spongeState; +int main(void) +{ + int __retres; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + spongeState *state = malloc(sizeof(spongeState)); + __e_acsl_store_block((void *)(& state),(size_t)8); + __e_acsl_full_init((void *)(& state)); + __e_acsl_initialize((void *)(& state->bitsInQueue),sizeof(unsigned int)); + state->bitsInQueue = (unsigned int)16; + /*@ assert ¬\initialized(&state->dataQueue[state->bitsInQueue / 8]); */ + { + int __gen_e_acsl_valid_read; + int __gen_e_acsl_initialized; + __gen_e_acsl_valid_read = __e_acsl_valid_read((void *)(& state->bitsInQueue), + sizeof(unsigned int), + (void *)(& state->bitsInQueue), + (void *)0); + __e_acsl_assert(__gen_e_acsl_valid_read,(char *)"RTE",(char *)"main", + (char *)"mem_access: \\valid_read(&state->bitsInQueue)", + 19); + __gen_e_acsl_initialized = __e_acsl_initialized((void *)(& state->dataQueue[ + state->bitsInQueue / 8U]), + sizeof(unsigned char __attribute__(( + __aligned__(32))))); + __e_acsl_assert(! __gen_e_acsl_initialized,(char *)"Assertion", + (char *)"main", + (char *)"!\\initialized(&state->dataQueue[state->bitsInQueue / 8])", + 19); + } + free((void *)state); + __retres = 0; + __e_acsl_delete_block((void *)(& state)); + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/bts/oracle_ci/gen_bts1478.c b/src/plugins/e-acsl/tests/bts/oracle_ci/gen_bts1478.c new file mode 100644 index 0000000000000000000000000000000000000000..9d38eb9b4037c025976aab3b0debf34537910361 --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/oracle_ci/gen_bts1478.c @@ -0,0 +1,69 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +extern int __e_acsl_sound_verdict; + +int global_i; + +int *global_i_ptr = & global_i; +int global_i = 0; +/*@ requires global_i ≡ 0; + requires \valid(global_i_ptr); + requires global_i_ptr ≡ &global_i; + */ +void __gen_e_acsl_loop(void); + +void loop(void) +{ + return; +} + +/*@ requires global_i ≡ 0; + requires \valid(global_i_ptr); + requires global_i_ptr ≡ &global_i; + */ +void __gen_e_acsl_loop(void) +{ + { + int __gen_e_acsl_valid; + __e_acsl_assert(global_i == 0,(char *)"Precondition",(char *)"loop", + (char *)"global_i == 0",9); + __gen_e_acsl_valid = __e_acsl_valid((void *)global_i_ptr,sizeof(int), + (void *)global_i_ptr, + (void *)(& global_i_ptr)); + __e_acsl_assert(__gen_e_acsl_valid,(char *)"Precondition",(char *)"loop", + (char *)"\\valid(global_i_ptr)",10); + __e_acsl_assert(global_i_ptr == & global_i,(char *)"Precondition", + (char *)"loop",(char *)"global_i_ptr == &global_i",11); + } + loop(); + return; +} + +void __e_acsl_globals_init(void) +{ + static char __e_acsl_already_run = 0; + if (! __e_acsl_already_run) { + __e_acsl_already_run = 1; + __e_acsl_store_block((void *)(& global_i_ptr),(size_t)8); + __e_acsl_full_init((void *)(& global_i_ptr)); + __e_acsl_store_block((void *)(& global_i),(size_t)4); + __e_acsl_full_init((void *)(& global_i)); + } + return; +} + +int main(void) +{ + int __retres; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + __e_acsl_globals_init(); + __gen_e_acsl_loop(); + __retres = 0; + __e_acsl_delete_block((void *)(& global_i_ptr)); + __e_acsl_delete_block((void *)(& global_i)); + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/bts/oracle_ci/gen_bts1700.c b/src/plugins/e-acsl/tests/bts/oracle_ci/gen_bts1700.c new file mode 100644 index 0000000000000000000000000000000000000000..8aed6eb36504ecf8efc47968962a96ccf6f976f6 --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/oracle_ci/gen_bts1700.c @@ -0,0 +1,48 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +struct toto { + +}; +int main(void) +{ + int __retres; + struct toto s; + struct toto *p; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + __e_acsl_store_block((void *)(& p),(size_t)8); + __e_acsl_store_block((void *)(& s),(size_t)0); + /*@ assert \valid(&s); */ + { + int __gen_e_acsl_valid; + __gen_e_acsl_valid = __e_acsl_valid((void *)(& s),sizeof(struct toto), + (void *)(& s),(void *)0); + __e_acsl_assert(__gen_e_acsl_valid,(char *)"Assertion",(char *)"main", + (char *)"\\valid(&s)",9); + } + __e_acsl_full_init((void *)(& p)); + p = & s; + /*@ assert \valid(p); */ + { + int __gen_e_acsl_initialized; + int __gen_e_acsl_and; + __gen_e_acsl_initialized = __e_acsl_initialized((void *)(& p), + sizeof(struct toto *)); + if (__gen_e_acsl_initialized) { + int __gen_e_acsl_valid_2; + __gen_e_acsl_valid_2 = __e_acsl_valid((void *)p,sizeof(struct toto), + (void *)p,(void *)(& p)); + __gen_e_acsl_and = __gen_e_acsl_valid_2; + } + else __gen_e_acsl_and = 0; + __e_acsl_assert(__gen_e_acsl_and,(char *)"Assertion",(char *)"main", + (char *)"\\valid(p)",12); + } + __retres = 0; + __e_acsl_delete_block((void *)(& p)); + __e_acsl_delete_block((void *)(& s)); + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/bts/oracle_ci/gen_bts1717.c b/src/plugins/e-acsl/tests/bts/oracle_ci/gen_bts1717.c new file mode 100644 index 0000000000000000000000000000000000000000..98cad6513199bdb168fb729cb1fd4a44ba181d4e --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/oracle_ci/gen_bts1717.c @@ -0,0 +1,47 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +int main(void) +{ + int __retres; + int *p; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + __e_acsl_store_block((void *)(& p),(size_t)8); + int a = 10; + __e_acsl_store_block((void *)(& a),(size_t)4); + __e_acsl_full_init((void *)(& a)); + goto lbl_1; + lbl_2: + /*@ assert \valid(p); */ + { + int __gen_e_acsl_initialized; + int __gen_e_acsl_and; + __gen_e_acsl_initialized = __e_acsl_initialized((void *)(& p), + sizeof(int *)); + if (__gen_e_acsl_initialized) { + int __gen_e_acsl_valid; + __gen_e_acsl_valid = __e_acsl_valid((void *)p,sizeof(int),(void *)p, + (void *)(& p)); + __gen_e_acsl_and = __gen_e_acsl_valid; + } + else __gen_e_acsl_and = 0; + __e_acsl_assert(__gen_e_acsl_and,(char *)"Assertion",(char *)"main", + (char *)"\\valid(p)",10); + } + __retres = 0; + goto return_label; + lbl_1: { + __e_acsl_full_init((void *)(& p)); + p = & a; + } + goto lbl_2; + return_label: + { + __e_acsl_delete_block((void *)(& p)); + __e_acsl_delete_block((void *)(& a)); + __e_acsl_memory_clean(); + return __retres; + } +} + + diff --git a/src/plugins/e-acsl/tests/bts/oracle_ci/gen_bts1718.c b/src/plugins/e-acsl/tests/bts/oracle_ci/gen_bts1718.c new file mode 100644 index 0000000000000000000000000000000000000000..9390aede98cae4c5436ef701e426508af52292cb --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/oracle_ci/gen_bts1718.c @@ -0,0 +1,47 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +int main(void) +{ + int __retres; + int *p; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + __e_acsl_store_block((void *)(& p),(size_t)8); + int a = 10; + __e_acsl_store_block((void *)(& a),(size_t)4); + __e_acsl_full_init((void *)(& a)); + goto lbl_1; + lbl_2: + /*@ assert \valid(p); */ + { + int __gen_e_acsl_initialized; + int __gen_e_acsl_and; + __gen_e_acsl_initialized = __e_acsl_initialized((void *)(& p), + sizeof(int *)); + if (__gen_e_acsl_initialized) { + int __gen_e_acsl_valid; + __gen_e_acsl_valid = __e_acsl_valid((void *)p,sizeof(int),(void *)p, + (void *)(& p)); + __gen_e_acsl_and = __gen_e_acsl_valid; + } + else __gen_e_acsl_and = 0; + __e_acsl_assert(__gen_e_acsl_and,(char *)"Assertion",(char *)"main", + (char *)"\\valid(p)",13); + } + __retres = 0; + goto return_label; + lbl_1: { + __e_acsl_full_init((void *)(& p)); + p = & a; + } + goto lbl_2; + return_label: + { + __e_acsl_delete_block((void *)(& p)); + __e_acsl_delete_block((void *)(& a)); + __e_acsl_memory_clean(); + return __retres; + } +} + + diff --git a/src/plugins/e-acsl/tests/bts/oracle_ci/gen_bts1740.c b/src/plugins/e-acsl/tests/bts/oracle_ci/gen_bts1740.c new file mode 100644 index 0000000000000000000000000000000000000000..23ebc578dedc86a9777417aabf541e019bd10fea --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/oracle_ci/gen_bts1740.c @@ -0,0 +1,60 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +int main(void) +{ + int __retres; + int *p; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + __e_acsl_store_block((void *)(& p),(size_t)8); + { + int a = 0; + __e_acsl_store_block((void *)(& a),(size_t)4); + __e_acsl_full_init((void *)(& a)); + __e_acsl_full_init((void *)(& p)); + p = & a; + /*@ assert \valid(p); */ + { + int __gen_e_acsl_initialized; + int __gen_e_acsl_and; + __gen_e_acsl_initialized = __e_acsl_initialized((void *)(& p), + sizeof(int *)); + if (__gen_e_acsl_initialized) { + int __gen_e_acsl_valid; + __gen_e_acsl_valid = __e_acsl_valid((void *)p,sizeof(int),(void *)p, + (void *)(& p)); + __gen_e_acsl_and = __gen_e_acsl_valid; + } + else __gen_e_acsl_and = 0; + __e_acsl_assert(__gen_e_acsl_and,(char *)"Assertion",(char *)"main", + (char *)"\\valid(p)",11); + } + __e_acsl_delete_block((void *)(& a)); + goto L; + __e_acsl_delete_block((void *)(& a)); + } + L: + /*@ assert ¬\valid(p); */ + { + int __gen_e_acsl_initialized_2; + int __gen_e_acsl_and_2; + __gen_e_acsl_initialized_2 = __e_acsl_initialized((void *)(& p), + sizeof(int *)); + if (__gen_e_acsl_initialized_2) { + int __gen_e_acsl_valid_2; + /*@ assert Eva: dangling_pointer: ¬\dangling(&p); */ + __gen_e_acsl_valid_2 = __e_acsl_valid((void *)p,sizeof(int),(void *)p, + (void *)(& p)); + __gen_e_acsl_and_2 = __gen_e_acsl_valid_2; + } + else __gen_e_acsl_and_2 = 0; + __e_acsl_assert(! __gen_e_acsl_and_2,(char *)"Assertion",(char *)"main", + (char *)"!\\valid(p)",16); + } + __retres = 0; + __e_acsl_delete_block((void *)(& p)); + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/bts/oracle_ci/gen_bts1837.c b/src/plugins/e-acsl/tests/bts/oracle_ci/gen_bts1837.c new file mode 100644 index 0000000000000000000000000000000000000000..1a56d79b25787f30f4b7fb4e4fb9e1181e076e68 --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/oracle_ci/gen_bts1837.c @@ -0,0 +1,152 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +char *__gen_e_acsl_literal_string_3; +char *__gen_e_acsl_literal_string; +char *__gen_e_acsl_literal_string_2; +char *S = (char *)"foo"; +int f(void) +{ + int __retres; + char *s1 = (char *)__gen_e_acsl_literal_string; + __e_acsl_store_block((void *)(& s1),(size_t)8); + __e_acsl_full_init((void *)(& s1)); + char *s2 = (char *)__gen_e_acsl_literal_string_2; + __e_acsl_store_block((void *)(& s2),(size_t)8); + __e_acsl_full_init((void *)(& s2)); + /*@ assert \valid_read(S); */ + { + int __gen_e_acsl_valid_read; + __gen_e_acsl_valid_read = __e_acsl_valid_read((void *)S,sizeof(char), + (void *)S,(void *)(& S)); + __e_acsl_assert(__gen_e_acsl_valid_read,(char *)"Assertion",(char *)"f", + (char *)"\\valid_read(S)",10); + } + /*@ assert \valid_read(s1); */ + { + int __gen_e_acsl_initialized; + int __gen_e_acsl_and; + __gen_e_acsl_initialized = __e_acsl_initialized((void *)(& s1), + sizeof(char *)); + if (__gen_e_acsl_initialized) { + int __gen_e_acsl_valid_read_2; + __gen_e_acsl_valid_read_2 = __e_acsl_valid_read((void *)s1, + sizeof(char), + (void *)s1, + (void *)(& s1)); + __gen_e_acsl_and = __gen_e_acsl_valid_read_2; + } + else __gen_e_acsl_and = 0; + __e_acsl_assert(__gen_e_acsl_and,(char *)"Assertion",(char *)"f", + (char *)"\\valid_read(s1)",11); + } + /*@ assert \valid_read(s2); */ + { + int __gen_e_acsl_initialized_2; + int __gen_e_acsl_and_2; + __gen_e_acsl_initialized_2 = __e_acsl_initialized((void *)(& s2), + sizeof(char *)); + if (__gen_e_acsl_initialized_2) { + int __gen_e_acsl_valid_read_3; + __gen_e_acsl_valid_read_3 = __e_acsl_valid_read((void *)s2, + sizeof(char), + (void *)s2, + (void *)(& s2)); + __gen_e_acsl_and_2 = __gen_e_acsl_valid_read_3; + } + else __gen_e_acsl_and_2 = 0; + __e_acsl_assert(__gen_e_acsl_and_2,(char *)"Assertion",(char *)"f", + (char *)"\\valid_read(s2)",12); + } + __retres = 0; + __e_acsl_delete_block((void *)(& s2)); + __e_acsl_delete_block((void *)(& s1)); + return __retres; +} + +void __e_acsl_globals_init(void) +{ + static char __e_acsl_already_run = 0; + if (! __e_acsl_already_run) { + __e_acsl_already_run = 1; + __gen_e_acsl_literal_string_3 = "toto"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_3, + sizeof("toto")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_3); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_3); + __gen_e_acsl_literal_string = "foo"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string,sizeof("foo")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string); + __gen_e_acsl_literal_string_2 = "bar"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_2,sizeof("bar")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_2); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_2); + __e_acsl_store_block((void *)(& S),(size_t)8); + __e_acsl_full_init((void *)(& S)); + } + return; +} + +int main(void) +{ + int __retres; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + __e_acsl_globals_init(); + int i = 4; + while (1) { + int tmp; + tmp = i; + /*@ assert Eva: signed_overflow: -2147483648 ≤ i - 1; */ + i --; + ; + if (! tmp) break; + { + char *s = (char *)__gen_e_acsl_literal_string_3; + __e_acsl_store_block((void *)(& s),(size_t)8); + __e_acsl_full_init((void *)(& s)); + /*@ assert \valid_read(s); */ + { + int __gen_e_acsl_initialized; + int __gen_e_acsl_and; + __gen_e_acsl_initialized = __e_acsl_initialized((void *)(& s), + sizeof(char *)); + if (__gen_e_acsl_initialized) { + int __gen_e_acsl_valid_read; + __gen_e_acsl_valid_read = __e_acsl_valid_read((void *)s, + sizeof(char), + (void *)s, + (void *)(& s)); + __gen_e_acsl_and = __gen_e_acsl_valid_read; + } + else __gen_e_acsl_and = 0; + __e_acsl_assert(__gen_e_acsl_and,(char *)"Assertion",(char *)"main", + (char *)"\\valid_read(s)",20); + } + /*@ assert ¬\valid(s); */ + { + int __gen_e_acsl_initialized_2; + int __gen_e_acsl_and_2; + __gen_e_acsl_initialized_2 = __e_acsl_initialized((void *)(& s), + sizeof(char *)); + if (__gen_e_acsl_initialized_2) { + int __gen_e_acsl_valid; + __gen_e_acsl_valid = __e_acsl_valid((void *)s,sizeof(char), + (void *)s,(void *)(& s)); + __gen_e_acsl_and_2 = __gen_e_acsl_valid; + } + else __gen_e_acsl_and_2 = 0; + __e_acsl_assert(! __gen_e_acsl_and_2,(char *)"Assertion", + (char *)"main",(char *)"!\\valid(s)",21); + __e_acsl_delete_block((void *)(& s)); + } + } + } + f(); + __retres = 0; + __e_acsl_delete_block((void *)(& S)); + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/bts/oracle_ci/gen_bts2191.c b/src/plugins/e-acsl/tests/bts/oracle_ci/gen_bts2191.c new file mode 100644 index 0000000000000000000000000000000000000000..d2d7d6be70285a97eb013d2a289ccdd87e2df2aa --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/oracle_ci/gen_bts2191.c @@ -0,0 +1,63 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +char *__gen_e_acsl_literal_string; +char *__gen_e_acsl_literal_string_2; +struct ST { + char *str ; + int num ; +}; +struct ST _G[2] = + {{.str = (char *)"Struct_G[0]", .num = 99}, + {.str = (char *)"Struct_G[1]", .num = 147}}; +void __e_acsl_globals_init(void) +{ + static char __e_acsl_already_run = 0; + if (! __e_acsl_already_run) { + __e_acsl_already_run = 1; + __gen_e_acsl_literal_string = "Struct_G[1]"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string, + sizeof("Struct_G[1]")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string); + __gen_e_acsl_literal_string_2 = "Struct_G[0]"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_2, + sizeof("Struct_G[0]")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_2); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_2); + __e_acsl_store_block((void *)(_G),(size_t)32); + __e_acsl_full_init((void *)(& _G)); + } + return; +} + +int main(int argc, char **argv) +{ + int __retres; + __e_acsl_memory_init(& argc,& argv,(size_t)8); + __e_acsl_globals_init(); + /*@ assert \valid_read(_G[0].str); */ + { + int __gen_e_acsl_initialized; + int __gen_e_acsl_and; + __gen_e_acsl_initialized = __e_acsl_initialized((void *)(& _G[0].str), + sizeof(char *)); + if (__gen_e_acsl_initialized) { + int __gen_e_acsl_valid_read; + __gen_e_acsl_valid_read = __e_acsl_valid_read((void *)_G[0].str, + sizeof(char), + (void *)_G[0].str, + (void *)(& _G[0].str)); + __gen_e_acsl_and = __gen_e_acsl_valid_read; + } + else __gen_e_acsl_and = 0; + __e_acsl_assert(__gen_e_acsl_and,(char *)"Assertion",(char *)"main", + (char *)"\\valid_read(_G[0].str)",22); + } + __retres = 0; + __e_acsl_delete_block((void *)(_G)); + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/bts/oracle_ci/gen_bts2192.c b/src/plugins/e-acsl/tests/bts/oracle_ci/gen_bts2192.c new file mode 100644 index 0000000000000000000000000000000000000000..5cd324316570b0133733102547a312cdef4c3b3f --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/oracle_ci/gen_bts2192.c @@ -0,0 +1,37 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +char *__gen_e_acsl_literal_string; +extern int __e_acsl_sound_verdict; + +int a; +char *n = (char *)"134"; +void __e_acsl_globals_init(void) +{ + static char __e_acsl_already_run = 0; + if (! __e_acsl_already_run) { + __e_acsl_already_run = 1; + __gen_e_acsl_literal_string = "134"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string,sizeof("134")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string); + __e_acsl_store_block((void *)(& n),(size_t)8); + __e_acsl_full_init((void *)(& n)); + } + return; +} + +int main(int argc, char **argv) +{ + int __retres; + __e_acsl_memory_init(& argc,& argv,(size_t)8); + __e_acsl_globals_init(); + argc = __gen_e_acsl_atoi((char const *)n); + a = argc; + __retres = 0; + __e_acsl_delete_block((void *)(& n)); + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/bts/oracle_ci/gen_bts2231.c b/src/plugins/e-acsl/tests/bts/oracle_ci/gen_bts2231.c new file mode 100644 index 0000000000000000000000000000000000000000..34883c5320423d24ad61d9eadb9ff086aa364531 --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/oracle_ci/gen_bts2231.c @@ -0,0 +1,49 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +long A = (long)0; +int main(void) +{ + int __retres; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + /*@ assert A + (long)((long)(3 * A) - 1) ≡ -1; */ + { + __e_acsl_mpz_t __gen_e_acsl_A; + __e_acsl_mpz_t __gen_e_acsl_; + __e_acsl_mpz_t __gen_e_acsl_mul; + long __gen_e_acsl__2; + __e_acsl_mpz_t __gen_e_acsl__3; + __e_acsl_mpz_t __gen_e_acsl_add; + __e_acsl_mpz_t __gen_e_acsl__4; + int __gen_e_acsl_eq; + __gmpz_init_set_si(__gen_e_acsl_A,A); + __gmpz_init_set_si(__gen_e_acsl_,3L); + __gmpz_init(__gen_e_acsl_mul); + __gmpz_mul(__gen_e_acsl_mul,(__e_acsl_mpz_struct const *)(__gen_e_acsl_), + (__e_acsl_mpz_struct const *)(__gen_e_acsl_A)); + __gen_e_acsl__2 = __gmpz_get_si((__e_acsl_mpz_struct const *)(__gen_e_acsl_mul)); + /*@ assert + Eva: signed_overflow: -9223372036854775808 ≤ __gen_e_acsl__2 - 1; + */ + __gmpz_init_set_si(__gen_e_acsl__3,__gen_e_acsl__2 - 1L); + __gmpz_init(__gen_e_acsl_add); + __gmpz_add(__gen_e_acsl_add, + (__e_acsl_mpz_struct const *)(__gen_e_acsl_A), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__3)); + __gmpz_init_set_si(__gen_e_acsl__4,(long)(-1)); + __gen_e_acsl_eq = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_add), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__4)); + __e_acsl_assert(__gen_e_acsl_eq == 0,(char *)"Assertion",(char *)"main", + (char *)"A + (long)((long)(3 * A) - 1) == -1",8); + __gmpz_clear(__gen_e_acsl_A); + __gmpz_clear(__gen_e_acsl_); + __gmpz_clear(__gen_e_acsl_mul); + __gmpz_clear(__gen_e_acsl__3); + __gmpz_clear(__gen_e_acsl_add); + __gmpz_clear(__gen_e_acsl__4); + } + __retres = 0; + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/bts/oracle_ci/gen_bts2252.c b/src/plugins/e-acsl/tests/bts/oracle_ci/gen_bts2252.c new file mode 100644 index 0000000000000000000000000000000000000000..7b40292a1946339d0c3dce68b94cc597745e4d9a --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/oracle_ci/gen_bts2252.c @@ -0,0 +1,65 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +char *__gen_e_acsl_literal_string; +/*@ assigns \result, *(x_0 + (0 ..)), *(x_1 + (0 ..)); + assigns \result \from *(x_0 + (0 ..)), *(x_1 + (0 ..)), x_2; + assigns *(x_0 + (0 ..)) \from *(x_0 + (0 ..)), *(x_1 + (0 ..)), x_2; + assigns *(x_1 + (0 ..)) \from *(x_0 + (0 ..)), *(x_1 + (0 ..)), x_2; + */ +extern int ( /* missing proto */ strncpy)(char *x_0, char *x_1, int x_2); + +void __e_acsl_globals_init(void) +{ + static char __e_acsl_already_run = 0; + if (! __e_acsl_already_run) { + __e_acsl_already_run = 1; + __gen_e_acsl_literal_string = "Test Code"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string, + sizeof("Test Code")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string); + } + return; +} + +int main(void) +{ + int __retres; + int i; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + __e_acsl_globals_init(); + char *srcbuf = (char *)__gen_e_acsl_literal_string; + __e_acsl_store_block((void *)(& srcbuf),(size_t)8); + __e_acsl_full_init((void *)(& srcbuf)); + int loc = 1; + char *destbuf = malloc((unsigned long)10 * sizeof(char)); + char ch = (char)'o'; + if (destbuf != (char *)0) { + i = -1; + while (i < 0) { + /*@ assert ¬\valid_read(srcbuf + i); */ + { + int __gen_e_acsl_valid_read; + __gen_e_acsl_valid_read = __e_acsl_valid_read((void *)(srcbuf + i), + sizeof(char), + (void *)srcbuf, + (void *)(& srcbuf)); + __e_acsl_assert(! __gen_e_acsl_valid_read,(char *)"Assertion", + (char *)"main",(char *)"!\\valid_read(srcbuf + i)", + 16); + } + /*@ assert Eva: mem_access: \valid_read(srcbuf + i); */ + if ((int)*(srcbuf + i) == (int)ch) loc = i; + i ++; + } + strncpy(destbuf + loc,srcbuf + loc,1); + free((void *)destbuf); + } + __retres = 0; + __e_acsl_delete_block((void *)(& srcbuf)); + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/bts/oracle_ci/gen_bts2305.c b/src/plugins/e-acsl/tests/bts/oracle_ci/gen_bts2305.c new file mode 100644 index 0000000000000000000000000000000000000000..29d1004ec5b7ebcd3a8136c1bb4a313979aa7184 --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/oracle_ci/gen_bts2305.c @@ -0,0 +1,43 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +struct bitfields { + int i : 2 ; + _Bool j : 1 ; +}; +struct bitfields t; +int test(struct bitfields *a) +{ + int __retres; + __retres = (int)a->i; + return __retres; +} + +void __e_acsl_globals_init(void) +{ + static char __e_acsl_already_run = 0; + if (! __e_acsl_already_run) { + __e_acsl_already_run = 1; + __e_acsl_store_block((void *)(& t),(size_t)4); + __e_acsl_full_init((void *)(& t)); + } + return; +} + +int main(int argc, char **argv) +{ + int tmp; + __e_acsl_memory_init(& argc,& argv,(size_t)8); + __e_acsl_globals_init(); + /*@ assert \valid_read(&t.j); */ ; + /*@ assert \valid_read(&t.j + (1 .. 3)); */ ; + ; + t.j = (_Bool)1; + /*@ assert \initialized(&t.j); */ ; + tmp = test(& t); + __e_acsl_delete_block((void *)(& t)); + __e_acsl_memory_clean(); + return tmp; +} + + diff --git a/src/plugins/e-acsl/tests/bts/oracle_ci/gen_bts2386.c b/src/plugins/e-acsl/tests/bts/oracle_ci/gen_bts2386.c new file mode 100644 index 0000000000000000000000000000000000000000..d2bead7b834fb6caea5b65104229f7b21bbbe209 --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/oracle_ci/gen_bts2386.c @@ -0,0 +1,68 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +char *__gen_e_acsl_literal_string; +void f(void const *s, int c, unsigned long n) +{ + __e_acsl_store_block((void *)(& s),(size_t)8); + unsigned char const *p = (unsigned char const *)s; + __e_acsl_store_block((void *)(& p),(size_t)8); + __e_acsl_full_init((void *)(& p)); + /*@ assert p - (unsigned char const *)s ≡ n - n; */ + { + __e_acsl_mpz_t __gen_e_acsl_; + __e_acsl_mpz_t __gen_e_acsl_n; + __e_acsl_mpz_t __gen_e_acsl_sub; + int __gen_e_acsl_eq; + __gmpz_init_set_ui(__gen_e_acsl_,p - (unsigned char const *)s); + __gmpz_init_set_ui(__gen_e_acsl_n,n); + __gmpz_init(__gen_e_acsl_sub); + __gmpz_sub(__gen_e_acsl_sub, + (__e_acsl_mpz_struct const *)(__gen_e_acsl_n), + (__e_acsl_mpz_struct const *)(__gen_e_acsl_n)); + __gen_e_acsl_eq = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_), + (__e_acsl_mpz_struct const *)(__gen_e_acsl_sub)); + __e_acsl_assert(__gen_e_acsl_eq == 0,(char *)"Assertion",(char *)"f", + (char *)"p - (unsigned char const *)s == n - n",7); + __gmpz_clear(__gen_e_acsl_); + __gmpz_clear(__gen_e_acsl_n); + __gmpz_clear(__gen_e_acsl_sub); + } + /*@ assert p - (unsigned char const *)s ≡ 0; */ + __e_acsl_assert(p - (unsigned char const *)s == 0UL,(char *)"Assertion", + (char *)"f",(char *)"p - (unsigned char const *)s == 0",8); + __e_acsl_delete_block((void *)(& s)); + __e_acsl_delete_block((void *)(& p)); + return; +} + +void __e_acsl_globals_init(void) +{ + static char __e_acsl_already_run = 0; + if (! __e_acsl_already_run) { + __e_acsl_already_run = 1; + __gen_e_acsl_literal_string = "1234567890"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string, + sizeof("1234567890")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string); + } + return; +} + +int main(void) +{ + int __retres; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + __e_acsl_globals_init(); + char const *s = __gen_e_acsl_literal_string; + __e_acsl_store_block((void *)(& s),(size_t)8); + __e_acsl_full_init((void *)(& s)); + f((void const *)s,'0',(unsigned long)11); + __retres = 0; + __e_acsl_delete_block((void *)(& s)); + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/bts/oracle_ci/gen_bts2406.c b/src/plugins/e-acsl/tests/bts/oracle_ci/gen_bts2406.c new file mode 100644 index 0000000000000000000000000000000000000000..a3166bf55c9d963ff0838533484b18d794275c62 --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/oracle_ci/gen_bts2406.c @@ -0,0 +1,48 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +char const tab[]; +char t[10]; +void __e_acsl_globals_init(void) +{ + static char __e_acsl_already_run = 0; + if (! __e_acsl_already_run) { + __e_acsl_already_run = 1; + __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; +} + + diff --git a/src/plugins/e-acsl/tests/bts/oracle_ci/gen_issue69.c b/src/plugins/e-acsl/tests/bts/oracle_ci/gen_issue69.c new file mode 100644 index 0000000000000000000000000000000000000000..a25febaa04eb5c0935ff2c13b3e7ebbd27a0ff85 --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/oracle_ci/gen_issue69.c @@ -0,0 +1,69 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +int main(void) +{ + int __retres; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + /*@ assert ∀ unsigned char c; 4 ≤ c ≤ 300 ⇒ 0 ≤ c ≤ 255; */ + { + int __gen_e_acsl_forall; + int __gen_e_acsl_c; + __gen_e_acsl_forall = 1; + __gen_e_acsl_c = (unsigned char)4; + while (1) { + if (__gen_e_acsl_c <= 255) ; else break; + { + int __gen_e_acsl_and; + if (0 <= __gen_e_acsl_c) __gen_e_acsl_and = __gen_e_acsl_c <= 255; + else __gen_e_acsl_and = 0; + if (__gen_e_acsl_and) ; + else { + __gen_e_acsl_forall = 0; + goto e_acsl_end_loop1; + } + } + __gen_e_acsl_c ++; + } + e_acsl_end_loop1: ; + __e_acsl_assert(__gen_e_acsl_forall,(char *)"Assertion",(char *)"main", + (char *)"\\forall unsigned char c; 4 <= c <= 300 ==> 0 <= c <= 255", + 6); + } + int n = 5; + /*@ assert \let m = n > 0? 4: 341; ∀ char u; 1 < u < m ⇒ u > 0; */ + { + int __gen_e_acsl_m; + int __gen_e_acsl_if; + int __gen_e_acsl_forall_2; + int __gen_e_acsl_u; + if (n > 0) __gen_e_acsl_if = 4; else __gen_e_acsl_if = 341; + __gen_e_acsl_m = __gen_e_acsl_if; + __gen_e_acsl_forall_2 = 1; + __gen_e_acsl_u = (char)1 + 1; + while (1) { + { + int __gen_e_acsl_and_2; + if (-128 <= __gen_e_acsl_u) __gen_e_acsl_and_2 = __gen_e_acsl_u <= 127; + else __gen_e_acsl_and_2 = 0; + __e_acsl_assert(__gen_e_acsl_and_2,(char *)"RTE",(char *)"main", + (char *)"-128 <= u <= 127",11); + } + if (__gen_e_acsl_u < __gen_e_acsl_m) ; else break; + if (__gen_e_acsl_u > 0) ; + else { + __gen_e_acsl_forall_2 = 0; + goto e_acsl_end_loop2; + } + __gen_e_acsl_u ++; + } + e_acsl_end_loop2: ; + __e_acsl_assert(__gen_e_acsl_forall_2,(char *)"Assertion",(char *)"main", + (char *)"\\let m = n > 0? 4: 341;\n\\forall char u; 1 < u < m ==> u > 0", + 10); + } + __retres = 0; + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/bts/oracle_ci/issue69.res.oracle b/src/plugins/e-acsl/tests/bts/oracle_ci/issue69.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..a3f1846d9e3c3d39035133222a4eb354bac869d2 --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/oracle_ci/issue69.res.oracle @@ -0,0 +1,3 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". +[eva:alarm] tests/bts/issue69.c:10: Warning: assertion got status unknown. diff --git a/src/plugins/e-acsl/tests/bts/oracle_dev/bts1304.res.oracle b/src/plugins/e-acsl/tests/bts/oracle_dev/bts1304.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..19b0f068878a54abe6eb70c9b11771166b5fb060 --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/oracle_dev/bts1304.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/bts/bts1304.i (no preprocessing) diff --git a/src/plugins/e-acsl/tests/bts/oracle_dev/bts1307.res.oracle b/src/plugins/e-acsl/tests/bts/oracle_dev/bts1307.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..0b966552605c312df3df587c9091b5dc19f54d58 --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/oracle_dev/bts1307.res.oracle @@ -0,0 +1,4 @@ +[kernel] Parsing tests/bts/bts1307.i (no preprocessing) +[kernel:parser:decimal-float] tests/bts/bts1307.i:17: Warning: + Floating-point constant 0.4 is not represented exactly. Will use 0x1.999999999999ap-2. + (warn-once: no further messages from category 'parser:decimal-float' will be emitted) diff --git a/src/plugins/e-acsl/tests/bts/oracle_dev/bts1324.res.oracle b/src/plugins/e-acsl/tests/bts/oracle_dev/bts1324.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..e65b24385610fbf0e9291a09879dba416d9cfe8e --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/oracle_dev/bts1324.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/bts/bts1324.i (no preprocessing) diff --git a/src/plugins/e-acsl/tests/bts/oracle_dev/bts1326.res.oracle b/src/plugins/e-acsl/tests/bts/oracle_dev/bts1326.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..99bd8d2ca4576581e7e3419c51e1178a1542723a --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/oracle_dev/bts1326.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/bts/bts1326.i (no preprocessing) diff --git a/src/plugins/e-acsl/tests/bts/oracle_dev/bts1390.res.oracle b/src/plugins/e-acsl/tests/bts/oracle_dev/bts1390.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..3790aca8b1648cf45e6ab0e2e7266144f44af3ae --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/oracle_dev/bts1390.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/bts/bts1390.c (with preprocessing) diff --git a/src/plugins/e-acsl/tests/bts/oracle_dev/bts1395.res.oracle b/src/plugins/e-acsl/tests/bts/oracle_dev/bts1395.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..cb9a17cb49257c74abf0d92dee4c7b8549ecd8b1 --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/oracle_dev/bts1395.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/bts/bts1395.i (no preprocessing) diff --git a/src/plugins/e-acsl/tests/bts/oracle_dev/bts1398.res.oracle b/src/plugins/e-acsl/tests/bts/oracle_dev/bts1398.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..ce219311963cd7c5a48aa4b07869a6c3d3c3389c --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/oracle_dev/bts1398.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/bts/bts1398.c (with preprocessing) diff --git a/src/plugins/e-acsl/tests/bts/oracle_dev/bts1399.res.oracle b/src/plugins/e-acsl/tests/bts/oracle_dev/bts1399.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..ea0b0b3e5e737e8e972eab0de467729f1b55189b --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/oracle_dev/bts1399.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/bts/bts1399.c (with preprocessing) diff --git a/src/plugins/e-acsl/tests/bts/oracle_dev/bts1478.res.oracle b/src/plugins/e-acsl/tests/bts/oracle_dev/bts1478.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..1baa04b66fa314c4f33180491d831eea829a54fe --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/oracle_dev/bts1478.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/bts/bts1478.c (with preprocessing) diff --git a/src/plugins/e-acsl/tests/bts/oracle_dev/bts1700.res.oracle b/src/plugins/e-acsl/tests/bts/oracle_dev/bts1700.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..d13cbafb98cd23d76f9ee695bc5c1e0e9158f7a4 --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/oracle_dev/bts1700.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/bts/bts1700.i (no preprocessing) diff --git a/src/plugins/e-acsl/tests/bts/oracle_dev/bts1717.res.oracle b/src/plugins/e-acsl/tests/bts/oracle_dev/bts1717.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..2ed4f6df3461b85181897a66820a8073efcbefdf --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/oracle_dev/bts1717.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/bts/bts1717.i (no preprocessing) diff --git a/src/plugins/e-acsl/tests/bts/oracle_dev/bts1718.res.oracle b/src/plugins/e-acsl/tests/bts/oracle_dev/bts1718.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..1c4ca2adb3d7fa12bc94ab4b2420f2c3a44603a7 --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/oracle_dev/bts1718.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/bts/bts1718.i (no preprocessing) diff --git a/src/plugins/e-acsl/tests/bts/oracle_dev/bts1740.res.oracle b/src/plugins/e-acsl/tests/bts/oracle_dev/bts1740.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..9751b7a8a5562c012c8a3a6bf06e091659203991 --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/oracle_dev/bts1740.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/bts/bts1740.i (no preprocessing) diff --git a/src/plugins/e-acsl/tests/bts/oracle_dev/bts1837.res.oracle b/src/plugins/e-acsl/tests/bts/oracle_dev/bts1837.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..f751f743c00132de9c3f257ce73c01deb8859b22 --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/oracle_dev/bts1837.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/bts/bts1837.i (no preprocessing) diff --git a/src/plugins/e-acsl/tests/bts/oracle_dev/bts2191.res.oracle b/src/plugins/e-acsl/tests/bts/oracle_dev/bts2191.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..4c326f214a130cf42d1e795388b0c88f34f6caa7 --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/oracle_dev/bts2191.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/bts/bts2191.c (with preprocessing) diff --git a/src/plugins/e-acsl/tests/bts/oracle_dev/bts2192.res.oracle b/src/plugins/e-acsl/tests/bts/oracle_dev/bts2192.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..0122a7e4246394af3459e31969e6a0375ed0c61c --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/oracle_dev/bts2192.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/bts/bts2192.c (with preprocessing) diff --git a/src/plugins/e-acsl/tests/bts/oracle_dev/bts2231.res.oracle b/src/plugins/e-acsl/tests/bts/oracle_dev/bts2231.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..4ef916d51cbfbbc01e1fb200ecaded57aa452471 --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/oracle_dev/bts2231.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/bts/bts2231.i (no preprocessing) diff --git a/src/plugins/e-acsl/tests/bts/oracle_dev/bts2252.res.oracle b/src/plugins/e-acsl/tests/bts/oracle_dev/bts2252.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..d21a94caccea54821812cfe937ca2446a230fb1c --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/oracle_dev/bts2252.res.oracle @@ -0,0 +1,3 @@ +[kernel] Parsing tests/bts/bts2252.c (with preprocessing) +[kernel:typing:implicit-function-declaration] tests/bts/bts2252.c:22: Warning: + Calling undeclared function strncpy. Old style K&R code? diff --git a/src/plugins/e-acsl/tests/bts/oracle_dev/bts2305.res.oracle b/src/plugins/e-acsl/tests/bts/oracle_dev/bts2305.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..5c570a670fa5408249a025b31ade7311a391fdd2 --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/oracle_dev/bts2305.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/bts/bts2305.c (with preprocessing) diff --git a/src/plugins/e-acsl/tests/bts/oracle_dev/bts2386.res.oracle b/src/plugins/e-acsl/tests/bts/oracle_dev/bts2386.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..3bd50695afb1343ab68cf179bf22c6364bacf2f7 --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/oracle_dev/bts2386.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/bts/bts2386.c (with preprocessing) diff --git a/src/plugins/e-acsl/tests/bts/oracle_dev/bts2406.res.oracle b/src/plugins/e-acsl/tests/bts/oracle_dev/bts2406.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..b09566f3aaf5b42219646778e6125c8a6b38df98 --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/oracle_dev/bts2406.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/bts/bts2406.c (with preprocessing) diff --git a/src/plugins/e-acsl/tests/bts/oracle_dev/issue69.res.oracle b/src/plugins/e-acsl/tests/bts/oracle_dev/issue69.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..c2db810f8d36e24400c596766b288e2e333c8a3d --- /dev/null +++ b/src/plugins/e-acsl/tests/bts/oracle_dev/issue69.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/bts/issue69.c (with preprocessing) diff --git a/src/plugins/e-acsl/tests/builtin/README.md b/src/plugins/e-acsl/tests/builtin/README.md new file mode 100644 index 0000000000000000000000000000000000000000..183840bc52b591901fd43bb350224e374d609abf --- /dev/null +++ b/src/plugins/e-acsl/tests/builtin/README.md @@ -0,0 +1 @@ +Like full-model, but also test instrumentation with -e-acsl-replace-libc-functions diff --git a/src/plugins/e-acsl/tests/builtin/oracle_ci/gen_strcat.c b/src/plugins/e-acsl/tests/builtin/oracle_ci/gen_strcat.c new file mode 100644 index 0000000000000000000000000000000000000000..26c57de7b341828a1aa8202d4ebde22536cd7572 --- /dev/null +++ b/src/plugins/e-acsl/tests/builtin/oracle_ci/gen_strcat.c @@ -0,0 +1,1051 @@ +/* Generated by Frama-C */ +#include "setjmp.h" +#include "signal.h" +#include "stdio.h" +#include "stdlib.h" +#include "string.h" +char *__gen_e_acsl_literal_string_25; +char *__gen_e_acsl_literal_string_24; +char *__gen_e_acsl_literal_string_23; +char *__gen_e_acsl_literal_string_22; +char *__gen_e_acsl_literal_string_21; +char *__gen_e_acsl_literal_string_20; +char *__gen_e_acsl_literal_string_19; +char *__gen_e_acsl_literal_string_18; +char *__gen_e_acsl_literal_string_17; +char *__gen_e_acsl_literal_string_16; +char *__gen_e_acsl_literal_string_15; +char *__gen_e_acsl_literal_string_14; +char *__gen_e_acsl_literal_string_13; +char *__gen_e_acsl_literal_string_12; +char *__gen_e_acsl_literal_string_11; +char *__gen_e_acsl_literal_string_10; +char *__gen_e_acsl_literal_string_9; +char *__gen_e_acsl_literal_string_8; +char *__gen_e_acsl_literal_string_7; +char *__gen_e_acsl_literal_string_6; +char *__gen_e_acsl_literal_string_5; +char *__gen_e_acsl_literal_string_3; +char *__gen_e_acsl_literal_string; +char *__gen_e_acsl_literal_string_4; +char *__gen_e_acsl_literal_string_2; +extern int __e_acsl_sound_verdict; + +void __e_acsl_globals_init(void) +{ + static char __e_acsl_already_run = 0; + if (! __e_acsl_already_run) { + __e_acsl_already_run = 1; + __gen_e_acsl_literal_string_25 = "tests/builtin/strcat.c:61"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_25, + sizeof("tests/builtin/strcat.c:61")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_25); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_25); + __gen_e_acsl_literal_string_24 = "tests/builtin/strcat.c:60"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_24, + sizeof("tests/builtin/strcat.c:60")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_24); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_24); + __gen_e_acsl_literal_string_23 = "tests/builtin/strcat.c:59"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_23, + sizeof("tests/builtin/strcat.c:59")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_23); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_23); + __gen_e_acsl_literal_string_22 = "tests/builtin/strcat.c:57"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_22, + sizeof("tests/builtin/strcat.c:57")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_22); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_22); + __gen_e_acsl_literal_string_21 = "tests/builtin/strcat.c:56"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_21, + sizeof("tests/builtin/strcat.c:56")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_21); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_21); + __gen_e_acsl_literal_string_20 = "tests/builtin/strcat.c:55"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_20, + sizeof("tests/builtin/strcat.c:55")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_20); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_20); + __gen_e_acsl_literal_string_19 = "tests/builtin/strcat.c:54"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_19, + sizeof("tests/builtin/strcat.c:54")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_19); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_19); + __gen_e_acsl_literal_string_18 = "tests/builtin/strcat.c:53"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_18, + sizeof("tests/builtin/strcat.c:53")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_18); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_18); + __gen_e_acsl_literal_string_17 = "tests/builtin/strcat.c:52"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_17, + sizeof("tests/builtin/strcat.c:52")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_17); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_17); + __gen_e_acsl_literal_string_16 = "tests/builtin/strcat.c:51"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_16, + sizeof("tests/builtin/strcat.c:51")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_16); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_16); + __gen_e_acsl_literal_string_15 = "tests/builtin/strcat.c:38"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_15, + sizeof("tests/builtin/strcat.c:38")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_15); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_15); + __gen_e_acsl_literal_string_14 = "tests/builtin/strcat.c:37"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_14, + sizeof("tests/builtin/strcat.c:37")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_14); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_14); + __gen_e_acsl_literal_string_13 = "tests/builtin/strcat.c:36"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_13, + sizeof("tests/builtin/strcat.c:36")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_13); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_13); + __gen_e_acsl_literal_string_12 = "tests/builtin/strcat.c:35"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_12, + sizeof("tests/builtin/strcat.c:35")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_12); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_12); + __gen_e_acsl_literal_string_11 = "tests/builtin/strcat.c:34"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_11, + sizeof("tests/builtin/strcat.c:34")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_11); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_11); + __gen_e_acsl_literal_string_10 = "tests/builtin/strcat.c:33"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_10, + sizeof("tests/builtin/strcat.c:33")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_10); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_10); + __gen_e_acsl_literal_string_9 = "tests/builtin/strcat.c:32"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_9, + sizeof("tests/builtin/strcat.c:32")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_9); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_9); + __gen_e_acsl_literal_string_8 = "tests/builtin/strcat.c:31"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_8, + sizeof("tests/builtin/strcat.c:31")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_8); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_8); + __gen_e_acsl_literal_string_7 = "tests/builtin/strcat.c:30"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_7, + sizeof("tests/builtin/strcat.c:30")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_7); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_7); + __gen_e_acsl_literal_string_6 = "tests/builtin/strcat.c:29"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_6, + sizeof("tests/builtin/strcat.c:29")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_6); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_6); + __gen_e_acsl_literal_string_5 = "tests/builtin/strcat.c:28"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_5, + sizeof("tests/builtin/strcat.c:28")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_5); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_5); + __gen_e_acsl_literal_string_3 = "tests/builtin/strcat.c:27"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_3, + sizeof("tests/builtin/strcat.c:27")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_3); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_3); + __gen_e_acsl_literal_string = "abcd"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string,sizeof("abcd")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string); + __gen_e_acsl_literal_string_4 = "FAIL: Unexpected value return from test at %s\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_4, + sizeof("FAIL: Unexpected value return from test at %s\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_4); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_4); + __gen_e_acsl_literal_string_2 = ""; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_2,sizeof("")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_2); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_2); + __e_acsl_store_block((void *)(& __gen_e_acsl_strncat),(size_t)1); + __e_acsl_full_init((void *)(& __gen_e_acsl_strncat)); + __e_acsl_store_block((void *)(& __gen_e_acsl_strcat),(size_t)1); + __e_acsl_full_init((void *)(& __gen_e_acsl_strcat)); + __e_acsl_store_block((void *)(& __gen_e_acsl_exit),(size_t)1); + __e_acsl_full_init((void *)(& __gen_e_acsl_exit)); + __e_acsl_store_block((void *)(& __fc_p_strerror),(size_t)8); + __e_acsl_full_init((void *)(& __fc_p_strerror)); + __e_acsl_store_block((void *)(strerror),(size_t)64); + __e_acsl_full_init((void *)(& strerror)); + __e_acsl_store_block((void *)(& __fc_strtok_ptr),(size_t)8); + __e_acsl_full_init((void *)(& __fc_strtok_ptr)); + __e_acsl_store_block((void *)(& __fc_p_fopen),(size_t)8); + __e_acsl_full_init((void *)(& __fc_p_fopen)); + __e_acsl_store_block((void *)(__fc_fopen),(size_t)128); + __e_acsl_full_init((void *)(& __fc_fopen)); + __e_acsl_store_block((void *)(& __fc_rand_max),(size_t)8); + __e_acsl_full_init((void *)(& __fc_rand_max)); + } + return; +} + +int main(int argc, char const **argv) +{ + int __retres; + __e_acsl_memory_init(& argc,(char ***)(& argv),(size_t)8); + __e_acsl_globals_init(); + __e_acsl_store_block((void *)(& __retres),(size_t)4); + char *const_str = (char *)__gen_e_acsl_literal_string; + __e_acsl_store_block((void *)(& const_str),(size_t)8); + __e_acsl_full_init((void *)(& const_str)); + char *unalloc_str = malloc((unsigned long)5); + __e_acsl_store_block((void *)(& unalloc_str),(size_t)8); + __e_acsl_full_init((void *)(& unalloc_str)); + char *_barrier = malloc((unsigned long)1); + __e_acsl_store_block((void *)(& _barrier),(size_t)8); + __e_acsl_full_init((void *)(& _barrier)); + char *empty_str = (char *)__gen_e_acsl_literal_string_2; + __e_acsl_store_block((void *)(& empty_str),(size_t)8); + __e_acsl_full_init((void *)(& empty_str)); + free((void *)unalloc_str); + { + char dest1[9] = + {(char)'d', (char)'c', (char)'b', (char)'a', (char)'\000'}; + __e_acsl_store_block((void *)(dest1),(size_t)9); + __e_acsl_full_init((void *)(& dest1)); + char dest2[8] = + {(char)'d', (char)'c', (char)'b', (char)'a', (char)'\000'}; + __e_acsl_store_block((void *)(dest2),(size_t)8); + __e_acsl_full_init((void *)(& dest2)); + char dest3[5] = + {(char)'-', (char)'-', (char)'-', (char)'-', (char)'\000'}; + __e_acsl_store_block((void *)(dest3),(size_t)5); + __e_acsl_full_init((void *)(& dest3)); + char dest4[10] = + {(char)'d', (char)'c', (char)'b', (char)'a', (char)'\000'}; + __e_acsl_store_block((void *)(dest4),(size_t)10); + __e_acsl_full_init((void *)(& dest4)); + char *pd1 = (char *)(& dest1); + __e_acsl_store_block((void *)(& pd1),(size_t)8); + __e_acsl_full_init((void *)(& pd1)); + char *pd2 = (char *)(& dest2); + __e_acsl_store_block((void *)(& pd2),(size_t)8); + __e_acsl_full_init((void *)(& pd2)); + char *pd3 = (char *)(& dest3); + __e_acsl_store_block((void *)(& pd3),(size_t)8); + __e_acsl_full_init((void *)(& pd3)); + char *pd4 = (char *)(& dest4); + __e_acsl_store_block((void *)(& pd4),(size_t)8); + __e_acsl_full_init((void *)(& pd4)); + { + int tmp_2; + __e_acsl_store_block((void *)(& tmp_2),(size_t)4); + sigjmp_buf *jmp_ctxt = get_jmp_ctxt(); + __e_acsl_store_block((void *)(& jmp_ctxt),(size_t)8); + __e_acsl_full_init((void *)(& jmp_ctxt)); + __e_acsl_full_init((void *)(& tmp_2)); + /*@ assert Eva: mem_access: \valid_read(jmp_ctxt); */ + tmp_2 = sigsetjmp(*jmp_ctxt,1); + switch (tmp_2) { + case 0: + { + set_handler(); + __gen_e_acsl_strcat(dest1,(char const *)const_str); + test_successful(); + break; + } + case 1: { + signal_eval(0,0,__gen_e_acsl_literal_string_3); + break; + } + case 2: { + signal_eval(1,0,__gen_e_acsl_literal_string_3); + break; + } + default: + { + printf(__gen_e_acsl_literal_string_4,__gen_e_acsl_literal_string_3); + __gen_e_acsl_exit(3); + } + } + __e_acsl_delete_block((void *)(& tmp_2)); + __e_acsl_delete_block((void *)(& jmp_ctxt)); + } + { + int tmp_4; + __e_acsl_store_block((void *)(& tmp_4),(size_t)4); + sigjmp_buf *jmp_ctxt_0 = get_jmp_ctxt(); + __e_acsl_store_block((void *)(& jmp_ctxt_0),(size_t)8); + __e_acsl_full_init((void *)(& jmp_ctxt_0)); + __e_acsl_full_init((void *)(& tmp_4)); + tmp_4 = sigsetjmp(*jmp_ctxt_0,1); + switch (tmp_4) { + case 0: + { + set_handler(); + __gen_e_acsl_strcat(dest3,(char const *)empty_str); + test_successful(); + break; + } + case 1: { + signal_eval(0,0,__gen_e_acsl_literal_string_5); + break; + } + case 2: { + signal_eval(1,0,__gen_e_acsl_literal_string_5); + break; + } + default: + { + printf(__gen_e_acsl_literal_string_4,__gen_e_acsl_literal_string_5); + __gen_e_acsl_exit(3); + } + } + __e_acsl_delete_block((void *)(& tmp_4)); + __e_acsl_delete_block((void *)(& jmp_ctxt_0)); + } + { + int tmp_6; + __e_acsl_store_block((void *)(& tmp_6),(size_t)4); + sigjmp_buf *jmp_ctxt_1 = get_jmp_ctxt(); + __e_acsl_store_block((void *)(& jmp_ctxt_1),(size_t)8); + __e_acsl_full_init((void *)(& jmp_ctxt_1)); + __e_acsl_full_init((void *)(& tmp_6)); + tmp_6 = sigsetjmp(*jmp_ctxt_1,1); + switch (tmp_6) { + case 0: + { + set_handler(); + __gen_e_acsl_strcat(dest2,(char const *)const_str); + test_successful(); + break; + } + case 1: { + signal_eval(0,1,__gen_e_acsl_literal_string_6); + break; + } + case 2: { + signal_eval(1,1,__gen_e_acsl_literal_string_6); + break; + } + default: + { + printf(__gen_e_acsl_literal_string_4,__gen_e_acsl_literal_string_6); + __gen_e_acsl_exit(3); + } + } + __e_acsl_delete_block((void *)(& tmp_6)); + __e_acsl_delete_block((void *)(& jmp_ctxt_1)); + } + { + int tmp_8; + __e_acsl_store_block((void *)(& tmp_8),(size_t)4); + sigjmp_buf *jmp_ctxt_2 = get_jmp_ctxt(); + __e_acsl_store_block((void *)(& jmp_ctxt_2),(size_t)8); + __e_acsl_full_init((void *)(& jmp_ctxt_2)); + __e_acsl_full_init((void *)(& tmp_8)); + tmp_8 = sigsetjmp(*jmp_ctxt_2,1); + switch (tmp_8) { + case 0: + { + set_handler(); + __gen_e_acsl_strcat(unalloc_str,(char const *)const_str); + test_successful(); + break; + } + case 1: { + signal_eval(0,1,__gen_e_acsl_literal_string_7); + break; + } + case 2: { + signal_eval(1,1,__gen_e_acsl_literal_string_7); + break; + } + default: + { + printf(__gen_e_acsl_literal_string_4,__gen_e_acsl_literal_string_7); + __gen_e_acsl_exit(3); + } + } + __e_acsl_delete_block((void *)(& tmp_8)); + __e_acsl_delete_block((void *)(& jmp_ctxt_2)); + } + { + int tmp_10; + __e_acsl_store_block((void *)(& tmp_10),(size_t)4); + sigjmp_buf *jmp_ctxt_3 = get_jmp_ctxt(); + __e_acsl_store_block((void *)(& jmp_ctxt_3),(size_t)8); + __e_acsl_full_init((void *)(& jmp_ctxt_3)); + __e_acsl_full_init((void *)(& tmp_10)); + tmp_10 = sigsetjmp(*jmp_ctxt_3,1); + switch (tmp_10) { + case 0: + { + set_handler(); + __gen_e_acsl_strcat(dest2,(char const *)unalloc_str); + test_successful(); + break; + } + case 1: { + signal_eval(0,1,__gen_e_acsl_literal_string_8); + break; + } + case 2: { + signal_eval(1,1,__gen_e_acsl_literal_string_8); + break; + } + default: + { + printf(__gen_e_acsl_literal_string_4,__gen_e_acsl_literal_string_8); + __gen_e_acsl_exit(3); + } + } + __e_acsl_delete_block((void *)(& tmp_10)); + __e_acsl_delete_block((void *)(& jmp_ctxt_3)); + } + { + int tmp_12; + __e_acsl_store_block((void *)(& tmp_12),(size_t)4); + sigjmp_buf *jmp_ctxt_4 = get_jmp_ctxt(); + __e_acsl_store_block((void *)(& jmp_ctxt_4),(size_t)8); + __e_acsl_full_init((void *)(& jmp_ctxt_4)); + __e_acsl_full_init((void *)(& tmp_12)); + tmp_12 = sigsetjmp(*jmp_ctxt_4,1); + switch (tmp_12) { + case 0: + { + set_handler(); + __gen_e_acsl_strcat((char *)0,__gen_e_acsl_literal_string_2); + test_successful(); + break; + } + case 1: { + signal_eval(0,1,__gen_e_acsl_literal_string_9); + break; + } + case 2: { + signal_eval(1,1,__gen_e_acsl_literal_string_9); + break; + } + default: + { + printf(__gen_e_acsl_literal_string_4,__gen_e_acsl_literal_string_9); + __gen_e_acsl_exit(3); + } + } + __e_acsl_delete_block((void *)(& tmp_12)); + __e_acsl_delete_block((void *)(& jmp_ctxt_4)); + } + { + int tmp_14; + __e_acsl_store_block((void *)(& tmp_14),(size_t)4); + sigjmp_buf *jmp_ctxt_5 = get_jmp_ctxt(); + __e_acsl_store_block((void *)(& jmp_ctxt_5),(size_t)8); + __e_acsl_full_init((void *)(& jmp_ctxt_5)); + __e_acsl_full_init((void *)(& tmp_14)); + tmp_14 = sigsetjmp(*jmp_ctxt_5,1); + switch (tmp_14) { + case 0: + { + set_handler(); + __gen_e_acsl_strcat(dest1,(char const *)0); + test_successful(); + break; + } + case 1: { + signal_eval(0,1,__gen_e_acsl_literal_string_10); + break; + } + case 2: { + signal_eval(1,1,__gen_e_acsl_literal_string_10); + break; + } + default: + { + printf(__gen_e_acsl_literal_string_4, + __gen_e_acsl_literal_string_10); + __gen_e_acsl_exit(3); + } + } + __e_acsl_delete_block((void *)(& tmp_14)); + __e_acsl_delete_block((void *)(& jmp_ctxt_5)); + } + { + int tmp_16; + __e_acsl_store_block((void *)(& tmp_16),(size_t)4); + sigjmp_buf *jmp_ctxt_6 = get_jmp_ctxt(); + __e_acsl_store_block((void *)(& jmp_ctxt_6),(size_t)8); + __e_acsl_full_init((void *)(& jmp_ctxt_6)); + __e_acsl_full_init((void *)(& tmp_16)); + tmp_16 = sigsetjmp(*jmp_ctxt_6,1); + switch (tmp_16) { + case 0: + { + set_handler(); + __gen_e_acsl_strcat(const_str,(char const *)const_str); + test_successful(); + break; + } + case 1: { + signal_eval(0,1,__gen_e_acsl_literal_string_11); + break; + } + case 2: { + signal_eval(1,1,__gen_e_acsl_literal_string_11); + break; + } + default: + { + printf(__gen_e_acsl_literal_string_4, + __gen_e_acsl_literal_string_11); + __gen_e_acsl_exit(3); + } + } + __e_acsl_delete_block((void *)(& tmp_16)); + __e_acsl_delete_block((void *)(& jmp_ctxt_6)); + } + { + int tmp_18; + __e_acsl_store_block((void *)(& tmp_18),(size_t)4); + sigjmp_buf *jmp_ctxt_7 = get_jmp_ctxt(); + __e_acsl_store_block((void *)(& jmp_ctxt_7),(size_t)8); + __e_acsl_full_init((void *)(& jmp_ctxt_7)); + __e_acsl_full_init((void *)(& tmp_18)); + tmp_18 = sigsetjmp(*jmp_ctxt_7,1); + switch (tmp_18) { + case 0: + { + set_handler(); + __gen_e_acsl_strcat(pd1,(char const *)pd1); + test_successful(); + break; + } + case 1: { + signal_eval(0,1,__gen_e_acsl_literal_string_12); + break; + } + case 2: { + signal_eval(1,1,__gen_e_acsl_literal_string_12); + break; + } + default: + { + printf(__gen_e_acsl_literal_string_4, + __gen_e_acsl_literal_string_12); + __gen_e_acsl_exit(3); + } + } + __e_acsl_delete_block((void *)(& tmp_18)); + __e_acsl_delete_block((void *)(& jmp_ctxt_7)); + } + { + int tmp_20; + __e_acsl_store_block((void *)(& tmp_20),(size_t)4); + sigjmp_buf *jmp_ctxt_8 = get_jmp_ctxt(); + __e_acsl_store_block((void *)(& jmp_ctxt_8),(size_t)8); + __e_acsl_full_init((void *)(& jmp_ctxt_8)); + __e_acsl_full_init((void *)(& tmp_20)); + tmp_20 = sigsetjmp(*jmp_ctxt_8,1); + switch (tmp_20) { + case 0: + { + set_handler(); + __gen_e_acsl_strcat(pd1 + 3,(char const *)pd1); + test_successful(); + break; + } + case 1: { + signal_eval(0,1,__gen_e_acsl_literal_string_13); + break; + } + case 2: { + signal_eval(1,1,__gen_e_acsl_literal_string_13); + break; + } + default: + { + printf(__gen_e_acsl_literal_string_4, + __gen_e_acsl_literal_string_13); + __gen_e_acsl_exit(3); + } + } + __e_acsl_delete_block((void *)(& tmp_20)); + __e_acsl_delete_block((void *)(& jmp_ctxt_8)); + } + { + int tmp_22; + __e_acsl_store_block((void *)(& tmp_22),(size_t)4); + sigjmp_buf *jmp_ctxt_9 = get_jmp_ctxt(); + __e_acsl_store_block((void *)(& jmp_ctxt_9),(size_t)8); + __e_acsl_full_init((void *)(& jmp_ctxt_9)); + __e_acsl_full_init((void *)(& tmp_22)); + tmp_22 = sigsetjmp(*jmp_ctxt_9,1); + switch (tmp_22) { + case 0: + { + set_handler(); + __gen_e_acsl_strcat(pd4 + 4,(char const *)pd4); + test_successful(); + break; + } + case 1: { + signal_eval(0,1,__gen_e_acsl_literal_string_14); + break; + } + case 2: { + signal_eval(1,1,__gen_e_acsl_literal_string_14); + break; + } + default: + { + printf(__gen_e_acsl_literal_string_4, + __gen_e_acsl_literal_string_14); + __gen_e_acsl_exit(3); + } + } + __e_acsl_delete_block((void *)(& tmp_22)); + __e_acsl_delete_block((void *)(& jmp_ctxt_9)); + } + { + int tmp_24; + __e_acsl_store_block((void *)(& tmp_24),(size_t)4); + sigjmp_buf *jmp_ctxt_10 = get_jmp_ctxt(); + __e_acsl_store_block((void *)(& jmp_ctxt_10),(size_t)8); + __e_acsl_full_init((void *)(& jmp_ctxt_10)); + __e_acsl_full_init((void *)(& tmp_24)); + tmp_24 = sigsetjmp(*jmp_ctxt_10,1); + switch (tmp_24) { + case 0: + { + set_handler(); + __e_acsl_initialize((void *)(pd4 + 5),sizeof(char)); + *(pd4 + 5) = (char)'\000'; + __gen_e_acsl_strcat(pd4 + 5,(char const *)pd4); + test_successful(); + break; + } + case 1: { + signal_eval(0,0,__gen_e_acsl_literal_string_15); + break; + } + case 2: { + signal_eval(1,0,__gen_e_acsl_literal_string_15); + break; + } + default: + { + printf(__gen_e_acsl_literal_string_4, + __gen_e_acsl_literal_string_15); + __gen_e_acsl_exit(3); + } + } + __e_acsl_delete_block((void *)(& tmp_24)); + __e_acsl_delete_block((void *)(& jmp_ctxt_10)); + __e_acsl_delete_block((void *)(& pd4)); + __e_acsl_delete_block((void *)(& pd3)); + __e_acsl_delete_block((void *)(& pd2)); + __e_acsl_delete_block((void *)(& pd1)); + __e_acsl_delete_block((void *)(dest4)); + __e_acsl_delete_block((void *)(dest3)); + __e_acsl_delete_block((void *)(dest2)); + __e_acsl_delete_block((void *)(dest1)); + } + } + { + char dest1_0[9] = + {(char)'d', (char)'c', (char)'b', (char)'a', (char)'\000'}; + __e_acsl_store_block((void *)(dest1_0),(size_t)9); + __e_acsl_full_init((void *)(& dest1_0)); + char dest2_0[8] = + {(char)'d', (char)'c', (char)'b', (char)'a', (char)'\000'}; + __e_acsl_store_block((void *)(dest2_0),(size_t)8); + __e_acsl_full_init((void *)(& dest2_0)); + char dest3_0[5] = + {(char)'-', (char)'-', (char)'-', (char)'-', (char)'\000'}; + __e_acsl_store_block((void *)(dest3_0),(size_t)5); + __e_acsl_full_init((void *)(& dest3_0)); + char dest4_0[10] = + {(char)'d', (char)'c', (char)'b', (char)'a', (char)'\000'}; + __e_acsl_store_block((void *)(dest4_0),(size_t)10); + __e_acsl_full_init((void *)(& dest4_0)); + char *pd1_0 = (char *)(& dest1_0); + __e_acsl_store_block((void *)(& pd1_0),(size_t)8); + __e_acsl_full_init((void *)(& pd1_0)); + char *pd2_0 = (char *)(& dest2_0); + __e_acsl_store_block((void *)(& pd2_0),(size_t)8); + __e_acsl_full_init((void *)(& pd2_0)); + char *pd3_0 = (char *)(& dest3_0); + __e_acsl_store_block((void *)(& pd3_0),(size_t)8); + __e_acsl_full_init((void *)(& pd3_0)); + char *pd4_0 = (char *)(& dest4_0); + __e_acsl_store_block((void *)(& pd4_0),(size_t)8); + __e_acsl_full_init((void *)(& pd4_0)); + { + int tmp_26; + __e_acsl_store_block((void *)(& tmp_26),(size_t)4); + sigjmp_buf *jmp_ctxt_11 = get_jmp_ctxt(); + __e_acsl_store_block((void *)(& jmp_ctxt_11),(size_t)8); + __e_acsl_full_init((void *)(& jmp_ctxt_11)); + __e_acsl_full_init((void *)(& tmp_26)); + tmp_26 = sigsetjmp(*jmp_ctxt_11,1); + switch (tmp_26) { + case 0: + { + set_handler(); + __gen_e_acsl_strncat(dest1_0,(char const *)const_str, + (unsigned long)4); + test_successful(); + break; + } + case 1: { + signal_eval(0,0,__gen_e_acsl_literal_string_16); + break; + } + case 2: { + signal_eval(1,0,__gen_e_acsl_literal_string_16); + break; + } + default: + { + printf(__gen_e_acsl_literal_string_4, + __gen_e_acsl_literal_string_16); + __gen_e_acsl_exit(3); + } + } + __e_acsl_delete_block((void *)(& tmp_26)); + __e_acsl_delete_block((void *)(& jmp_ctxt_11)); + } + { + int tmp_28; + __e_acsl_store_block((void *)(& tmp_28),(size_t)4); + sigjmp_buf *jmp_ctxt_12 = get_jmp_ctxt(); + __e_acsl_store_block((void *)(& jmp_ctxt_12),(size_t)8); + __e_acsl_full_init((void *)(& jmp_ctxt_12)); + __e_acsl_full_init((void *)(& tmp_28)); + tmp_28 = sigsetjmp(*jmp_ctxt_12,1); + switch (tmp_28) { + case 0: + { + set_handler(); + __gen_e_acsl_strncat(dest2_0,(char const *)const_str, + (unsigned long)4); + test_successful(); + break; + } + case 1: { + signal_eval(0,1,__gen_e_acsl_literal_string_17); + break; + } + case 2: { + signal_eval(1,1,__gen_e_acsl_literal_string_17); + break; + } + default: + { + printf(__gen_e_acsl_literal_string_4, + __gen_e_acsl_literal_string_17); + __gen_e_acsl_exit(3); + } + } + __e_acsl_delete_block((void *)(& tmp_28)); + __e_acsl_delete_block((void *)(& jmp_ctxt_12)); + } + { + int tmp_30; + __e_acsl_store_block((void *)(& tmp_30),(size_t)4); + sigjmp_buf *jmp_ctxt_13 = get_jmp_ctxt(); + __e_acsl_store_block((void *)(& jmp_ctxt_13),(size_t)8); + __e_acsl_full_init((void *)(& jmp_ctxt_13)); + __e_acsl_full_init((void *)(& tmp_30)); + tmp_30 = sigsetjmp(*jmp_ctxt_13,1); + switch (tmp_30) { + case 0: + { + set_handler(); + __gen_e_acsl_strncat(unalloc_str,(char const *)const_str, + (unsigned long)1); + test_successful(); + break; + } + case 1: { + signal_eval(0,1,__gen_e_acsl_literal_string_18); + break; + } + case 2: { + signal_eval(1,1,__gen_e_acsl_literal_string_18); + break; + } + default: + { + printf(__gen_e_acsl_literal_string_4, + __gen_e_acsl_literal_string_18); + __gen_e_acsl_exit(3); + } + } + __e_acsl_delete_block((void *)(& tmp_30)); + __e_acsl_delete_block((void *)(& jmp_ctxt_13)); + } + { + int tmp_32; + __e_acsl_store_block((void *)(& tmp_32),(size_t)4); + sigjmp_buf *jmp_ctxt_14 = get_jmp_ctxt(); + __e_acsl_store_block((void *)(& jmp_ctxt_14),(size_t)8); + __e_acsl_full_init((void *)(& jmp_ctxt_14)); + __e_acsl_full_init((void *)(& tmp_32)); + tmp_32 = sigsetjmp(*jmp_ctxt_14,1); + switch (tmp_32) { + case 0: + { + set_handler(); + __gen_e_acsl_strncat(dest2_0,(char const *)unalloc_str, + (unsigned long)1); + test_successful(); + break; + } + case 1: { + signal_eval(0,1,__gen_e_acsl_literal_string_19); + break; + } + case 2: { + signal_eval(1,1,__gen_e_acsl_literal_string_19); + break; + } + default: + { + printf(__gen_e_acsl_literal_string_4, + __gen_e_acsl_literal_string_19); + __gen_e_acsl_exit(3); + } + } + __e_acsl_delete_block((void *)(& tmp_32)); + __e_acsl_delete_block((void *)(& jmp_ctxt_14)); + } + { + int tmp_34; + __e_acsl_store_block((void *)(& tmp_34),(size_t)4); + sigjmp_buf *jmp_ctxt_15 = get_jmp_ctxt(); + __e_acsl_store_block((void *)(& jmp_ctxt_15),(size_t)8); + __e_acsl_full_init((void *)(& jmp_ctxt_15)); + __e_acsl_full_init((void *)(& tmp_34)); + tmp_34 = sigsetjmp(*jmp_ctxt_15,1); + switch (tmp_34) { + case 0: + { + set_handler(); + __gen_e_acsl_strncat((char *)0,(char const *)const_str, + (unsigned long)1); + test_successful(); + break; + } + case 1: { + signal_eval(0,1,__gen_e_acsl_literal_string_20); + break; + } + case 2: { + signal_eval(1,1,__gen_e_acsl_literal_string_20); + break; + } + default: + { + printf(__gen_e_acsl_literal_string_4, + __gen_e_acsl_literal_string_20); + __gen_e_acsl_exit(3); + } + } + __e_acsl_delete_block((void *)(& tmp_34)); + __e_acsl_delete_block((void *)(& jmp_ctxt_15)); + } + { + int tmp_36; + __e_acsl_store_block((void *)(& tmp_36),(size_t)4); + sigjmp_buf *jmp_ctxt_16 = get_jmp_ctxt(); + __e_acsl_store_block((void *)(& jmp_ctxt_16),(size_t)8); + __e_acsl_full_init((void *)(& jmp_ctxt_16)); + __e_acsl_full_init((void *)(& tmp_36)); + tmp_36 = sigsetjmp(*jmp_ctxt_16,1); + switch (tmp_36) { + case 0: + { + set_handler(); + __gen_e_acsl_strncat(dest2_0,(char const *)0,(unsigned long)1); + test_successful(); + break; + } + case 1: { + signal_eval(0,1,__gen_e_acsl_literal_string_21); + break; + } + case 2: { + signal_eval(1,1,__gen_e_acsl_literal_string_21); + break; + } + default: + { + printf(__gen_e_acsl_literal_string_4, + __gen_e_acsl_literal_string_21); + __gen_e_acsl_exit(3); + } + } + __e_acsl_delete_block((void *)(& tmp_36)); + __e_acsl_delete_block((void *)(& jmp_ctxt_16)); + } + { + int tmp_38; + __e_acsl_store_block((void *)(& tmp_38),(size_t)4); + sigjmp_buf *jmp_ctxt_17 = get_jmp_ctxt(); + __e_acsl_store_block((void *)(& jmp_ctxt_17),(size_t)8); + __e_acsl_full_init((void *)(& jmp_ctxt_17)); + __e_acsl_full_init((void *)(& tmp_38)); + tmp_38 = sigsetjmp(*jmp_ctxt_17,1); + switch (tmp_38) { + case 0: + { + set_handler(); + __gen_e_acsl_strncat(const_str,(char const *)const_str, + (unsigned long)1); + test_successful(); + break; + } + case 1: { + signal_eval(0,1,__gen_e_acsl_literal_string_22); + break; + } + case 2: { + signal_eval(1,1,__gen_e_acsl_literal_string_22); + break; + } + default: + { + printf(__gen_e_acsl_literal_string_4, + __gen_e_acsl_literal_string_22); + __gen_e_acsl_exit(3); + } + } + __e_acsl_delete_block((void *)(& tmp_38)); + __e_acsl_delete_block((void *)(& jmp_ctxt_17)); + } + { + int tmp_40; + __e_acsl_store_block((void *)(& tmp_40),(size_t)4); + sigjmp_buf *jmp_ctxt_18 = get_jmp_ctxt(); + __e_acsl_store_block((void *)(& jmp_ctxt_18),(size_t)8); + __e_acsl_full_init((void *)(& jmp_ctxt_18)); + __e_acsl_full_init((void *)(& tmp_40)); + tmp_40 = sigsetjmp(*jmp_ctxt_18,1); + switch (tmp_40) { + case 0: + { + set_handler(); + __gen_e_acsl_strncat(pd1_0,(char const *)pd1_0,(unsigned long)1); + test_successful(); + break; + } + case 1: { + signal_eval(0,1,__gen_e_acsl_literal_string_23); + break; + } + case 2: { + signal_eval(1,1,__gen_e_acsl_literal_string_23); + break; + } + default: + { + printf(__gen_e_acsl_literal_string_4, + __gen_e_acsl_literal_string_23); + __gen_e_acsl_exit(3); + } + } + __e_acsl_delete_block((void *)(& tmp_40)); + __e_acsl_delete_block((void *)(& jmp_ctxt_18)); + } + { + int tmp_42; + __e_acsl_store_block((void *)(& tmp_42),(size_t)4); + sigjmp_buf *jmp_ctxt_19 = get_jmp_ctxt(); + __e_acsl_store_block((void *)(& jmp_ctxt_19),(size_t)8); + __e_acsl_full_init((void *)(& jmp_ctxt_19)); + __e_acsl_full_init((void *)(& tmp_42)); + tmp_42 = sigsetjmp(*jmp_ctxt_19,1); + switch (tmp_42) { + case 0: + { + set_handler(); + __gen_e_acsl_strncat(pd1_0 + 3,(char const *)pd1_0, + (unsigned long)5); + test_successful(); + break; + } + case 1: { + signal_eval(0,1,__gen_e_acsl_literal_string_24); + break; + } + case 2: { + signal_eval(1,1,__gen_e_acsl_literal_string_24); + break; + } + default: + { + printf(__gen_e_acsl_literal_string_4, + __gen_e_acsl_literal_string_24); + __gen_e_acsl_exit(3); + } + } + __e_acsl_delete_block((void *)(& tmp_42)); + __e_acsl_delete_block((void *)(& jmp_ctxt_19)); + } + { + int tmp_44; + __e_acsl_store_block((void *)(& tmp_44),(size_t)4); + sigjmp_buf *jmp_ctxt_20 = get_jmp_ctxt(); + __e_acsl_store_block((void *)(& jmp_ctxt_20),(size_t)8); + __e_acsl_full_init((void *)(& jmp_ctxt_20)); + __e_acsl_full_init((void *)(& tmp_44)); + tmp_44 = sigsetjmp(*jmp_ctxt_20,1); + switch (tmp_44) { + case 0: + { + set_handler(); + __gen_e_acsl_strncat(pd4_0 + 4,(char const *)pd4_0, + (unsigned long)5); + test_successful(); + break; + } + case 1: { + signal_eval(0,1,__gen_e_acsl_literal_string_25); + break; + } + case 2: { + signal_eval(1,1,__gen_e_acsl_literal_string_25); + break; + } + default: + { + printf(__gen_e_acsl_literal_string_4, + __gen_e_acsl_literal_string_25); + __gen_e_acsl_exit(3); + } + } + __e_acsl_delete_block((void *)(& tmp_44)); + __e_acsl_delete_block((void *)(& jmp_ctxt_20)); + __e_acsl_delete_block((void *)(& pd4_0)); + __e_acsl_delete_block((void *)(& pd3_0)); + __e_acsl_delete_block((void *)(& pd2_0)); + __e_acsl_delete_block((void *)(& pd1_0)); + __e_acsl_delete_block((void *)(dest4_0)); + __e_acsl_delete_block((void *)(dest3_0)); + __e_acsl_delete_block((void *)(dest2_0)); + __e_acsl_delete_block((void *)(dest1_0)); + } + } + __e_acsl_full_init((void *)(& __retres)); + __retres = 0; + __e_acsl_delete_block((void *)(& argv)); + __e_acsl_delete_block((void *)(& argc)); + __e_acsl_delete_block((void *)(& __fc_p_strerror)); + __e_acsl_delete_block((void *)(strerror)); + __e_acsl_delete_block((void *)(& __fc_strtok_ptr)); + __e_acsl_delete_block((void *)(& __fc_p_fopen)); + __e_acsl_delete_block((void *)(__fc_fopen)); + __e_acsl_delete_block((void *)(& __fc_rand_max)); + __e_acsl_delete_block((void *)(& empty_str)); + __e_acsl_delete_block((void *)(& _barrier)); + __e_acsl_delete_block((void *)(& unalloc_str)); + __e_acsl_delete_block((void *)(& const_str)); + __e_acsl_delete_block((void *)(& __retres)); + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/builtin/oracle_ci/gen_strcmp.c b/src/plugins/e-acsl/tests/builtin/oracle_ci/gen_strcmp.c new file mode 100644 index 0000000000000000000000000000000000000000..6f6f697e18a8f9b2be86d320185e08b36d897296 --- /dev/null +++ b/src/plugins/e-acsl/tests/builtin/oracle_ci/gen_strcmp.c @@ -0,0 +1,1410 @@ +/* Generated by Frama-C */ +#include "setjmp.h" +#include "signal.h" +#include "stdio.h" +#include "stdlib.h" +#include "string.h" +char *__gen_e_acsl_literal_string_28; +char *__gen_e_acsl_literal_string_27; +char *__gen_e_acsl_literal_string_26; +char *__gen_e_acsl_literal_string_25; +char *__gen_e_acsl_literal_string_24; +char *__gen_e_acsl_literal_string_23; +char *__gen_e_acsl_literal_string_22; +char *__gen_e_acsl_literal_string_21; +char *__gen_e_acsl_literal_string_19; +char *__gen_e_acsl_literal_string_18; +char *__gen_e_acsl_literal_string_17; +char *__gen_e_acsl_literal_string_16; +char *__gen_e_acsl_literal_string_15; +char *__gen_e_acsl_literal_string_14; +char *__gen_e_acsl_literal_string_13; +char *__gen_e_acsl_literal_string_12; +char *__gen_e_acsl_literal_string_11; +char *__gen_e_acsl_literal_string_10; +char *__gen_e_acsl_literal_string_9; +char *__gen_e_acsl_literal_string_8; +char *__gen_e_acsl_literal_string_7; +char *__gen_e_acsl_literal_string_6; +char *__gen_e_acsl_literal_string_5; +char *__gen_e_acsl_literal_string_3; +char *__gen_e_acsl_literal_string_2; +char *__gen_e_acsl_literal_string_20; +char *__gen_e_acsl_literal_string; +char *__gen_e_acsl_literal_string_4; +extern int __e_acsl_sound_verdict; + +__inline static void fail_ncomp(int cond, char *fmt, int l, int r) +{ + __e_acsl_store_block((void *)(& r),(size_t)4); + __e_acsl_store_block((void *)(& l),(size_t)4); + __e_acsl_store_block((void *)(& fmt),(size_t)8); + __e_acsl_store_block((void *)(& cond),(size_t)4); + if (cond) { + fprintf(stderr,(char const *)fmt,l,r); + __gen_e_acsl_abort(); + } + __e_acsl_delete_block((void *)(& r)); + __e_acsl_delete_block((void *)(& l)); + __e_acsl_delete_block((void *)(& fmt)); + __e_acsl_delete_block((void *)(& cond)); + return; +} + +void __e_acsl_globals_init(void) +{ + static char __e_acsl_already_run = 0; + if (! __e_acsl_already_run) { + __e_acsl_already_run = 1; + __gen_e_acsl_literal_string_28 = "tests/builtin/strcmp.c:87"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_28, + sizeof("tests/builtin/strcmp.c:87")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_28); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_28); + __gen_e_acsl_literal_string_27 = "tests/builtin/strcmp.c:85"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_27, + sizeof("tests/builtin/strcmp.c:85")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_27); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_27); + __gen_e_acsl_literal_string_26 = "tests/builtin/strcmp.c:84"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_26, + sizeof("tests/builtin/strcmp.c:84")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_26); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_26); + __gen_e_acsl_literal_string_25 = "tests/builtin/strcmp.c:82"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_25, + sizeof("tests/builtin/strcmp.c:82")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_25); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_25); + __gen_e_acsl_literal_string_24 = "tests/builtin/strcmp.c:79"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_24, + sizeof("tests/builtin/strcmp.c:79")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_24); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_24); + __gen_e_acsl_literal_string_23 = "tests/builtin/strcmp.c:77"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_23, + sizeof("tests/builtin/strcmp.c:77")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_23); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_23); + __gen_e_acsl_literal_string_22 = "tests/builtin/strcmp.c:75"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_22, + sizeof("tests/builtin/strcmp.c:75")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_22); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_22); + __gen_e_acsl_literal_string_21 = "tests/builtin/strcmp.c:73"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_21, + sizeof("tests/builtin/strcmp.c:73")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_21); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_21); + __gen_e_acsl_literal_string_19 = "tests/builtin/strcmp.c:69"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_19, + sizeof("tests/builtin/strcmp.c:69")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_19); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_19); + __gen_e_acsl_literal_string_18 = "tests/builtin/strcmp.c:68"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_18, + sizeof("tests/builtin/strcmp.c:68")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_18); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_18); + __gen_e_acsl_literal_string_17 = "tests/builtin/strcmp.c:66"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_17, + sizeof("tests/builtin/strcmp.c:66")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_17); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_17); + __gen_e_acsl_literal_string_16 = "tests/builtin/strcmp.c:65"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_16, + sizeof("tests/builtin/strcmp.c:65")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_16); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_16); + __gen_e_acsl_literal_string_15 = "tests/builtin/strcmp.c:64"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_15, + sizeof("tests/builtin/strcmp.c:64")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_15); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_15); + __gen_e_acsl_literal_string_14 = "tests/builtin/strcmp.c:52"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_14, + sizeof("tests/builtin/strcmp.c:52")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_14); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_14); + __gen_e_acsl_literal_string_13 = "tests/builtin/strcmp.c:51"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_13, + sizeof("tests/builtin/strcmp.c:51")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_13); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_13); + __gen_e_acsl_literal_string_12 = "tests/builtin/strcmp.c:46"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_12, + sizeof("tests/builtin/strcmp.c:46")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_12); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_12); + __gen_e_acsl_literal_string_11 = "tests/builtin/strcmp.c:45"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_11, + sizeof("tests/builtin/strcmp.c:45")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_11); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_11); + __gen_e_acsl_literal_string_10 = "tests/builtin/strcmp.c:43"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_10, + sizeof("tests/builtin/strcmp.c:43")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_10); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_10); + __gen_e_acsl_literal_string_9 = "tests/builtin/strcmp.c:41"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_9, + sizeof("tests/builtin/strcmp.c:41")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_9); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_9); + __gen_e_acsl_literal_string_8 = "tests/builtin/strcmp.c:39"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_8, + sizeof("tests/builtin/strcmp.c:39")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_8); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_8); + __gen_e_acsl_literal_string_7 = "tests/builtin/strcmp.c:37"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_7, + sizeof("tests/builtin/strcmp.c:37")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_7); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_7); + __gen_e_acsl_literal_string_6 = "tests/builtin/strcmp.c:34"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_6, + sizeof("tests/builtin/strcmp.c:34")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_6); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_6); + __gen_e_acsl_literal_string_5 = "tests/builtin/strcmp.c:33"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_5, + sizeof("tests/builtin/strcmp.c:33")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_5); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_5); + __gen_e_acsl_literal_string_3 = "tests/builtin/strcmp.c:32"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_3, + sizeof("tests/builtin/strcmp.c:32")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_3); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_3); + __gen_e_acsl_literal_string_2 = "comparison failure: %d == %d\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_2, + sizeof("comparison failure: %d == %d\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_2); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_2); + __gen_e_acsl_literal_string_20 = "comparison failure: %d != %d\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_20, + sizeof("comparison failure: %d != %d\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_20); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_20); + __gen_e_acsl_literal_string = "abc"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string,sizeof("abc")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string); + __gen_e_acsl_literal_string_4 = "FAIL: Unexpected value return from test at %s\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_4, + sizeof("FAIL: Unexpected value return from test at %s\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_4); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_4); + __e_acsl_store_block((void *)(& __gen_e_acsl_strdup),(size_t)1); + __e_acsl_full_init((void *)(& __gen_e_acsl_strdup)); + __e_acsl_store_block((void *)(& __gen_e_acsl_strncmp),(size_t)1); + __e_acsl_full_init((void *)(& __gen_e_acsl_strncmp)); + __e_acsl_store_block((void *)(& __gen_e_acsl_strcmp),(size_t)1); + __e_acsl_full_init((void *)(& __gen_e_acsl_strcmp)); + __e_acsl_store_block((void *)(& __gen_e_acsl_exit),(size_t)1); + __e_acsl_full_init((void *)(& __gen_e_acsl_exit)); + __e_acsl_store_block((void *)(& __gen_e_acsl_abort),(size_t)1); + __e_acsl_full_init((void *)(& __gen_e_acsl_abort)); + __e_acsl_store_block((void *)(& fail_ncomp),(size_t)1); + __e_acsl_full_init((void *)(& fail_ncomp)); + __e_acsl_store_block((void *)(& __fc_p_strerror),(size_t)8); + __e_acsl_full_init((void *)(& __fc_p_strerror)); + __e_acsl_store_block((void *)(strerror),(size_t)64); + __e_acsl_full_init((void *)(& strerror)); + __e_acsl_store_block((void *)(& __fc_strtok_ptr),(size_t)8); + __e_acsl_full_init((void *)(& __fc_strtok_ptr)); + __e_acsl_store_block((void *)(& __fc_p_fopen),(size_t)8); + __e_acsl_full_init((void *)(& __fc_p_fopen)); + __e_acsl_store_block((void *)(__fc_fopen),(size_t)128); + __e_acsl_full_init((void *)(& __fc_fopen)); + __e_acsl_store_block((void *)(& stderr),(size_t)8); + __e_acsl_full_init((void *)(& stderr)); + __e_acsl_store_block((void *)(& __fc_p_random48_counter),(size_t)8); + __e_acsl_full_init((void *)(& __fc_p_random48_counter)); + __e_acsl_store_block((void *)(random48_counter),(size_t)6); + __e_acsl_full_init((void *)(& random48_counter)); + __e_acsl_store_block((void *)(& __fc_random48_init),(size_t)4); + __e_acsl_full_init((void *)(& __fc_random48_init)); + __e_acsl_store_block((void *)(& __fc_rand_max),(size_t)8); + __e_acsl_full_init((void *)(& __fc_rand_max)); + } + return; +} + +int main(int argc, char const **argv) +{ + int __retres; + int res; + __e_acsl_memory_init(& argc,(char ***)(& argv),(size_t)8); + __e_acsl_globals_init(); + __e_acsl_store_block((void *)(& res),(size_t)4); + __e_acsl_store_block((void *)(& __retres),(size_t)4); + char const *cl = __gen_e_acsl_literal_string; + __e_acsl_store_block((void *)(& cl),(size_t)8); + __e_acsl_full_init((void *)(& cl)); + char const *cr = __gen_e_acsl_literal_string; + __e_acsl_store_block((void *)(& cr),(size_t)8); + __e_acsl_full_init((void *)(& cr)); + char al[4] = {(char)'a', (char)'b', (char)'c', (char)'\000'}; + __e_acsl_store_block((void *)(al),(size_t)4); + __e_acsl_full_init((void *)(& al)); + char ar[4] = {(char)'a', (char)'b', (char)'c', (char)'\000'}; + __e_acsl_store_block((void *)(ar),(size_t)4); + __e_acsl_full_init((void *)(& ar)); + char *dl = __gen_e_acsl_strdup(__gen_e_acsl_literal_string); + __e_acsl_store_block((void *)(& dl),(size_t)8); + __e_acsl_full_init((void *)(& dl)); + char *dr = __gen_e_acsl_strdup(__gen_e_acsl_literal_string); + __e_acsl_store_block((void *)(& dr),(size_t)8); + __e_acsl_full_init((void *)(& dr)); + { + int tmp_2; + __e_acsl_store_block((void *)(& tmp_2),(size_t)4); + sigjmp_buf *jmp_ctxt = get_jmp_ctxt(); + __e_acsl_store_block((void *)(& jmp_ctxt),(size_t)8); + __e_acsl_full_init((void *)(& jmp_ctxt)); + __e_acsl_full_init((void *)(& tmp_2)); + /*@ assert Eva: mem_access: \valid_read(jmp_ctxt); */ + tmp_2 = sigsetjmp(*jmp_ctxt,1); + switch (tmp_2) { + case 0: + { + int tmp_3; + int tmp_4; + __e_acsl_store_block((void *)(& tmp_4),(size_t)4); + __e_acsl_store_block((void *)(& tmp_3),(size_t)4); + set_handler(); + __e_acsl_full_init((void *)(& tmp_3)); + tmp_3 = __gen_e_acsl_strcmp(cl,cr); + __e_acsl_full_init((void *)(& tmp_4)); + tmp_4 = __gen_e_acsl_strcmp(cl,cr); + fail_ncomp(tmp_4 != 0,(char *)__gen_e_acsl_literal_string_2,tmp_3,0); + test_successful(); + __e_acsl_delete_block((void *)(& tmp_3)); + __e_acsl_delete_block((void *)(& tmp_4)); + break; + __e_acsl_delete_block((void *)(& tmp_4)); + __e_acsl_delete_block((void *)(& tmp_3)); + } + case 1: { + signal_eval(0,0,__gen_e_acsl_literal_string_3); + break; + } + case 2: { + signal_eval(1,0,__gen_e_acsl_literal_string_3); + break; + } + default: + { + printf(__gen_e_acsl_literal_string_4,__gen_e_acsl_literal_string_3); + __gen_e_acsl_exit(3); + } + } + __e_acsl_delete_block((void *)(& tmp_2)); + __e_acsl_delete_block((void *)(& jmp_ctxt)); + } + { + int tmp_6; + __e_acsl_store_block((void *)(& tmp_6),(size_t)4); + sigjmp_buf *jmp_ctxt_0 = get_jmp_ctxt(); + __e_acsl_store_block((void *)(& jmp_ctxt_0),(size_t)8); + __e_acsl_full_init((void *)(& jmp_ctxt_0)); + __e_acsl_full_init((void *)(& tmp_6)); + tmp_6 = sigsetjmp(*jmp_ctxt_0,1); + switch (tmp_6) { + case 0: + { + int tmp_7; + int tmp_8; + __e_acsl_store_block((void *)(& tmp_8),(size_t)4); + __e_acsl_store_block((void *)(& tmp_7),(size_t)4); + set_handler(); + __e_acsl_full_init((void *)(& tmp_7)); + tmp_7 = __gen_e_acsl_strcmp((char const *)(al),(char const *)(ar)); + __e_acsl_full_init((void *)(& tmp_8)); + tmp_8 = __gen_e_acsl_strcmp((char const *)(al),(char const *)(ar)); + fail_ncomp(tmp_8 != 0,(char *)__gen_e_acsl_literal_string_2,tmp_7,0); + test_successful(); + __e_acsl_delete_block((void *)(& tmp_7)); + __e_acsl_delete_block((void *)(& tmp_8)); + break; + __e_acsl_delete_block((void *)(& tmp_8)); + __e_acsl_delete_block((void *)(& tmp_7)); + } + case 1: { + signal_eval(0,0,__gen_e_acsl_literal_string_5); + break; + } + case 2: { + signal_eval(1,0,__gen_e_acsl_literal_string_5); + break; + } + default: + { + printf(__gen_e_acsl_literal_string_4,__gen_e_acsl_literal_string_5); + __gen_e_acsl_exit(3); + } + } + __e_acsl_delete_block((void *)(& tmp_6)); + __e_acsl_delete_block((void *)(& jmp_ctxt_0)); + } + { + int tmp_10; + __e_acsl_store_block((void *)(& tmp_10),(size_t)4); + sigjmp_buf *jmp_ctxt_1 = get_jmp_ctxt(); + __e_acsl_store_block((void *)(& jmp_ctxt_1),(size_t)8); + __e_acsl_full_init((void *)(& jmp_ctxt_1)); + __e_acsl_full_init((void *)(& tmp_10)); + tmp_10 = sigsetjmp(*jmp_ctxt_1,1); + switch (tmp_10) { + case 0: + { + int tmp_11; + int tmp_12; + __e_acsl_store_block((void *)(& tmp_12),(size_t)4); + __e_acsl_store_block((void *)(& tmp_11),(size_t)4); + set_handler(); + __e_acsl_full_init((void *)(& tmp_11)); + tmp_11 = __gen_e_acsl_strcmp((char const *)dl,(char const *)dr); + __e_acsl_full_init((void *)(& tmp_12)); + tmp_12 = __gen_e_acsl_strcmp((char const *)dl,(char const *)dr); + fail_ncomp(tmp_12 != 0,(char *)__gen_e_acsl_literal_string_2,tmp_11, + 0); + test_successful(); + __e_acsl_delete_block((void *)(& tmp_11)); + __e_acsl_delete_block((void *)(& tmp_12)); + break; + __e_acsl_delete_block((void *)(& tmp_12)); + __e_acsl_delete_block((void *)(& tmp_11)); + } + case 1: { + signal_eval(0,0,__gen_e_acsl_literal_string_6); + break; + } + case 2: { + signal_eval(1,0,__gen_e_acsl_literal_string_6); + break; + } + default: + { + printf(__gen_e_acsl_literal_string_4,__gen_e_acsl_literal_string_6); + __gen_e_acsl_exit(3); + } + } + __e_acsl_delete_block((void *)(& tmp_10)); + __e_acsl_delete_block((void *)(& jmp_ctxt_1)); + } + __e_acsl_initialize((void *)(& al[3]),sizeof(char)); + al[3] = (char)'a'; + { + int tmp_14; + __e_acsl_store_block((void *)(& tmp_14),(size_t)4); + sigjmp_buf *jmp_ctxt_2 = get_jmp_ctxt(); + __e_acsl_store_block((void *)(& jmp_ctxt_2),(size_t)8); + __e_acsl_full_init((void *)(& jmp_ctxt_2)); + __e_acsl_full_init((void *)(& tmp_14)); + tmp_14 = sigsetjmp(*jmp_ctxt_2,1); + switch (tmp_14) { + case 0: + { + int tmp_15; + int tmp_16; + __e_acsl_store_block((void *)(& tmp_16),(size_t)4); + __e_acsl_store_block((void *)(& tmp_15),(size_t)4); + set_handler(); + __e_acsl_full_init((void *)(& tmp_15)); + tmp_15 = __gen_e_acsl_strcmp((char const *)(al),(char const *)(ar)); + __e_acsl_full_init((void *)(& tmp_16)); + tmp_16 = __gen_e_acsl_strcmp((char const *)(al),(char const *)(ar)); + fail_ncomp(tmp_16 != 0,(char *)__gen_e_acsl_literal_string_2,tmp_15, + 0); + test_successful(); + __e_acsl_delete_block((void *)(& tmp_15)); + __e_acsl_delete_block((void *)(& tmp_16)); + break; + __e_acsl_delete_block((void *)(& tmp_16)); + __e_acsl_delete_block((void *)(& tmp_15)); + } + case 1: { + signal_eval(0,1,__gen_e_acsl_literal_string_7); + break; + } + case 2: { + signal_eval(1,1,__gen_e_acsl_literal_string_7); + break; + } + default: + { + printf(__gen_e_acsl_literal_string_4,__gen_e_acsl_literal_string_7); + __gen_e_acsl_exit(3); + } + } + __e_acsl_delete_block((void *)(& tmp_14)); + __e_acsl_delete_block((void *)(& jmp_ctxt_2)); + } + __e_acsl_initialize((void *)(& ar[3]),sizeof(char)); + ar[3] = (char)'a'; + __e_acsl_initialize((void *)(& al[3]),sizeof(char)); + al[3] = (char)0; + { + int tmp_18; + __e_acsl_store_block((void *)(& tmp_18),(size_t)4); + sigjmp_buf *jmp_ctxt_3 = get_jmp_ctxt(); + __e_acsl_store_block((void *)(& jmp_ctxt_3),(size_t)8); + __e_acsl_full_init((void *)(& jmp_ctxt_3)); + __e_acsl_full_init((void *)(& tmp_18)); + tmp_18 = sigsetjmp(*jmp_ctxt_3,1); + switch (tmp_18) { + case 0: + { + int tmp_19; + int tmp_20; + __e_acsl_store_block((void *)(& tmp_20),(size_t)4); + __e_acsl_store_block((void *)(& tmp_19),(size_t)4); + set_handler(); + __e_acsl_full_init((void *)(& tmp_19)); + tmp_19 = __gen_e_acsl_strcmp((char const *)(al),(char const *)(ar)); + __e_acsl_full_init((void *)(& tmp_20)); + tmp_20 = __gen_e_acsl_strcmp((char const *)(al),(char const *)(ar)); + fail_ncomp(tmp_20 != 0,(char *)__gen_e_acsl_literal_string_2,tmp_19, + 0); + test_successful(); + __e_acsl_delete_block((void *)(& tmp_19)); + __e_acsl_delete_block((void *)(& tmp_20)); + break; + __e_acsl_delete_block((void *)(& tmp_20)); + __e_acsl_delete_block((void *)(& tmp_19)); + } + case 1: { + signal_eval(0,1,__gen_e_acsl_literal_string_8); + break; + } + case 2: { + signal_eval(1,1,__gen_e_acsl_literal_string_8); + break; + } + default: + { + printf(__gen_e_acsl_literal_string_4,__gen_e_acsl_literal_string_8); + __gen_e_acsl_exit(3); + } + } + __e_acsl_delete_block((void *)(& tmp_18)); + __e_acsl_delete_block((void *)(& jmp_ctxt_3)); + } + __e_acsl_initialize((void *)(dl + 3),sizeof(char)); + *(dl + 3) = (char)'a'; + { + int tmp_22; + __e_acsl_store_block((void *)(& tmp_22),(size_t)4); + sigjmp_buf *jmp_ctxt_4 = get_jmp_ctxt(); + __e_acsl_store_block((void *)(& jmp_ctxt_4),(size_t)8); + __e_acsl_full_init((void *)(& jmp_ctxt_4)); + __e_acsl_full_init((void *)(& tmp_22)); + tmp_22 = sigsetjmp(*jmp_ctxt_4,1); + switch (tmp_22) { + case 0: + { + int tmp_23; + int tmp_24; + __e_acsl_store_block((void *)(& tmp_24),(size_t)4); + __e_acsl_store_block((void *)(& tmp_23),(size_t)4); + set_handler(); + __e_acsl_full_init((void *)(& tmp_23)); + tmp_23 = __gen_e_acsl_strcmp((char const *)dl,(char const *)dr); + __e_acsl_full_init((void *)(& tmp_24)); + tmp_24 = __gen_e_acsl_strcmp((char const *)dl,(char const *)dr); + fail_ncomp(tmp_24 != 0,(char *)__gen_e_acsl_literal_string_2,tmp_23, + 0); + test_successful(); + __e_acsl_delete_block((void *)(& tmp_23)); + __e_acsl_delete_block((void *)(& tmp_24)); + break; + __e_acsl_delete_block((void *)(& tmp_24)); + __e_acsl_delete_block((void *)(& tmp_23)); + } + case 1: { + signal_eval(0,1,__gen_e_acsl_literal_string_9); + break; + } + case 2: { + signal_eval(1,1,__gen_e_acsl_literal_string_9); + break; + } + default: + { + printf(__gen_e_acsl_literal_string_4,__gen_e_acsl_literal_string_9); + __gen_e_acsl_exit(3); + } + } + __e_acsl_delete_block((void *)(& tmp_22)); + __e_acsl_delete_block((void *)(& jmp_ctxt_4)); + } + __e_acsl_initialize((void *)(dr + 3),sizeof(char)); + *(dr + 3) = (char)'a'; + __e_acsl_initialize((void *)(dl + 3),sizeof(char)); + *(dl + 3) = (char)0; + { + int tmp_26; + __e_acsl_store_block((void *)(& tmp_26),(size_t)4); + sigjmp_buf *jmp_ctxt_5 = get_jmp_ctxt(); + __e_acsl_store_block((void *)(& jmp_ctxt_5),(size_t)8); + __e_acsl_full_init((void *)(& jmp_ctxt_5)); + __e_acsl_full_init((void *)(& tmp_26)); + tmp_26 = sigsetjmp(*jmp_ctxt_5,1); + switch (tmp_26) { + case 0: + { + int tmp_27; + int tmp_28; + __e_acsl_store_block((void *)(& tmp_28),(size_t)4); + __e_acsl_store_block((void *)(& tmp_27),(size_t)4); + set_handler(); + __e_acsl_full_init((void *)(& tmp_27)); + tmp_27 = __gen_e_acsl_strcmp((char const *)dl,(char const *)dr); + __e_acsl_full_init((void *)(& tmp_28)); + tmp_28 = __gen_e_acsl_strcmp((char const *)dl,(char const *)dr); + fail_ncomp(tmp_28 != 0,(char *)__gen_e_acsl_literal_string_2,tmp_27, + 0); + test_successful(); + __e_acsl_delete_block((void *)(& tmp_27)); + __e_acsl_delete_block((void *)(& tmp_28)); + break; + __e_acsl_delete_block((void *)(& tmp_28)); + __e_acsl_delete_block((void *)(& tmp_27)); + } + case 1: { + signal_eval(0,1,__gen_e_acsl_literal_string_10); + break; + } + case 2: { + signal_eval(1,1,__gen_e_acsl_literal_string_10); + break; + } + default: + { + printf(__gen_e_acsl_literal_string_4,__gen_e_acsl_literal_string_10); + __gen_e_acsl_exit(3); + } + } + __e_acsl_delete_block((void *)(& tmp_26)); + __e_acsl_delete_block((void *)(& jmp_ctxt_5)); + } + { + int tmp_30; + __e_acsl_store_block((void *)(& tmp_30),(size_t)4); + sigjmp_buf *jmp_ctxt_6 = get_jmp_ctxt(); + __e_acsl_store_block((void *)(& jmp_ctxt_6),(size_t)8); + __e_acsl_full_init((void *)(& jmp_ctxt_6)); + __e_acsl_full_init((void *)(& tmp_30)); + tmp_30 = sigsetjmp(*jmp_ctxt_6,1); + switch (tmp_30) { + case 0: + { + int tmp_31; + int tmp_32; + __e_acsl_store_block((void *)(& tmp_32),(size_t)4); + __e_acsl_store_block((void *)(& tmp_31),(size_t)4); + set_handler(); + __e_acsl_full_init((void *)(& tmp_31)); + tmp_31 = __gen_e_acsl_strcmp((char const *)dl,(char const *)0); + __e_acsl_full_init((void *)(& tmp_32)); + tmp_32 = __gen_e_acsl_strcmp((char const *)dl,(char const *)0); + fail_ncomp(tmp_32 != 0,(char *)__gen_e_acsl_literal_string_2,tmp_31, + 0); + test_successful(); + __e_acsl_delete_block((void *)(& tmp_31)); + __e_acsl_delete_block((void *)(& tmp_32)); + break; + __e_acsl_delete_block((void *)(& tmp_32)); + __e_acsl_delete_block((void *)(& tmp_31)); + } + case 1: { + signal_eval(0,1,__gen_e_acsl_literal_string_11); + break; + } + case 2: { + signal_eval(1,1,__gen_e_acsl_literal_string_11); + break; + } + default: + { + printf(__gen_e_acsl_literal_string_4,__gen_e_acsl_literal_string_11); + __gen_e_acsl_exit(3); + } + } + __e_acsl_delete_block((void *)(& tmp_30)); + __e_acsl_delete_block((void *)(& jmp_ctxt_6)); + } + { + int tmp_34; + __e_acsl_store_block((void *)(& tmp_34),(size_t)4); + sigjmp_buf *jmp_ctxt_7 = get_jmp_ctxt(); + __e_acsl_store_block((void *)(& jmp_ctxt_7),(size_t)8); + __e_acsl_full_init((void *)(& jmp_ctxt_7)); + __e_acsl_full_init((void *)(& tmp_34)); + tmp_34 = sigsetjmp(*jmp_ctxt_7,1); + switch (tmp_34) { + case 0: + { + int tmp_35; + int tmp_36; + __e_acsl_store_block((void *)(& tmp_36),(size_t)4); + __e_acsl_store_block((void *)(& tmp_35),(size_t)4); + set_handler(); + __e_acsl_full_init((void *)(& tmp_35)); + tmp_35 = __gen_e_acsl_strcmp((char const *)0,(char const *)dr); + __e_acsl_full_init((void *)(& tmp_36)); + tmp_36 = __gen_e_acsl_strcmp((char const *)0,(char const *)dr); + fail_ncomp(tmp_36 != 0,(char *)__gen_e_acsl_literal_string_2,tmp_35, + 0); + test_successful(); + __e_acsl_delete_block((void *)(& tmp_35)); + __e_acsl_delete_block((void *)(& tmp_36)); + break; + __e_acsl_delete_block((void *)(& tmp_36)); + __e_acsl_delete_block((void *)(& tmp_35)); + } + case 1: { + signal_eval(0,1,__gen_e_acsl_literal_string_12); + break; + } + case 2: { + signal_eval(1,1,__gen_e_acsl_literal_string_12); + break; + } + default: + { + printf(__gen_e_acsl_literal_string_4,__gen_e_acsl_literal_string_12); + __gen_e_acsl_exit(3); + } + } + __e_acsl_delete_block((void *)(& tmp_34)); + __e_acsl_delete_block((void *)(& jmp_ctxt_7)); + } + free((void *)dl); + free((void *)dr); + { + int tmp_38; + __e_acsl_store_block((void *)(& tmp_38),(size_t)4); + sigjmp_buf *jmp_ctxt_8 = get_jmp_ctxt(); + __e_acsl_store_block((void *)(& jmp_ctxt_8),(size_t)8); + __e_acsl_full_init((void *)(& jmp_ctxt_8)); + __e_acsl_full_init((void *)(& tmp_38)); + tmp_38 = sigsetjmp(*jmp_ctxt_8,1); + switch (tmp_38) { + case 0: + { + int tmp_39; + int tmp_40; + __e_acsl_store_block((void *)(& tmp_40),(size_t)4); + __e_acsl_store_block((void *)(& tmp_39),(size_t)4); + set_handler(); + __e_acsl_full_init((void *)(& tmp_39)); + tmp_39 = __gen_e_acsl_strcmp((char const *)dl,(char const *)(ar)); + __e_acsl_full_init((void *)(& tmp_40)); + tmp_40 = __gen_e_acsl_strcmp((char const *)dl,(char const *)(ar)); + fail_ncomp(tmp_40 != 0,(char *)__gen_e_acsl_literal_string_2,tmp_39, + 0); + test_successful(); + __e_acsl_delete_block((void *)(& tmp_39)); + __e_acsl_delete_block((void *)(& tmp_40)); + break; + __e_acsl_delete_block((void *)(& tmp_40)); + __e_acsl_delete_block((void *)(& tmp_39)); + } + case 1: { + signal_eval(0,1,__gen_e_acsl_literal_string_13); + break; + } + case 2: { + signal_eval(1,1,__gen_e_acsl_literal_string_13); + break; + } + default: + { + printf(__gen_e_acsl_literal_string_4,__gen_e_acsl_literal_string_13); + __gen_e_acsl_exit(3); + } + } + __e_acsl_delete_block((void *)(& tmp_38)); + __e_acsl_delete_block((void *)(& jmp_ctxt_8)); + } + { + int tmp_42; + __e_acsl_store_block((void *)(& tmp_42),(size_t)4); + sigjmp_buf *jmp_ctxt_9 = get_jmp_ctxt(); + __e_acsl_store_block((void *)(& jmp_ctxt_9),(size_t)8); + __e_acsl_full_init((void *)(& jmp_ctxt_9)); + __e_acsl_full_init((void *)(& tmp_42)); + tmp_42 = sigsetjmp(*jmp_ctxt_9,1); + switch (tmp_42) { + case 0: + { + int tmp_43; + int tmp_44; + __e_acsl_store_block((void *)(& tmp_44),(size_t)4); + __e_acsl_store_block((void *)(& tmp_43),(size_t)4); + set_handler(); + __e_acsl_full_init((void *)(& tmp_43)); + tmp_43 = __gen_e_acsl_strcmp((char const *)(al),(char const *)dr); + __e_acsl_full_init((void *)(& tmp_44)); + tmp_44 = __gen_e_acsl_strcmp((char const *)(al),(char const *)dr); + fail_ncomp(tmp_44 != 0,(char *)__gen_e_acsl_literal_string_2,tmp_43, + 0); + test_successful(); + __e_acsl_delete_block((void *)(& tmp_43)); + __e_acsl_delete_block((void *)(& tmp_44)); + break; + __e_acsl_delete_block((void *)(& tmp_44)); + __e_acsl_delete_block((void *)(& tmp_43)); + } + case 1: { + signal_eval(0,1,__gen_e_acsl_literal_string_14); + break; + } + case 2: { + signal_eval(1,1,__gen_e_acsl_literal_string_14); + break; + } + default: + { + printf(__gen_e_acsl_literal_string_4,__gen_e_acsl_literal_string_14); + __gen_e_acsl_exit(3); + } + } + __e_acsl_delete_block((void *)(& tmp_42)); + __e_acsl_delete_block((void *)(& jmp_ctxt_9)); + } + __e_acsl_full_init((void *)(& dl)); + dl = __gen_e_acsl_strdup(__gen_e_acsl_literal_string); + __e_acsl_full_init((void *)(& dr)); + dr = __gen_e_acsl_strdup(__gen_e_acsl_literal_string); + char nal[4] = {(char)'a', (char)'b', (char)'c', (char)'\000'}; + __e_acsl_store_block((void *)(nal),(size_t)4); + __e_acsl_full_init((void *)(& nal)); + char nar[4] = {(char)'a', (char)'b', (char)'c', (char)'\000'}; + __e_acsl_store_block((void *)(nar),(size_t)4); + __e_acsl_full_init((void *)(& nar)); + { + int tmp_46; + __e_acsl_store_block((void *)(& tmp_46),(size_t)4); + sigjmp_buf *jmp_ctxt_10 = get_jmp_ctxt(); + __e_acsl_store_block((void *)(& jmp_ctxt_10),(size_t)8); + __e_acsl_full_init((void *)(& jmp_ctxt_10)); + __e_acsl_full_init((void *)(& tmp_46)); + tmp_46 = sigsetjmp(*jmp_ctxt_10,1); + switch (tmp_46) { + case 0: + { + int tmp_47; + int tmp_48; + __e_acsl_store_block((void *)(& tmp_48),(size_t)4); + __e_acsl_store_block((void *)(& tmp_47),(size_t)4); + set_handler(); + __e_acsl_full_init((void *)(& tmp_47)); + tmp_47 = __gen_e_acsl_strncmp(cl,cr,(unsigned long)3); + __e_acsl_full_init((void *)(& tmp_48)); + tmp_48 = __gen_e_acsl_strncmp(cl,cr,(unsigned long)3); + fail_ncomp(tmp_48 != 0,(char *)__gen_e_acsl_literal_string_2,tmp_47, + 0); + test_successful(); + __e_acsl_delete_block((void *)(& tmp_47)); + __e_acsl_delete_block((void *)(& tmp_48)); + break; + __e_acsl_delete_block((void *)(& tmp_48)); + __e_acsl_delete_block((void *)(& tmp_47)); + } + case 1: { + signal_eval(0,0,__gen_e_acsl_literal_string_15); + break; + } + case 2: { + signal_eval(1,0,__gen_e_acsl_literal_string_15); + break; + } + default: + { + printf(__gen_e_acsl_literal_string_4,__gen_e_acsl_literal_string_15); + __gen_e_acsl_exit(3); + } + } + __e_acsl_delete_block((void *)(& tmp_46)); + __e_acsl_delete_block((void *)(& jmp_ctxt_10)); + } + { + int tmp_50; + __e_acsl_store_block((void *)(& tmp_50),(size_t)4); + sigjmp_buf *jmp_ctxt_11 = get_jmp_ctxt(); + __e_acsl_store_block((void *)(& jmp_ctxt_11),(size_t)8); + __e_acsl_full_init((void *)(& jmp_ctxt_11)); + __e_acsl_full_init((void *)(& tmp_50)); + tmp_50 = sigsetjmp(*jmp_ctxt_11,1); + switch (tmp_50) { + case 0: + { + int tmp_51; + int tmp_52; + __e_acsl_store_block((void *)(& tmp_52),(size_t)4); + __e_acsl_store_block((void *)(& tmp_51),(size_t)4); + set_handler(); + __e_acsl_full_init((void *)(& tmp_51)); + tmp_51 = __gen_e_acsl_strncmp((char const *)(nal), + (char const *)(nar),(unsigned long)3); + __e_acsl_full_init((void *)(& tmp_52)); + tmp_52 = __gen_e_acsl_strncmp((char const *)(nal), + (char const *)(nar),(unsigned long)3); + fail_ncomp(tmp_52 != 0,(char *)__gen_e_acsl_literal_string_2,tmp_51, + 0); + test_successful(); + __e_acsl_delete_block((void *)(& tmp_51)); + __e_acsl_delete_block((void *)(& tmp_52)); + break; + __e_acsl_delete_block((void *)(& tmp_52)); + __e_acsl_delete_block((void *)(& tmp_51)); + } + case 1: { + signal_eval(0,0,__gen_e_acsl_literal_string_16); + break; + } + case 2: { + signal_eval(1,0,__gen_e_acsl_literal_string_16); + break; + } + default: + { + printf(__gen_e_acsl_literal_string_4,__gen_e_acsl_literal_string_16); + __gen_e_acsl_exit(3); + } + } + __e_acsl_delete_block((void *)(& tmp_50)); + __e_acsl_delete_block((void *)(& jmp_ctxt_11)); + } + { + int tmp_54; + __e_acsl_store_block((void *)(& tmp_54),(size_t)4); + sigjmp_buf *jmp_ctxt_12 = get_jmp_ctxt(); + __e_acsl_store_block((void *)(& jmp_ctxt_12),(size_t)8); + __e_acsl_full_init((void *)(& jmp_ctxt_12)); + __e_acsl_full_init((void *)(& tmp_54)); + tmp_54 = sigsetjmp(*jmp_ctxt_12,1); + switch (tmp_54) { + case 0: + { + int tmp_55; + int tmp_56; + __e_acsl_store_block((void *)(& tmp_56),(size_t)4); + __e_acsl_store_block((void *)(& tmp_55),(size_t)4); + set_handler(); + __e_acsl_full_init((void *)(& tmp_55)); + tmp_55 = __gen_e_acsl_strncmp((char const *)dl,(char const *)dr, + (unsigned long)3); + __e_acsl_full_init((void *)(& tmp_56)); + tmp_56 = __gen_e_acsl_strncmp((char const *)dl,(char const *)dr, + (unsigned long)3); + fail_ncomp(tmp_56 != 0,(char *)__gen_e_acsl_literal_string_2,tmp_55, + 0); + test_successful(); + __e_acsl_delete_block((void *)(& tmp_55)); + __e_acsl_delete_block((void *)(& tmp_56)); + break; + __e_acsl_delete_block((void *)(& tmp_56)); + __e_acsl_delete_block((void *)(& tmp_55)); + } + case 1: { + signal_eval(0,0,__gen_e_acsl_literal_string_17); + break; + } + case 2: { + signal_eval(1,0,__gen_e_acsl_literal_string_17); + break; + } + default: + { + printf(__gen_e_acsl_literal_string_4,__gen_e_acsl_literal_string_17); + __gen_e_acsl_exit(3); + } + } + __e_acsl_delete_block((void *)(& tmp_54)); + __e_acsl_delete_block((void *)(& jmp_ctxt_12)); + } + { + int tmp_58; + __e_acsl_store_block((void *)(& tmp_58),(size_t)4); + sigjmp_buf *jmp_ctxt_13 = get_jmp_ctxt(); + __e_acsl_store_block((void *)(& jmp_ctxt_13),(size_t)8); + __e_acsl_full_init((void *)(& jmp_ctxt_13)); + __e_acsl_full_init((void *)(& tmp_58)); + tmp_58 = sigsetjmp(*jmp_ctxt_13,1); + switch (tmp_58) { + case 0: + { + int tmp_59; + int tmp_60; + __e_acsl_store_block((void *)(& tmp_60),(size_t)4); + __e_acsl_store_block((void *)(& tmp_59),(size_t)4); + set_handler(); + __e_acsl_full_init((void *)(& tmp_59)); + tmp_59 = __gen_e_acsl_strncmp((char const *)(nal), + (char const *)(nar),(unsigned long)6); + __e_acsl_full_init((void *)(& tmp_60)); + tmp_60 = __gen_e_acsl_strncmp((char const *)(nal), + (char const *)(nar),(unsigned long)6); + fail_ncomp(tmp_60 != 0,(char *)__gen_e_acsl_literal_string_2,tmp_59, + 0); + test_successful(); + __e_acsl_delete_block((void *)(& tmp_59)); + __e_acsl_delete_block((void *)(& tmp_60)); + break; + __e_acsl_delete_block((void *)(& tmp_60)); + __e_acsl_delete_block((void *)(& tmp_59)); + } + case 1: { + signal_eval(0,0,__gen_e_acsl_literal_string_18); + break; + } + case 2: { + signal_eval(1,0,__gen_e_acsl_literal_string_18); + break; + } + default: + { + printf(__gen_e_acsl_literal_string_4,__gen_e_acsl_literal_string_18); + __gen_e_acsl_exit(3); + } + } + __e_acsl_delete_block((void *)(& tmp_58)); + __e_acsl_delete_block((void *)(& jmp_ctxt_13)); + } + { + int tmp_62; + __e_acsl_store_block((void *)(& tmp_62),(size_t)4); + sigjmp_buf *jmp_ctxt_14 = get_jmp_ctxt(); + __e_acsl_store_block((void *)(& jmp_ctxt_14),(size_t)8); + __e_acsl_full_init((void *)(& jmp_ctxt_14)); + __e_acsl_full_init((void *)(& tmp_62)); + tmp_62 = sigsetjmp(*jmp_ctxt_14,1); + switch (tmp_62) { + case 0: + { + int tmp_63; + int tmp_64; + __e_acsl_store_block((void *)(& tmp_64),(size_t)4); + __e_acsl_store_block((void *)(& tmp_63),(size_t)4); + set_handler(); + __e_acsl_full_init((void *)(& tmp_63)); + tmp_63 = __gen_e_acsl_strncmp((char const *)dl,(char const *)dr, + (unsigned long)6); + __e_acsl_full_init((void *)(& tmp_64)); + tmp_64 = __gen_e_acsl_strncmp((char const *)dl,(char const *)dr, + (unsigned long)6); + fail_ncomp(tmp_64 != 0,(char *)__gen_e_acsl_literal_string_2,tmp_63, + 0); + test_successful(); + __e_acsl_delete_block((void *)(& tmp_63)); + __e_acsl_delete_block((void *)(& tmp_64)); + break; + __e_acsl_delete_block((void *)(& tmp_64)); + __e_acsl_delete_block((void *)(& tmp_63)); + } + case 1: { + signal_eval(0,0,__gen_e_acsl_literal_string_19); + break; + } + case 2: { + signal_eval(1,0,__gen_e_acsl_literal_string_19); + break; + } + default: + { + printf(__gen_e_acsl_literal_string_4,__gen_e_acsl_literal_string_19); + __gen_e_acsl_exit(3); + } + } + __e_acsl_delete_block((void *)(& tmp_62)); + __e_acsl_delete_block((void *)(& jmp_ctxt_14)); + } + __e_acsl_initialize((void *)(& nal[3]),sizeof(char)); + nal[3] = (char)'d'; + { + int tmp_66; + __e_acsl_store_block((void *)(& tmp_66),(size_t)4); + sigjmp_buf *jmp_ctxt_15 = get_jmp_ctxt(); + __e_acsl_store_block((void *)(& jmp_ctxt_15),(size_t)8); + __e_acsl_full_init((void *)(& jmp_ctxt_15)); + __e_acsl_full_init((void *)(& tmp_66)); + tmp_66 = sigsetjmp(*jmp_ctxt_15,1); + switch (tmp_66) { + case 0: + { + int tmp_67; + int tmp_68; + __e_acsl_store_block((void *)(& tmp_68),(size_t)4); + __e_acsl_store_block((void *)(& tmp_67),(size_t)4); + set_handler(); + __e_acsl_full_init((void *)(& tmp_67)); + tmp_67 = __gen_e_acsl_strncmp((char const *)(nal), + (char const *)(nar),(unsigned long)4); + __e_acsl_full_init((void *)(& tmp_68)); + tmp_68 = __gen_e_acsl_strncmp((char const *)(nal), + (char const *)(nar),(unsigned long)4); + fail_ncomp(tmp_68 == 0,(char *)__gen_e_acsl_literal_string_20,tmp_67, + 0); + test_successful(); + __e_acsl_delete_block((void *)(& tmp_67)); + __e_acsl_delete_block((void *)(& tmp_68)); + break; + __e_acsl_delete_block((void *)(& tmp_68)); + __e_acsl_delete_block((void *)(& tmp_67)); + } + case 1: { + signal_eval(0,0,__gen_e_acsl_literal_string_21); + break; + } + case 2: { + signal_eval(1,0,__gen_e_acsl_literal_string_21); + break; + } + default: + { + printf(__gen_e_acsl_literal_string_4,__gen_e_acsl_literal_string_21); + __gen_e_acsl_exit(3); + } + } + __e_acsl_delete_block((void *)(& tmp_66)); + __e_acsl_delete_block((void *)(& jmp_ctxt_15)); + } + __e_acsl_initialize((void *)(& nar[3]),sizeof(char)); + nar[3] = (char)'d'; + __e_acsl_initialize((void *)(& nal[3]),sizeof(char)); + nal[3] = (char)0; + { + int tmp_70; + __e_acsl_store_block((void *)(& tmp_70),(size_t)4); + sigjmp_buf *jmp_ctxt_16 = get_jmp_ctxt(); + __e_acsl_store_block((void *)(& jmp_ctxt_16),(size_t)8); + __e_acsl_full_init((void *)(& jmp_ctxt_16)); + __e_acsl_full_init((void *)(& tmp_70)); + tmp_70 = sigsetjmp(*jmp_ctxt_16,1); + switch (tmp_70) { + case 0: + { + int tmp_71; + int tmp_72; + __e_acsl_store_block((void *)(& tmp_72),(size_t)4); + __e_acsl_store_block((void *)(& tmp_71),(size_t)4); + set_handler(); + __e_acsl_full_init((void *)(& tmp_71)); + tmp_71 = __gen_e_acsl_strncmp((char const *)(nal), + (char const *)(nar),(unsigned long)4); + __e_acsl_full_init((void *)(& tmp_72)); + tmp_72 = __gen_e_acsl_strncmp((char const *)(nal), + (char const *)(nar),(unsigned long)4); + fail_ncomp(tmp_72 == 0,(char *)__gen_e_acsl_literal_string_20,tmp_71, + 0); + test_successful(); + __e_acsl_delete_block((void *)(& tmp_71)); + __e_acsl_delete_block((void *)(& tmp_72)); + break; + __e_acsl_delete_block((void *)(& tmp_72)); + __e_acsl_delete_block((void *)(& tmp_71)); + } + case 1: { + signal_eval(0,0,__gen_e_acsl_literal_string_22); + break; + } + case 2: { + signal_eval(1,0,__gen_e_acsl_literal_string_22); + break; + } + default: + { + printf(__gen_e_acsl_literal_string_4,__gen_e_acsl_literal_string_22); + __gen_e_acsl_exit(3); + } + } + __e_acsl_delete_block((void *)(& tmp_70)); + __e_acsl_delete_block((void *)(& jmp_ctxt_16)); + } + __e_acsl_initialize((void *)(dl + 3),sizeof(char)); + *(dl + 3) = (char)'d'; + { + int tmp_74; + __e_acsl_store_block((void *)(& tmp_74),(size_t)4); + sigjmp_buf *jmp_ctxt_17 = get_jmp_ctxt(); + __e_acsl_store_block((void *)(& jmp_ctxt_17),(size_t)8); + __e_acsl_full_init((void *)(& jmp_ctxt_17)); + __e_acsl_full_init((void *)(& tmp_74)); + tmp_74 = sigsetjmp(*jmp_ctxt_17,1); + switch (tmp_74) { + case 0: + { + int tmp_75; + int tmp_76; + __e_acsl_store_block((void *)(& tmp_76),(size_t)4); + __e_acsl_store_block((void *)(& tmp_75),(size_t)4); + set_handler(); + __e_acsl_full_init((void *)(& tmp_75)); + tmp_75 = __gen_e_acsl_strncmp((char const *)dl,(char const *)dr, + (unsigned long)4); + __e_acsl_full_init((void *)(& tmp_76)); + tmp_76 = __gen_e_acsl_strncmp((char const *)dl,(char const *)dr, + (unsigned long)4); + fail_ncomp(tmp_76 == 0,(char *)__gen_e_acsl_literal_string_20,tmp_75, + 0); + test_successful(); + __e_acsl_delete_block((void *)(& tmp_75)); + __e_acsl_delete_block((void *)(& tmp_76)); + break; + __e_acsl_delete_block((void *)(& tmp_76)); + __e_acsl_delete_block((void *)(& tmp_75)); + } + case 1: { + signal_eval(0,0,__gen_e_acsl_literal_string_23); + break; + } + case 2: { + signal_eval(1,0,__gen_e_acsl_literal_string_23); + break; + } + default: + { + printf(__gen_e_acsl_literal_string_4,__gen_e_acsl_literal_string_23); + __gen_e_acsl_exit(3); + } + } + __e_acsl_delete_block((void *)(& tmp_74)); + __e_acsl_delete_block((void *)(& jmp_ctxt_17)); + } + __e_acsl_initialize((void *)(dr + 3),sizeof(char)); + *(dr + 3) = (char)'d'; + __e_acsl_initialize((void *)(dl + 3),sizeof(char)); + *(dl + 3) = (char)0; + { + int tmp_78; + __e_acsl_store_block((void *)(& tmp_78),(size_t)4); + sigjmp_buf *jmp_ctxt_18 = get_jmp_ctxt(); + __e_acsl_store_block((void *)(& jmp_ctxt_18),(size_t)8); + __e_acsl_full_init((void *)(& jmp_ctxt_18)); + __e_acsl_full_init((void *)(& tmp_78)); + tmp_78 = sigsetjmp(*jmp_ctxt_18,1); + switch (tmp_78) { + case 0: + { + int tmp_79; + int tmp_80; + __e_acsl_store_block((void *)(& tmp_80),(size_t)4); + __e_acsl_store_block((void *)(& tmp_79),(size_t)4); + set_handler(); + __e_acsl_full_init((void *)(& tmp_79)); + tmp_79 = __gen_e_acsl_strncmp((char const *)dl,(char const *)dr, + (unsigned long)4); + __e_acsl_full_init((void *)(& tmp_80)); + tmp_80 = __gen_e_acsl_strncmp((char const *)dl,(char const *)dr, + (unsigned long)4); + fail_ncomp(tmp_80 == 0,(char *)__gen_e_acsl_literal_string_20,tmp_79, + 0); + test_successful(); + __e_acsl_delete_block((void *)(& tmp_79)); + __e_acsl_delete_block((void *)(& tmp_80)); + break; + __e_acsl_delete_block((void *)(& tmp_80)); + __e_acsl_delete_block((void *)(& tmp_79)); + } + case 1: { + signal_eval(0,0,__gen_e_acsl_literal_string_24); + break; + } + case 2: { + signal_eval(1,0,__gen_e_acsl_literal_string_24); + break; + } + default: + { + printf(__gen_e_acsl_literal_string_4,__gen_e_acsl_literal_string_24); + __gen_e_acsl_exit(3); + } + } + __e_acsl_delete_block((void *)(& tmp_78)); + __e_acsl_delete_block((void *)(& jmp_ctxt_18)); + } + { + int tmp_82; + __e_acsl_store_block((void *)(& tmp_82),(size_t)4); + sigjmp_buf *jmp_ctxt_19 = get_jmp_ctxt(); + __e_acsl_store_block((void *)(& jmp_ctxt_19),(size_t)8); + __e_acsl_full_init((void *)(& jmp_ctxt_19)); + __e_acsl_full_init((void *)(& tmp_82)); + tmp_82 = sigsetjmp(*jmp_ctxt_19,1); + switch (tmp_82) { + case 0: + { + set_handler(); + __e_acsl_full_init((void *)(& res)); + res = __gen_e_acsl_strncmp((char const *)(nal),(char const *)(nar), + (unsigned long)5); + test_successful(); + break; + } + case 1: { + signal_eval(0,1,__gen_e_acsl_literal_string_25); + break; + } + case 2: { + signal_eval(1,1,__gen_e_acsl_literal_string_25); + break; + } + default: + { + printf(__gen_e_acsl_literal_string_4,__gen_e_acsl_literal_string_25); + __gen_e_acsl_exit(3); + } + } + __e_acsl_delete_block((void *)(& tmp_82)); + __e_acsl_delete_block((void *)(& jmp_ctxt_19)); + } + __e_acsl_initialize((void *)(& nal[3]),sizeof(char)); + nal[3] = (char)'d'; + __e_acsl_initialize((void *)(& nar[3]),sizeof(char)); + nar[3] = (char)0; + { + int tmp_84; + __e_acsl_store_block((void *)(& tmp_84),(size_t)4); + sigjmp_buf *jmp_ctxt_20 = get_jmp_ctxt(); + __e_acsl_store_block((void *)(& jmp_ctxt_20),(size_t)8); + __e_acsl_full_init((void *)(& jmp_ctxt_20)); + __e_acsl_full_init((void *)(& tmp_84)); + tmp_84 = sigsetjmp(*jmp_ctxt_20,1); + switch (tmp_84) { + case 0: + { + set_handler(); + __e_acsl_full_init((void *)(& res)); + res = __gen_e_acsl_strncmp((char const *)(al),(char const *)(ar), + (unsigned long)5); + test_successful(); + break; + } + case 1: { + signal_eval(0,1,__gen_e_acsl_literal_string_26); + break; + } + case 2: { + signal_eval(1,1,__gen_e_acsl_literal_string_26); + break; + } + default: + { + printf(__gen_e_acsl_literal_string_4,__gen_e_acsl_literal_string_26); + __gen_e_acsl_exit(3); + } + } + __e_acsl_delete_block((void *)(& tmp_84)); + __e_acsl_delete_block((void *)(& jmp_ctxt_20)); + } + { + int tmp_86; + __e_acsl_store_block((void *)(& tmp_86),(size_t)4); + sigjmp_buf *jmp_ctxt_21 = get_jmp_ctxt(); + __e_acsl_store_block((void *)(& jmp_ctxt_21),(size_t)8); + __e_acsl_full_init((void *)(& jmp_ctxt_21)); + __e_acsl_full_init((void *)(& tmp_86)); + tmp_86 = sigsetjmp(*jmp_ctxt_21,1); + switch (tmp_86) { + case 0: + { + set_handler(); + __e_acsl_full_init((void *)(& res)); + res = __gen_e_acsl_strncmp((char const *)dl,(char const *)dr, + (unsigned long)5); + test_successful(); + break; + } + case 1: { + signal_eval(0,1,__gen_e_acsl_literal_string_27); + break; + } + case 2: { + signal_eval(1,1,__gen_e_acsl_literal_string_27); + break; + } + default: + { + printf(__gen_e_acsl_literal_string_4,__gen_e_acsl_literal_string_27); + __gen_e_acsl_exit(3); + } + } + __e_acsl_delete_block((void *)(& tmp_86)); + __e_acsl_delete_block((void *)(& jmp_ctxt_21)); + } + __e_acsl_initialize((void *)(dl + 3),sizeof(char)); + *(dl + 3) = (char)'d'; + __e_acsl_initialize((void *)(dr + 3),sizeof(char)); + *(dr + 3) = (char)0; + { + int tmp_88; + __e_acsl_store_block((void *)(& tmp_88),(size_t)4); + sigjmp_buf *jmp_ctxt_22 = get_jmp_ctxt(); + __e_acsl_store_block((void *)(& jmp_ctxt_22),(size_t)8); + __e_acsl_full_init((void *)(& jmp_ctxt_22)); + __e_acsl_full_init((void *)(& tmp_88)); + tmp_88 = sigsetjmp(*jmp_ctxt_22,1); + switch (tmp_88) { + case 0: + { + set_handler(); + __e_acsl_full_init((void *)(& res)); + res = __gen_e_acsl_strncmp((char const *)dl,(char const *)dr, + (unsigned long)5); + test_successful(); + break; + } + case 1: { + signal_eval(0,1,__gen_e_acsl_literal_string_28); + break; + } + case 2: { + signal_eval(1,1,__gen_e_acsl_literal_string_28); + break; + } + default: + { + printf(__gen_e_acsl_literal_string_4,__gen_e_acsl_literal_string_28); + __gen_e_acsl_exit(3); + } + } + __e_acsl_delete_block((void *)(& tmp_88)); + __e_acsl_delete_block((void *)(& jmp_ctxt_22)); + } + free((void *)dl); + free((void *)dr); + __e_acsl_full_init((void *)(& __retres)); + __retres = 0; + __e_acsl_delete_block((void *)(& argv)); + __e_acsl_delete_block((void *)(& argc)); + __e_acsl_delete_block((void *)(& fail_ncomp)); + __e_acsl_delete_block((void *)(& __fc_p_strerror)); + __e_acsl_delete_block((void *)(strerror)); + __e_acsl_delete_block((void *)(& __fc_strtok_ptr)); + __e_acsl_delete_block((void *)(& __fc_p_fopen)); + __e_acsl_delete_block((void *)(__fc_fopen)); + __e_acsl_delete_block((void *)(& stderr)); + __e_acsl_delete_block((void *)(& __fc_p_random48_counter)); + __e_acsl_delete_block((void *)(random48_counter)); + __e_acsl_delete_block((void *)(& __fc_random48_init)); + __e_acsl_delete_block((void *)(& __fc_rand_max)); + __e_acsl_delete_block((void *)(nar)); + __e_acsl_delete_block((void *)(nal)); + __e_acsl_delete_block((void *)(& res)); + __e_acsl_delete_block((void *)(& dr)); + __e_acsl_delete_block((void *)(& dl)); + __e_acsl_delete_block((void *)(ar)); + __e_acsl_delete_block((void *)(al)); + __e_acsl_delete_block((void *)(& cr)); + __e_acsl_delete_block((void *)(& cl)); + __e_acsl_delete_block((void *)(& __retres)); + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/builtin/oracle_ci/gen_strcpy.c b/src/plugins/e-acsl/tests/builtin/oracle_ci/gen_strcpy.c new file mode 100644 index 0000000000000000000000000000000000000000..9e679e5810106c7d8204433ef64b6aca91e092d9 --- /dev/null +++ b/src/plugins/e-acsl/tests/builtin/oracle_ci/gen_strcpy.c @@ -0,0 +1,782 @@ +/* Generated by Frama-C */ +#include "setjmp.h" +#include "signal.h" +#include "stdio.h" +#include "stdlib.h" +#include "string.h" +char *__gen_e_acsl_literal_string_20; +char *__gen_e_acsl_literal_string_19; +char *__gen_e_acsl_literal_string_18; +char *__gen_e_acsl_literal_string_17; +char *__gen_e_acsl_literal_string_16; +char *__gen_e_acsl_literal_string_15; +char *__gen_e_acsl_literal_string_14; +char *__gen_e_acsl_literal_string_13; +char *__gen_e_acsl_literal_string_12; +char *__gen_e_acsl_literal_string_11; +char *__gen_e_acsl_literal_string_10; +char *__gen_e_acsl_literal_string_9; +char *__gen_e_acsl_literal_string_8; +char *__gen_e_acsl_literal_string_7; +char *__gen_e_acsl_literal_string_6; +char *__gen_e_acsl_literal_string_5; +char *__gen_e_acsl_literal_string_2; +char *__gen_e_acsl_literal_string; +char *__gen_e_acsl_literal_string_3; +char *__gen_e_acsl_literal_string_4; +extern int __e_acsl_sound_verdict; + +void __e_acsl_globals_init(void) +{ + static char __e_acsl_already_run = 0; + if (! __e_acsl_already_run) { + __e_acsl_already_run = 1; + __gen_e_acsl_literal_string_20 = "tests/builtin/strcpy.c:39"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_20, + sizeof("tests/builtin/strcpy.c:39")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_20); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_20); + __gen_e_acsl_literal_string_19 = "tests/builtin/strcpy.c:38"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_19, + sizeof("tests/builtin/strcpy.c:38")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_19); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_19); + __gen_e_acsl_literal_string_18 = "tests/builtin/strcpy.c:37"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_18, + sizeof("tests/builtin/strcpy.c:37")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_18); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_18); + __gen_e_acsl_literal_string_17 = "tests/builtin/strcpy.c:36"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_17, + sizeof("tests/builtin/strcpy.c:36")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_17); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_17); + __gen_e_acsl_literal_string_16 = "tests/builtin/strcpy.c:35"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_16, + sizeof("tests/builtin/strcpy.c:35")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_16); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_16); + __gen_e_acsl_literal_string_15 = "tests/builtin/strcpy.c:34"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_15, + sizeof("tests/builtin/strcpy.c:34")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_15); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_15); + __gen_e_acsl_literal_string_14 = "tests/builtin/strcpy.c:33"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_14, + sizeof("tests/builtin/strcpy.c:33")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_14); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_14); + __gen_e_acsl_literal_string_13 = "tests/builtin/strcpy.c:32"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_13, + sizeof("tests/builtin/strcpy.c:32")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_13); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_13); + __gen_e_acsl_literal_string_12 = "tests/builtin/strcpy.c:29"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_12, + sizeof("tests/builtin/strcpy.c:29")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_12); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_12); + __gen_e_acsl_literal_string_11 = "tests/builtin/strcpy.c:28"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_11, + sizeof("tests/builtin/strcpy.c:28")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_11); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_11); + __gen_e_acsl_literal_string_10 = "tests/builtin/strcpy.c:27"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_10, + sizeof("tests/builtin/strcpy.c:27")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_10); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_10); + __gen_e_acsl_literal_string_9 = "tests/builtin/strcpy.c:26"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_9, + sizeof("tests/builtin/strcpy.c:26")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_9); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_9); + __gen_e_acsl_literal_string_8 = "tests/builtin/strcpy.c:25"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_8, + sizeof("tests/builtin/strcpy.c:25")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_8); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_8); + __gen_e_acsl_literal_string_7 = "tests/builtin/strcpy.c:24"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_7, + sizeof("tests/builtin/strcpy.c:24")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_7); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_7); + __gen_e_acsl_literal_string_6 = "tests/builtin/strcpy.c:23"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_6, + sizeof("tests/builtin/strcpy.c:23")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_6); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_6); + __gen_e_acsl_literal_string_5 = "tests/builtin/strcpy.c:22"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_5, + sizeof("tests/builtin/strcpy.c:22")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_5); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_5); + __gen_e_acsl_literal_string_2 = "tests/builtin/strcpy.c:21"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_2, + sizeof("tests/builtin/strcpy.c:21")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_2); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_2); + __gen_e_acsl_literal_string = "abcd"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string,sizeof("abcd")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string); + __gen_e_acsl_literal_string_3 = "FAIL: Unexpected value return from test at %s\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_3, + sizeof("FAIL: Unexpected value return from test at %s\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_3); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_3); + __gen_e_acsl_literal_string_4 = ""; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_4,sizeof("")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_4); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_4); + __e_acsl_store_block((void *)(& __gen_e_acsl_strdup),(size_t)1); + __e_acsl_full_init((void *)(& __gen_e_acsl_strdup)); + __e_acsl_store_block((void *)(& __gen_e_acsl_strncpy),(size_t)1); + __e_acsl_full_init((void *)(& __gen_e_acsl_strncpy)); + __e_acsl_store_block((void *)(& __gen_e_acsl_strcpy),(size_t)1); + __e_acsl_full_init((void *)(& __gen_e_acsl_strcpy)); + __e_acsl_store_block((void *)(& __gen_e_acsl_exit),(size_t)1); + __e_acsl_full_init((void *)(& __gen_e_acsl_exit)); + __e_acsl_store_block((void *)(& __fc_p_strerror),(size_t)8); + __e_acsl_full_init((void *)(& __fc_p_strerror)); + __e_acsl_store_block((void *)(strerror),(size_t)64); + __e_acsl_full_init((void *)(& strerror)); + __e_acsl_store_block((void *)(& __fc_strtok_ptr),(size_t)8); + __e_acsl_full_init((void *)(& __fc_strtok_ptr)); + __e_acsl_store_block((void *)(& __fc_p_fopen),(size_t)8); + __e_acsl_full_init((void *)(& __fc_p_fopen)); + __e_acsl_store_block((void *)(__fc_fopen),(size_t)128); + __e_acsl_full_init((void *)(& __fc_fopen)); + __e_acsl_store_block((void *)(& __fc_rand_max),(size_t)8); + __e_acsl_full_init((void *)(& __fc_rand_max)); + } + return; +} + +int main(int argc, char const **argv) +{ + int __retres; + __e_acsl_memory_init(& argc,(char ***)(& argv),(size_t)8); + __e_acsl_globals_init(); + __e_acsl_store_block((void *)(& __retres),(size_t)4); + char empty_str[1] = {(char)'\000'}; + __e_acsl_store_block((void *)(empty_str),(size_t)1); + __e_acsl_full_init((void *)(& empty_str)); + char *const_str = (char *)__gen_e_acsl_literal_string; + __e_acsl_store_block((void *)(& const_str),(size_t)8); + __e_acsl_full_init((void *)(& const_str)); + char *src = __gen_e_acsl_strdup(__gen_e_acsl_literal_string); + __e_acsl_store_block((void *)(& src),(size_t)8); + __e_acsl_full_init((void *)(& src)); + char *dest1 = malloc((unsigned long)5); + __e_acsl_store_block((void *)(& dest1),(size_t)8); + __e_acsl_full_init((void *)(& dest1)); + char *dest2 = malloc((unsigned long)4); + __e_acsl_store_block((void *)(& dest2),(size_t)8); + __e_acsl_full_init((void *)(& dest2)); + char dest3[256] = + {(char)'a', (char)'b', (char)'c', (char)'d', (char)'\000'}; + __e_acsl_store_block((void *)(dest3),(size_t)256); + __e_acsl_full_init((void *)(& dest3)); + size_t len = (unsigned long)0; + __e_acsl_store_block((void *)(& len),(size_t)8); + __e_acsl_full_init((void *)(& len)); + char *unalloc_str = malloc((unsigned long)5); + __e_acsl_store_block((void *)(& unalloc_str),(size_t)8); + __e_acsl_full_init((void *)(& unalloc_str)); + char *_barrier = malloc((unsigned long)1); + __e_acsl_store_block((void *)(& _barrier),(size_t)8); + __e_acsl_full_init((void *)(& _barrier)); + free((void *)unalloc_str); + { + int tmp_5; + __e_acsl_store_block((void *)(& tmp_5),(size_t)4); + sigjmp_buf *jmp_ctxt = get_jmp_ctxt(); + __e_acsl_store_block((void *)(& jmp_ctxt),(size_t)8); + __e_acsl_full_init((void *)(& jmp_ctxt)); + __e_acsl_full_init((void *)(& tmp_5)); + /*@ assert Eva: mem_access: \valid_read(jmp_ctxt); */ + tmp_5 = sigsetjmp(*jmp_ctxt,1); + switch (tmp_5) { + case 0: + { + set_handler(); + __gen_e_acsl_strcpy(dest1,(char const *)src); + test_successful(); + break; + } + case 1: { + signal_eval(0,0,__gen_e_acsl_literal_string_2); + break; + } + case 2: { + signal_eval(1,0,__gen_e_acsl_literal_string_2); + break; + } + default: + { + printf(__gen_e_acsl_literal_string_3,__gen_e_acsl_literal_string_2); + __gen_e_acsl_exit(3); + } + } + __e_acsl_delete_block((void *)(& tmp_5)); + __e_acsl_delete_block((void *)(& jmp_ctxt)); + } + { + int tmp_7; + __e_acsl_store_block((void *)(& tmp_7),(size_t)4); + sigjmp_buf *jmp_ctxt_0 = get_jmp_ctxt(); + __e_acsl_store_block((void *)(& jmp_ctxt_0),(size_t)8); + __e_acsl_full_init((void *)(& jmp_ctxt_0)); + __e_acsl_full_init((void *)(& tmp_7)); + tmp_7 = sigsetjmp(*jmp_ctxt_0,1); + switch (tmp_7) { + case 0: + { + set_handler(); + __gen_e_acsl_strcpy(empty_str,__gen_e_acsl_literal_string_4); + test_successful(); + break; + } + case 1: { + signal_eval(0,0,__gen_e_acsl_literal_string_5); + break; + } + case 2: { + signal_eval(1,0,__gen_e_acsl_literal_string_5); + break; + } + default: + { + printf(__gen_e_acsl_literal_string_3,__gen_e_acsl_literal_string_5); + __gen_e_acsl_exit(3); + } + } + __e_acsl_delete_block((void *)(& tmp_7)); + __e_acsl_delete_block((void *)(& jmp_ctxt_0)); + } + { + int tmp_9; + __e_acsl_store_block((void *)(& tmp_9),(size_t)4); + sigjmp_buf *jmp_ctxt_1 = get_jmp_ctxt(); + __e_acsl_store_block((void *)(& jmp_ctxt_1),(size_t)8); + __e_acsl_full_init((void *)(& jmp_ctxt_1)); + __e_acsl_full_init((void *)(& tmp_9)); + tmp_9 = sigsetjmp(*jmp_ctxt_1,1); + switch (tmp_9) { + case 0: + { + set_handler(); + __gen_e_acsl_strcpy(dest2,(char const *)src); + test_successful(); + break; + } + case 1: { + signal_eval(0,1,__gen_e_acsl_literal_string_6); + break; + } + case 2: { + signal_eval(1,1,__gen_e_acsl_literal_string_6); + break; + } + default: + { + printf(__gen_e_acsl_literal_string_3,__gen_e_acsl_literal_string_6); + __gen_e_acsl_exit(3); + } + } + __e_acsl_delete_block((void *)(& tmp_9)); + __e_acsl_delete_block((void *)(& jmp_ctxt_1)); + } + { + int tmp_11; + __e_acsl_store_block((void *)(& tmp_11),(size_t)4); + sigjmp_buf *jmp_ctxt_2 = get_jmp_ctxt(); + __e_acsl_store_block((void *)(& jmp_ctxt_2),(size_t)8); + __e_acsl_full_init((void *)(& jmp_ctxt_2)); + __e_acsl_full_init((void *)(& tmp_11)); + tmp_11 = sigsetjmp(*jmp_ctxt_2,1); + switch (tmp_11) { + case 0: + { + set_handler(); + __gen_e_acsl_strcpy(unalloc_str,(char const *)src); + test_successful(); + break; + } + case 1: { + signal_eval(0,1,__gen_e_acsl_literal_string_7); + break; + } + case 2: { + signal_eval(1,1,__gen_e_acsl_literal_string_7); + break; + } + default: + { + printf(__gen_e_acsl_literal_string_3,__gen_e_acsl_literal_string_7); + __gen_e_acsl_exit(3); + } + } + __e_acsl_delete_block((void *)(& tmp_11)); + __e_acsl_delete_block((void *)(& jmp_ctxt_2)); + } + { + int tmp_13; + __e_acsl_store_block((void *)(& tmp_13),(size_t)4); + sigjmp_buf *jmp_ctxt_3 = get_jmp_ctxt(); + __e_acsl_store_block((void *)(& jmp_ctxt_3),(size_t)8); + __e_acsl_full_init((void *)(& jmp_ctxt_3)); + __e_acsl_full_init((void *)(& tmp_13)); + tmp_13 = sigsetjmp(*jmp_ctxt_3,1); + switch (tmp_13) { + case 0: + { + set_handler(); + __gen_e_acsl_strcpy(const_str,(char const *)src); + test_successful(); + break; + } + case 1: { + signal_eval(0,1,__gen_e_acsl_literal_string_8); + break; + } + case 2: { + signal_eval(1,1,__gen_e_acsl_literal_string_8); + break; + } + default: + { + printf(__gen_e_acsl_literal_string_3,__gen_e_acsl_literal_string_8); + __gen_e_acsl_exit(3); + } + } + __e_acsl_delete_block((void *)(& tmp_13)); + __e_acsl_delete_block((void *)(& jmp_ctxt_3)); + } + { + int tmp_15; + __e_acsl_store_block((void *)(& tmp_15),(size_t)4); + sigjmp_buf *jmp_ctxt_4 = get_jmp_ctxt(); + __e_acsl_store_block((void *)(& jmp_ctxt_4),(size_t)8); + __e_acsl_full_init((void *)(& jmp_ctxt_4)); + __e_acsl_full_init((void *)(& tmp_15)); + tmp_15 = sigsetjmp(*jmp_ctxt_4,1); + switch (tmp_15) { + case 0: + { + set_handler(); + __gen_e_acsl_strcpy(src,(char const *)const_str); + test_successful(); + break; + } + case 1: { + signal_eval(0,0,__gen_e_acsl_literal_string_9); + break; + } + case 2: { + signal_eval(1,0,__gen_e_acsl_literal_string_9); + break; + } + default: + { + printf(__gen_e_acsl_literal_string_3,__gen_e_acsl_literal_string_9); + __gen_e_acsl_exit(3); + } + } + __e_acsl_delete_block((void *)(& tmp_15)); + __e_acsl_delete_block((void *)(& jmp_ctxt_4)); + } + { + int tmp_17; + __e_acsl_store_block((void *)(& tmp_17),(size_t)4); + sigjmp_buf *jmp_ctxt_5 = get_jmp_ctxt(); + __e_acsl_store_block((void *)(& jmp_ctxt_5),(size_t)8); + __e_acsl_full_init((void *)(& jmp_ctxt_5)); + __e_acsl_full_init((void *)(& tmp_17)); + tmp_17 = sigsetjmp(*jmp_ctxt_5,1); + switch (tmp_17) { + case 0: + { + set_handler(); + __gen_e_acsl_strcpy(src,(char const *)src); + test_successful(); + break; + } + case 1: { + signal_eval(0,1,__gen_e_acsl_literal_string_10); + break; + } + case 2: { + signal_eval(1,1,__gen_e_acsl_literal_string_10); + break; + } + default: + { + printf(__gen_e_acsl_literal_string_3,__gen_e_acsl_literal_string_10); + __gen_e_acsl_exit(3); + } + } + __e_acsl_delete_block((void *)(& tmp_17)); + __e_acsl_delete_block((void *)(& jmp_ctxt_5)); + } + { + int tmp_19; + __e_acsl_store_block((void *)(& tmp_19),(size_t)4); + sigjmp_buf *jmp_ctxt_6 = get_jmp_ctxt(); + __e_acsl_store_block((void *)(& jmp_ctxt_6),(size_t)8); + __e_acsl_full_init((void *)(& jmp_ctxt_6)); + __e_acsl_full_init((void *)(& tmp_19)); + tmp_19 = sigsetjmp(*jmp_ctxt_6,1); + switch (tmp_19) { + case 0: + { + set_handler(); + __gen_e_acsl_strcpy(& dest3[5],(char const *)(dest3)); + test_successful(); + break; + } + case 1: { + signal_eval(0,0,__gen_e_acsl_literal_string_11); + break; + } + case 2: { + signal_eval(1,0,__gen_e_acsl_literal_string_11); + break; + } + default: + { + printf(__gen_e_acsl_literal_string_3,__gen_e_acsl_literal_string_11); + __gen_e_acsl_exit(3); + } + } + __e_acsl_delete_block((void *)(& tmp_19)); + __e_acsl_delete_block((void *)(& jmp_ctxt_6)); + } + { + int tmp_21; + __e_acsl_store_block((void *)(& tmp_21),(size_t)4); + sigjmp_buf *jmp_ctxt_7 = get_jmp_ctxt(); + __e_acsl_store_block((void *)(& jmp_ctxt_7),(size_t)8); + __e_acsl_full_init((void *)(& jmp_ctxt_7)); + __e_acsl_full_init((void *)(& tmp_21)); + tmp_21 = sigsetjmp(*jmp_ctxt_7,1); + switch (tmp_21) { + case 0: + { + set_handler(); + __gen_e_acsl_strcpy(& dest3[4],(char const *)(dest3)); + test_successful(); + break; + } + case 1: { + signal_eval(0,1,__gen_e_acsl_literal_string_12); + break; + } + case 2: { + signal_eval(1,1,__gen_e_acsl_literal_string_12); + break; + } + default: + { + printf(__gen_e_acsl_literal_string_3,__gen_e_acsl_literal_string_12); + __gen_e_acsl_exit(3); + } + } + __e_acsl_delete_block((void *)(& tmp_21)); + __e_acsl_delete_block((void *)(& jmp_ctxt_7)); + } + { + int tmp_23; + __e_acsl_store_block((void *)(& tmp_23),(size_t)4); + sigjmp_buf *jmp_ctxt_8 = get_jmp_ctxt(); + __e_acsl_store_block((void *)(& jmp_ctxt_8),(size_t)8); + __e_acsl_full_init((void *)(& jmp_ctxt_8)); + __e_acsl_full_init((void *)(& tmp_23)); + tmp_23 = sigsetjmp(*jmp_ctxt_8,1); + switch (tmp_23) { + case 0: + { + set_handler(); + __gen_e_acsl_strncpy(dest1,(char const *)src,(unsigned long)5); + test_successful(); + break; + } + case 1: { + signal_eval(0,0,__gen_e_acsl_literal_string_13); + break; + } + case 2: { + signal_eval(1,0,__gen_e_acsl_literal_string_13); + break; + } + default: + { + printf(__gen_e_acsl_literal_string_3,__gen_e_acsl_literal_string_13); + __gen_e_acsl_exit(3); + } + } + __e_acsl_delete_block((void *)(& tmp_23)); + __e_acsl_delete_block((void *)(& jmp_ctxt_8)); + } + { + int tmp_25; + __e_acsl_store_block((void *)(& tmp_25),(size_t)4); + sigjmp_buf *jmp_ctxt_9 = get_jmp_ctxt(); + __e_acsl_store_block((void *)(& jmp_ctxt_9),(size_t)8); + __e_acsl_full_init((void *)(& jmp_ctxt_9)); + __e_acsl_full_init((void *)(& tmp_25)); + tmp_25 = sigsetjmp(*jmp_ctxt_9,1); + switch (tmp_25) { + case 0: + { + set_handler(); + __gen_e_acsl_strncpy(dest1,(char const *)src,(unsigned long)6); + test_successful(); + break; + } + case 1: { + signal_eval(0,1,__gen_e_acsl_literal_string_14); + break; + } + case 2: { + signal_eval(1,1,__gen_e_acsl_literal_string_14); + break; + } + default: + { + printf(__gen_e_acsl_literal_string_3,__gen_e_acsl_literal_string_14); + __gen_e_acsl_exit(3); + } + } + __e_acsl_delete_block((void *)(& tmp_25)); + __e_acsl_delete_block((void *)(& jmp_ctxt_9)); + } + { + int tmp_27; + __e_acsl_store_block((void *)(& tmp_27),(size_t)4); + sigjmp_buf *jmp_ctxt_10 = get_jmp_ctxt(); + __e_acsl_store_block((void *)(& jmp_ctxt_10),(size_t)8); + __e_acsl_full_init((void *)(& jmp_ctxt_10)); + __e_acsl_full_init((void *)(& tmp_27)); + tmp_27 = sigsetjmp(*jmp_ctxt_10,1); + switch (tmp_27) { + case 0: + { + set_handler(); + __gen_e_acsl_strncpy(unalloc_str,(char const *)src,(unsigned long)5); + test_successful(); + break; + } + case 1: { + signal_eval(0,1,__gen_e_acsl_literal_string_15); + break; + } + case 2: { + signal_eval(1,1,__gen_e_acsl_literal_string_15); + break; + } + default: + { + printf(__gen_e_acsl_literal_string_3,__gen_e_acsl_literal_string_15); + __gen_e_acsl_exit(3); + } + } + __e_acsl_delete_block((void *)(& tmp_27)); + __e_acsl_delete_block((void *)(& jmp_ctxt_10)); + } + { + int tmp_29; + __e_acsl_store_block((void *)(& tmp_29),(size_t)4); + sigjmp_buf *jmp_ctxt_11 = get_jmp_ctxt(); + __e_acsl_store_block((void *)(& jmp_ctxt_11),(size_t)8); + __e_acsl_full_init((void *)(& jmp_ctxt_11)); + __e_acsl_full_init((void *)(& tmp_29)); + tmp_29 = sigsetjmp(*jmp_ctxt_11,1); + switch (tmp_29) { + case 0: + { + set_handler(); + __gen_e_acsl_strncpy(const_str,(char const *)src,(unsigned long)5); + test_successful(); + break; + } + case 1: { + signal_eval(0,1,__gen_e_acsl_literal_string_16); + break; + } + case 2: { + signal_eval(1,1,__gen_e_acsl_literal_string_16); + break; + } + default: + { + printf(__gen_e_acsl_literal_string_3,__gen_e_acsl_literal_string_16); + __gen_e_acsl_exit(3); + } + } + __e_acsl_delete_block((void *)(& tmp_29)); + __e_acsl_delete_block((void *)(& jmp_ctxt_11)); + } + { + int tmp_31; + __e_acsl_store_block((void *)(& tmp_31),(size_t)4); + sigjmp_buf *jmp_ctxt_12 = get_jmp_ctxt(); + __e_acsl_store_block((void *)(& jmp_ctxt_12),(size_t)8); + __e_acsl_full_init((void *)(& jmp_ctxt_12)); + __e_acsl_full_init((void *)(& tmp_31)); + tmp_31 = sigsetjmp(*jmp_ctxt_12,1); + switch (tmp_31) { + case 0: + { + set_handler(); + __gen_e_acsl_strncpy(src,(char const *)const_str,(unsigned long)5); + test_successful(); + break; + } + case 1: { + signal_eval(0,0,__gen_e_acsl_literal_string_17); + break; + } + case 2: { + signal_eval(1,0,__gen_e_acsl_literal_string_17); + break; + } + default: + { + printf(__gen_e_acsl_literal_string_3,__gen_e_acsl_literal_string_17); + __gen_e_acsl_exit(3); + } + } + __e_acsl_delete_block((void *)(& tmp_31)); + __e_acsl_delete_block((void *)(& jmp_ctxt_12)); + } + { + int tmp_33; + __e_acsl_store_block((void *)(& tmp_33),(size_t)4); + sigjmp_buf *jmp_ctxt_13 = get_jmp_ctxt(); + __e_acsl_store_block((void *)(& jmp_ctxt_13),(size_t)8); + __e_acsl_full_init((void *)(& jmp_ctxt_13)); + __e_acsl_full_init((void *)(& tmp_33)); + tmp_33 = sigsetjmp(*jmp_ctxt_13,1); + switch (tmp_33) { + case 0: + { + set_handler(); + __gen_e_acsl_strncpy(src,(char const *)src,(unsigned long)5); + test_successful(); + break; + } + case 1: { + signal_eval(0,1,__gen_e_acsl_literal_string_18); + break; + } + case 2: { + signal_eval(1,1,__gen_e_acsl_literal_string_18); + break; + } + default: + { + printf(__gen_e_acsl_literal_string_3,__gen_e_acsl_literal_string_18); + __gen_e_acsl_exit(3); + } + } + __e_acsl_delete_block((void *)(& tmp_33)); + __e_acsl_delete_block((void *)(& jmp_ctxt_13)); + } + { + int tmp_35; + __e_acsl_store_block((void *)(& tmp_35),(size_t)4); + sigjmp_buf *jmp_ctxt_14 = get_jmp_ctxt(); + __e_acsl_store_block((void *)(& jmp_ctxt_14),(size_t)8); + __e_acsl_full_init((void *)(& jmp_ctxt_14)); + __e_acsl_full_init((void *)(& tmp_35)); + tmp_35 = sigsetjmp(*jmp_ctxt_14,1); + switch (tmp_35) { + case 0: + { + set_handler(); + __gen_e_acsl_strncpy(& dest3[5],(char const *)(dest3), + (unsigned long)5); + test_successful(); + break; + } + case 1: { + signal_eval(0,0,__gen_e_acsl_literal_string_19); + break; + } + case 2: { + signal_eval(1,0,__gen_e_acsl_literal_string_19); + break; + } + default: + { + printf(__gen_e_acsl_literal_string_3,__gen_e_acsl_literal_string_19); + __gen_e_acsl_exit(3); + } + } + __e_acsl_delete_block((void *)(& tmp_35)); + __e_acsl_delete_block((void *)(& jmp_ctxt_14)); + } + { + int tmp_37; + __e_acsl_store_block((void *)(& tmp_37),(size_t)4); + sigjmp_buf *jmp_ctxt_15 = get_jmp_ctxt(); + __e_acsl_store_block((void *)(& jmp_ctxt_15),(size_t)8); + __e_acsl_full_init((void *)(& jmp_ctxt_15)); + __e_acsl_full_init((void *)(& tmp_37)); + tmp_37 = sigsetjmp(*jmp_ctxt_15,1); + switch (tmp_37) { + case 0: + { + set_handler(); + __gen_e_acsl_strncpy(& dest3[4],(char const *)(dest3), + (unsigned long)5); + test_successful(); + break; + } + case 1: { + signal_eval(0,1,__gen_e_acsl_literal_string_20); + break; + } + case 2: { + signal_eval(1,1,__gen_e_acsl_literal_string_20); + break; + } + default: + { + printf(__gen_e_acsl_literal_string_3,__gen_e_acsl_literal_string_20); + __gen_e_acsl_exit(3); + } + } + __e_acsl_delete_block((void *)(& tmp_37)); + __e_acsl_delete_block((void *)(& jmp_ctxt_15)); + } + free((void *)src); + free((void *)dest1); + free((void *)dest2); + __e_acsl_full_init((void *)(& __retres)); + __retres = 0; + __e_acsl_delete_block((void *)(& argv)); + __e_acsl_delete_block((void *)(& argc)); + __e_acsl_delete_block((void *)(& __fc_p_strerror)); + __e_acsl_delete_block((void *)(strerror)); + __e_acsl_delete_block((void *)(& __fc_strtok_ptr)); + __e_acsl_delete_block((void *)(& __fc_p_fopen)); + __e_acsl_delete_block((void *)(__fc_fopen)); + __e_acsl_delete_block((void *)(& __fc_rand_max)); + __e_acsl_delete_block((void *)(& _barrier)); + __e_acsl_delete_block((void *)(& unalloc_str)); + __e_acsl_delete_block((void *)(& len)); + __e_acsl_delete_block((void *)(dest3)); + __e_acsl_delete_block((void *)(& dest2)); + __e_acsl_delete_block((void *)(& dest1)); + __e_acsl_delete_block((void *)(& src)); + __e_acsl_delete_block((void *)(& const_str)); + __e_acsl_delete_block((void *)(empty_str)); + __e_acsl_delete_block((void *)(& __retres)); + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/builtin/oracle_ci/gen_strlen.c b/src/plugins/e-acsl/tests/builtin/oracle_ci/gen_strlen.c new file mode 100644 index 0000000000000000000000000000000000000000..7867b6295cb6891ecc6de1aec8adc86cf7f4aaf5 --- /dev/null +++ b/src/plugins/e-acsl/tests/builtin/oracle_ci/gen_strlen.c @@ -0,0 +1,453 @@ +/* Generated by Frama-C */ +#include "setjmp.h" +#include "signal.h" +#include "stdio.h" +#include "stdlib.h" +#include "string.h" +char *__gen_e_acsl_literal_string_3; +char *__gen_e_acsl_literal_string_2; +char *__gen_e_acsl_literal_string_11; +char *__gen_e_acsl_literal_string_10; +char *__gen_e_acsl_literal_string_9; +char *__gen_e_acsl_literal_string_8; +char *__gen_e_acsl_literal_string_7; +char *__gen_e_acsl_literal_string_6; +char *__gen_e_acsl_literal_string_4; +char *__gen_e_acsl_literal_string_5; +char *__gen_e_acsl_literal_string; +extern int __e_acsl_sound_verdict; + +void __e_acsl_globals_init(void) +{ + static char __e_acsl_already_run = 0; + if (! __e_acsl_already_run) { + __e_acsl_already_run = 1; + __gen_e_acsl_literal_string_3 = "the hog"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_3, + sizeof("the hog")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_3); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_3); + __gen_e_acsl_literal_string_2 = "the cat"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_2, + sizeof("the cat")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_2); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_2); + __gen_e_acsl_literal_string_11 = "tests/builtin/strlen.c:28"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_11, + sizeof("tests/builtin/strlen.c:28")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_11); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_11); + __gen_e_acsl_literal_string_10 = "tests/builtin/strlen.c:26"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_10, + sizeof("tests/builtin/strlen.c:26")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_10); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_10); + __gen_e_acsl_literal_string_9 = "tests/builtin/strlen.c:25"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_9, + sizeof("tests/builtin/strlen.c:25")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_9); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_9); + __gen_e_acsl_literal_string_8 = "tests/builtin/strlen.c:21"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_8, + sizeof("tests/builtin/strlen.c:21")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_8); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_8); + __gen_e_acsl_literal_string_7 = "tests/builtin/strlen.c:20"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_7, + sizeof("tests/builtin/strlen.c:20")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_7); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_7); + __gen_e_acsl_literal_string_6 = "tests/builtin/strlen.c:19"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_6, + sizeof("tests/builtin/strlen.c:19")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_6); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_6); + __gen_e_acsl_literal_string_4 = "tests/builtin/strlen.c:18"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_4, + sizeof("tests/builtin/strlen.c:18")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_4); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_4); + __gen_e_acsl_literal_string_5 = "FAIL: Unexpected value return from test at %s\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_5, + sizeof("FAIL: Unexpected value return from test at %s\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_5); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_5); + __gen_e_acsl_literal_string = ""; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string,sizeof("")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string); + __e_acsl_store_block((void *)(& __gen_e_acsl_strdup),(size_t)1); + __e_acsl_full_init((void *)(& __gen_e_acsl_strdup)); + __e_acsl_store_block((void *)(& __gen_e_acsl_strlen),(size_t)1); + __e_acsl_full_init((void *)(& __gen_e_acsl_strlen)); + __e_acsl_store_block((void *)(& __gen_e_acsl_exit),(size_t)1); + __e_acsl_full_init((void *)(& __gen_e_acsl_exit)); + __e_acsl_store_block((void *)(& __gen_e_acsl_abort),(size_t)1); + __e_acsl_full_init((void *)(& __gen_e_acsl_abort)); + __e_acsl_store_block((void *)(& __fc_p_strerror),(size_t)8); + __e_acsl_full_init((void *)(& __fc_p_strerror)); + __e_acsl_store_block((void *)(strerror),(size_t)64); + __e_acsl_full_init((void *)(& strerror)); + __e_acsl_store_block((void *)(& __fc_strtok_ptr),(size_t)8); + __e_acsl_full_init((void *)(& __fc_strtok_ptr)); + __e_acsl_store_block((void *)(& __fc_p_fopen),(size_t)8); + __e_acsl_full_init((void *)(& __fc_p_fopen)); + __e_acsl_store_block((void *)(__fc_fopen),(size_t)128); + __e_acsl_full_init((void *)(& __fc_fopen)); + __e_acsl_store_block((void *)(& __fc_p_random48_counter),(size_t)8); + __e_acsl_full_init((void *)(& __fc_p_random48_counter)); + __e_acsl_store_block((void *)(random48_counter),(size_t)6); + __e_acsl_full_init((void *)(& random48_counter)); + __e_acsl_store_block((void *)(& __fc_random48_init),(size_t)4); + __e_acsl_full_init((void *)(& __fc_random48_init)); + __e_acsl_store_block((void *)(& __fc_rand_max),(size_t)8); + __e_acsl_full_init((void *)(& __fc_rand_max)); + } + return; +} + +int main(int argc, char const **argv) +{ + int __retres; + int len; + __e_acsl_memory_init(& argc,(char ***)(& argv),(size_t)8); + __e_acsl_globals_init(); + __e_acsl_store_block((void *)(& len),(size_t)4); + __e_acsl_store_block((void *)(& __retres),(size_t)4); + char *empty_str = (char *)__gen_e_acsl_literal_string; + __e_acsl_store_block((void *)(& empty_str),(size_t)8); + __e_acsl_full_init((void *)(& empty_str)); + char *heap_str = __gen_e_acsl_strdup(__gen_e_acsl_literal_string_2); + __e_acsl_store_block((void *)(& heap_str),(size_t)8); + __e_acsl_full_init((void *)(& heap_str)); + char stack_str[8] = + {(char)'t', + (char)'h', + (char)'e', + (char)' ', + (char)'d', + (char)'o', + (char)'g', + (char)'\000'}; + __e_acsl_store_block((void *)(stack_str),(size_t)8); + __e_acsl_full_init((void *)(& stack_str)); + char *const_str = (char *)__gen_e_acsl_literal_string_3; + __e_acsl_store_block((void *)(& const_str),(size_t)8); + __e_acsl_full_init((void *)(& const_str)); + { + int tmp_1; + __e_acsl_store_block((void *)(& tmp_1),(size_t)4); + sigjmp_buf *jmp_ctxt = get_jmp_ctxt(); + __e_acsl_store_block((void *)(& jmp_ctxt),(size_t)8); + __e_acsl_full_init((void *)(& jmp_ctxt)); + __e_acsl_full_init((void *)(& tmp_1)); + /*@ assert Eva: mem_access: \valid_read(jmp_ctxt); */ + tmp_1 = sigsetjmp(*jmp_ctxt,1); + switch (tmp_1) { + case 0: + { + size_t tmp_2; + __e_acsl_store_block((void *)(& tmp_2),(size_t)8); + set_handler(); + __e_acsl_full_init((void *)(& tmp_2)); + tmp_2 = __gen_e_acsl_strlen((char const *)empty_str); + __e_acsl_full_init((void *)(& len)); + len = tmp_2 != (size_t)0; + if (len) __gen_e_acsl_abort(); + test_successful(); + __e_acsl_delete_block((void *)(& tmp_2)); + break; + __e_acsl_delete_block((void *)(& tmp_2)); + } + case 1: { + signal_eval(0,0,__gen_e_acsl_literal_string_4); + break; + } + case 2: { + signal_eval(1,0,__gen_e_acsl_literal_string_4); + break; + } + default: + { + printf(__gen_e_acsl_literal_string_5,__gen_e_acsl_literal_string_4); + __gen_e_acsl_exit(3); + } + } + __e_acsl_delete_block((void *)(& tmp_1)); + __e_acsl_delete_block((void *)(& jmp_ctxt)); + } + { + int tmp_4; + __e_acsl_store_block((void *)(& tmp_4),(size_t)4); + sigjmp_buf *jmp_ctxt_0 = get_jmp_ctxt(); + __e_acsl_store_block((void *)(& jmp_ctxt_0),(size_t)8); + __e_acsl_full_init((void *)(& jmp_ctxt_0)); + __e_acsl_full_init((void *)(& tmp_4)); + tmp_4 = sigsetjmp(*jmp_ctxt_0,1); + switch (tmp_4) { + case 0: + { + size_t tmp_5; + __e_acsl_store_block((void *)(& tmp_5),(size_t)8); + set_handler(); + __e_acsl_full_init((void *)(& tmp_5)); + tmp_5 = __gen_e_acsl_strlen((char const *)heap_str); + __e_acsl_full_init((void *)(& len)); + len = tmp_5 != (size_t)7; + if (len) __gen_e_acsl_abort(); + test_successful(); + __e_acsl_delete_block((void *)(& tmp_5)); + break; + __e_acsl_delete_block((void *)(& tmp_5)); + } + case 1: { + signal_eval(0,0,__gen_e_acsl_literal_string_6); + break; + } + case 2: { + signal_eval(1,0,__gen_e_acsl_literal_string_6); + break; + } + default: + { + printf(__gen_e_acsl_literal_string_5,__gen_e_acsl_literal_string_6); + __gen_e_acsl_exit(3); + } + } + __e_acsl_delete_block((void *)(& tmp_4)); + __e_acsl_delete_block((void *)(& jmp_ctxt_0)); + } + { + int tmp_7; + __e_acsl_store_block((void *)(& tmp_7),(size_t)4); + sigjmp_buf *jmp_ctxt_1 = get_jmp_ctxt(); + __e_acsl_store_block((void *)(& jmp_ctxt_1),(size_t)8); + __e_acsl_full_init((void *)(& jmp_ctxt_1)); + __e_acsl_full_init((void *)(& tmp_7)); + tmp_7 = sigsetjmp(*jmp_ctxt_1,1); + switch (tmp_7) { + case 0: + { + size_t tmp_8; + __e_acsl_store_block((void *)(& tmp_8),(size_t)8); + set_handler(); + __e_acsl_full_init((void *)(& tmp_8)); + tmp_8 = __gen_e_acsl_strlen((char const *)(stack_str)); + __e_acsl_full_init((void *)(& len)); + len = tmp_8 != (size_t)7; + if (len) __gen_e_acsl_abort(); + test_successful(); + __e_acsl_delete_block((void *)(& tmp_8)); + break; + __e_acsl_delete_block((void *)(& tmp_8)); + } + case 1: { + signal_eval(0,0,__gen_e_acsl_literal_string_7); + break; + } + case 2: { + signal_eval(1,0,__gen_e_acsl_literal_string_7); + break; + } + default: + { + printf(__gen_e_acsl_literal_string_5,__gen_e_acsl_literal_string_7); + __gen_e_acsl_exit(3); + } + } + __e_acsl_delete_block((void *)(& tmp_7)); + __e_acsl_delete_block((void *)(& jmp_ctxt_1)); + } + { + int tmp_10; + __e_acsl_store_block((void *)(& tmp_10),(size_t)4); + sigjmp_buf *jmp_ctxt_2 = get_jmp_ctxt(); + __e_acsl_store_block((void *)(& jmp_ctxt_2),(size_t)8); + __e_acsl_full_init((void *)(& jmp_ctxt_2)); + __e_acsl_full_init((void *)(& tmp_10)); + tmp_10 = sigsetjmp(*jmp_ctxt_2,1); + switch (tmp_10) { + case 0: + { + size_t tmp_11; + __e_acsl_store_block((void *)(& tmp_11),(size_t)8); + set_handler(); + __e_acsl_full_init((void *)(& tmp_11)); + tmp_11 = __gen_e_acsl_strlen((char const *)const_str); + __e_acsl_full_init((void *)(& len)); + len = tmp_11 != (size_t)7; + if (len) __gen_e_acsl_abort(); + test_successful(); + __e_acsl_delete_block((void *)(& tmp_11)); + break; + __e_acsl_delete_block((void *)(& tmp_11)); + } + case 1: { + signal_eval(0,0,__gen_e_acsl_literal_string_8); + break; + } + case 2: { + signal_eval(1,0,__gen_e_acsl_literal_string_8); + break; + } + default: + { + printf(__gen_e_acsl_literal_string_5,__gen_e_acsl_literal_string_8); + __gen_e_acsl_exit(3); + } + } + __e_acsl_delete_block((void *)(& tmp_10)); + __e_acsl_delete_block((void *)(& jmp_ctxt_2)); + } + __e_acsl_initialize((void *)(heap_str + 7),sizeof(char)); + *(heap_str + 7) = (char)'a'; + __e_acsl_initialize((void *)(& stack_str[7]),sizeof(char)); + stack_str[7] = (char)'a'; + { + int tmp_13; + __e_acsl_store_block((void *)(& tmp_13),(size_t)4); + sigjmp_buf *jmp_ctxt_3 = get_jmp_ctxt(); + __e_acsl_store_block((void *)(& jmp_ctxt_3),(size_t)8); + __e_acsl_full_init((void *)(& jmp_ctxt_3)); + __e_acsl_full_init((void *)(& tmp_13)); + tmp_13 = sigsetjmp(*jmp_ctxt_3,1); + switch (tmp_13) { + case 0: + { + size_t tmp_14; + __e_acsl_store_block((void *)(& tmp_14),(size_t)8); + set_handler(); + __e_acsl_full_init((void *)(& tmp_14)); + tmp_14 = __gen_e_acsl_strlen((char const *)heap_str); + __e_acsl_full_init((void *)(& len)); + len = tmp_14 != (size_t)7; + if (len) __gen_e_acsl_abort(); + test_successful(); + __e_acsl_delete_block((void *)(& tmp_14)); + break; + __e_acsl_delete_block((void *)(& tmp_14)); + } + case 1: { + signal_eval(0,1,__gen_e_acsl_literal_string_9); + break; + } + case 2: { + signal_eval(1,1,__gen_e_acsl_literal_string_9); + break; + } + default: + { + printf(__gen_e_acsl_literal_string_5,__gen_e_acsl_literal_string_9); + __gen_e_acsl_exit(3); + } + } + __e_acsl_delete_block((void *)(& tmp_13)); + __e_acsl_delete_block((void *)(& jmp_ctxt_3)); + } + { + int tmp_16; + __e_acsl_store_block((void *)(& tmp_16),(size_t)4); + sigjmp_buf *jmp_ctxt_4 = get_jmp_ctxt(); + __e_acsl_store_block((void *)(& jmp_ctxt_4),(size_t)8); + __e_acsl_full_init((void *)(& jmp_ctxt_4)); + __e_acsl_full_init((void *)(& tmp_16)); + tmp_16 = sigsetjmp(*jmp_ctxt_4,1); + switch (tmp_16) { + case 0: + { + size_t tmp_17; + __e_acsl_store_block((void *)(& tmp_17),(size_t)8); + set_handler(); + __e_acsl_full_init((void *)(& tmp_17)); + tmp_17 = __gen_e_acsl_strlen((char const *)(stack_str)); + __e_acsl_full_init((void *)(& len)); + len = tmp_17 != (size_t)7; + if (len) __gen_e_acsl_abort(); + test_successful(); + __e_acsl_delete_block((void *)(& tmp_17)); + break; + __e_acsl_delete_block((void *)(& tmp_17)); + } + case 1: { + signal_eval(0,1,__gen_e_acsl_literal_string_10); + break; + } + case 2: { + signal_eval(1,1,__gen_e_acsl_literal_string_10); + break; + } + default: + { + printf(__gen_e_acsl_literal_string_5,__gen_e_acsl_literal_string_10); + __gen_e_acsl_exit(3); + } + } + __e_acsl_delete_block((void *)(& tmp_16)); + __e_acsl_delete_block((void *)(& jmp_ctxt_4)); + } + free((void *)heap_str); + { + int tmp_19; + __e_acsl_store_block((void *)(& tmp_19),(size_t)4); + sigjmp_buf *jmp_ctxt_5 = get_jmp_ctxt(); + __e_acsl_store_block((void *)(& jmp_ctxt_5),(size_t)8); + __e_acsl_full_init((void *)(& jmp_ctxt_5)); + __e_acsl_full_init((void *)(& tmp_19)); + tmp_19 = sigsetjmp(*jmp_ctxt_5,1); + switch (tmp_19) { + case 0: + { + size_t tmp_20; + __e_acsl_store_block((void *)(& tmp_20),(size_t)8); + set_handler(); + __e_acsl_full_init((void *)(& tmp_20)); + tmp_20 = __gen_e_acsl_strlen((char const *)heap_str); + __e_acsl_full_init((void *)(& len)); + len = tmp_20 != (size_t)7; + if (len) __gen_e_acsl_abort(); + test_successful(); + __e_acsl_delete_block((void *)(& tmp_20)); + break; + __e_acsl_delete_block((void *)(& tmp_20)); + } + case 1: { + signal_eval(0,1,__gen_e_acsl_literal_string_11); + break; + } + case 2: { + signal_eval(1,1,__gen_e_acsl_literal_string_11); + break; + } + default: + { + printf(__gen_e_acsl_literal_string_5,__gen_e_acsl_literal_string_11); + __gen_e_acsl_exit(3); + } + } + __e_acsl_delete_block((void *)(& tmp_19)); + __e_acsl_delete_block((void *)(& jmp_ctxt_5)); + } + __e_acsl_full_init((void *)(& __retres)); + __retres = 0; + __e_acsl_delete_block((void *)(& argv)); + __e_acsl_delete_block((void *)(& argc)); + __e_acsl_delete_block((void *)(& __fc_p_strerror)); + __e_acsl_delete_block((void *)(strerror)); + __e_acsl_delete_block((void *)(& __fc_strtok_ptr)); + __e_acsl_delete_block((void *)(& __fc_p_fopen)); + __e_acsl_delete_block((void *)(__fc_fopen)); + __e_acsl_delete_block((void *)(& __fc_p_random48_counter)); + __e_acsl_delete_block((void *)(random48_counter)); + __e_acsl_delete_block((void *)(& __fc_random48_init)); + __e_acsl_delete_block((void *)(& __fc_rand_max)); + __e_acsl_delete_block((void *)(& const_str)); + __e_acsl_delete_block((void *)(stack_str)); + __e_acsl_delete_block((void *)(& heap_str)); + __e_acsl_delete_block((void *)(& empty_str)); + __e_acsl_delete_block((void *)(& len)); + __e_acsl_delete_block((void *)(& __retres)); + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/builtin/oracle_ci/strcat.res.oracle b/src/plugins/e-acsl/tests/builtin/oracle_ci/strcat.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..db06f9cb2ec734289a0ff74f65f844fded8e2b94 --- /dev/null +++ b/src/plugins/e-acsl/tests/builtin/oracle_ci/strcat.res.oracle @@ -0,0 +1,113 @@ +[e-acsl] beginning translation. +[e-acsl] Warning: annotating undefined function `exit': + the generated program may miss memory instrumentation + if there are memory-related annotations. +[e-acsl] Warning: annotating undefined function `strcat': + the generated program may miss memory instrumentation + if there are memory-related annotations. +[e-acsl] Warning: annotating undefined function `strncat': + the generated program may miss memory instrumentation + if there are memory-related annotations. +[kernel:annot:missing-spec] FRAMAC_SHARE/libc/stdio.h:169: Warning: + Neither code nor specification for function printf, generating default assigns from the prototype +[kernel:annot:missing-spec] FRAMAC_SHARE/libc/setjmp.h:47: Warning: + Neither code nor specification for function sigsetjmp, generating default assigns from the prototype +[kernel:annot:missing-spec] tests/builtin/signalled.h:14: Warning: + Neither code nor specification for function signal_eval, generating default assigns from the prototype +[kernel:annot:missing-spec] tests/builtin/signalled.h:18: Warning: + Neither code nor specification for function get_jmp_ctxt, generating default assigns from the prototype +[kernel:annot:missing-spec] tests/builtin/signalled.h:20: Warning: + Neither code nor specification for function set_handler, generating default assigns from the prototype +[kernel:annot:missing-spec] tests/builtin/signalled.h:22: Warning: + Neither code nor specification for function test_successful, generating default assigns from the prototype +[e-acsl] FRAMAC_SHARE/libc/string.h:421: Warning: + E-ACSL construct `logic function application' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/string.h:422: Warning: + E-ACSL construct `logic function application' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/string.h:427: Warning: + E-ACSL construct `logic function application' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/string.h:435: Warning: + E-ACSL construct `logic function application' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/string.h:435: Warning: + E-ACSL construct `assigns clause in behavior' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/string.h:427: Warning: + E-ACSL construct `assigns clause in behavior' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/string.h:425: Warning: + E-ACSL construct `assigns clause in behavior' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/string.h:406: Warning: + E-ACSL construct `logic function application' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/string.h:407: Warning: + E-ACSL construct `logic function application' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/string.h:408: Warning: + E-ACSL construct `logic function returning an integer' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/string.h:408: Warning: + E-ACSL construct `assigns clause in behavior' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/string.h:411: Warning: + E-ACSL construct `logic function returning an integer' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/string.h:414: Warning: + E-ACSL construct `logic function returning an integer' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/string.h:415: Warning: + E-ACSL construct `logic function returning an integer' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/string.h:416: Warning: + E-ACSL construct `assigns clause in behavior' is not yet supported. + Ignoring annotation. +[e-acsl] translation done in project "e-acsl". +[eva] Analyzing a complete application starting at main +[eva] Computing initial state +[eva] Initial state computed +[eva:initial-state] Values of globals at initialization + __e_acsl_init ∈ [--..--] + __e_acsl_heap_allocation_size ∈ [--..--] + __e_acsl_math_HUGE_VAL ∈ [-1.79769313486e+308 .. 1.79769313486e+308] + __e_acsl_math_HUGE_VALF ∈ [-3.40282346639e+38 .. 3.40282346639e+38] + __e_acsl_math_INFINITY ∈ [-1.79769313486e+308 .. 1.79769313486e+308] + __e_acsl_sound_verdict ∈ [--..--] + __gen_e_acsl_literal_string ∈ {0} + __gen_e_acsl_literal_string_2 ∈ {0} + __gen_e_acsl_literal_string_3 ∈ {0} + __gen_e_acsl_literal_string_4 ∈ {0} + __gen_e_acsl_literal_string_5 ∈ {0} + __gen_e_acsl_literal_string_6 ∈ {0} + __gen_e_acsl_literal_string_7 ∈ {0} + __gen_e_acsl_literal_string_8 ∈ {0} + __gen_e_acsl_literal_string_9 ∈ {0} + __gen_e_acsl_literal_string_10 ∈ {0} + __gen_e_acsl_literal_string_11 ∈ {0} + __gen_e_acsl_literal_string_12 ∈ {0} + __gen_e_acsl_literal_string_13 ∈ {0} + __gen_e_acsl_literal_string_14 ∈ {0} + __gen_e_acsl_literal_string_15 ∈ {0} + __gen_e_acsl_literal_string_16 ∈ {0} + __gen_e_acsl_literal_string_17 ∈ {0} + __gen_e_acsl_literal_string_18 ∈ {0} + __gen_e_acsl_literal_string_19 ∈ {0} + __gen_e_acsl_literal_string_20 ∈ {0} + __gen_e_acsl_literal_string_21 ∈ {0} + __gen_e_acsl_literal_string_22 ∈ {0} + __gen_e_acsl_literal_string_23 ∈ {0} + __gen_e_acsl_literal_string_24 ∈ {0} + __gen_e_acsl_literal_string_25 ∈ {0} +[eva] using specification for function __e_acsl_memory_init +[eva] using specification for function __e_acsl_store_block +[eva] using specification for function __e_acsl_full_init +[eva] using specification for function __e_acsl_mark_readonly +[eva] tests/builtin/strcat.c:11: allocating variable __malloc_main_l11 +[eva] tests/builtin/strcat.c:12: allocating variable __malloc_main_l12 +[eva] using specification for function get_jmp_ctxt +[eva:alarm] tests/builtin/strcat.c:27: Warning: + out of bounds read. assert \valid_read(jmp_ctxt); +[eva] done for function main diff --git a/src/plugins/e-acsl/tests/builtin/oracle_ci/strcmp.res.oracle b/src/plugins/e-acsl/tests/builtin/oracle_ci/strcmp.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..008bdcc7f190644e55759a874790c59c6d659fa7 --- /dev/null +++ b/src/plugins/e-acsl/tests/builtin/oracle_ci/strcmp.res.oracle @@ -0,0 +1,133 @@ +[e-acsl] beginning translation. +[e-acsl] Warning: annotating undefined function `abort': + the generated program may miss memory instrumentation + if there are memory-related annotations. +[e-acsl] Warning: annotating undefined function `exit': + the generated program may miss memory instrumentation + if there are memory-related annotations. +[e-acsl] Warning: annotating undefined function `strcmp': + the generated program may miss memory instrumentation + if there are memory-related annotations. +[e-acsl] Warning: annotating undefined function `strncmp': + the generated program may miss memory instrumentation + if there are memory-related annotations. +[e-acsl] Warning: annotating undefined function `strdup': + the generated program may miss memory instrumentation + if there are memory-related annotations. +[kernel:annot:missing-spec] FRAMAC_SHARE/libc/stdio.h:165: Warning: + Neither code nor specification for function fprintf, generating default assigns from the prototype +[kernel:annot:missing-spec] FRAMAC_SHARE/libc/stdio.h:169: Warning: + Neither code nor specification for function printf, generating default assigns from the prototype +[kernel:annot:missing-spec] FRAMAC_SHARE/libc/setjmp.h:47: Warning: + Neither code nor specification for function sigsetjmp, generating default assigns from the prototype +[kernel:annot:missing-spec] tests/builtin/signalled.h:14: Warning: + Neither code nor specification for function signal_eval, generating default assigns from the prototype +[kernel:annot:missing-spec] tests/builtin/signalled.h:18: Warning: + Neither code nor specification for function get_jmp_ctxt, generating default assigns from the prototype +[kernel:annot:missing-spec] tests/builtin/signalled.h:20: Warning: + Neither code nor specification for function set_handler, generating default assigns from the prototype +[kernel:annot:missing-spec] tests/builtin/signalled.h:22: Warning: + Neither code nor specification for function test_successful, generating default assigns from the prototype +[e-acsl] FRAMAC_SHARE/libc/stdlib.h:457: Warning: + E-ACSL construct `assigns clause in behavior' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/string.h:469: Warning: + E-ACSL construct `logic function application' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/string.h:469: Warning: + E-ACSL construct `assigns clause in behavior' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/string.h:476: Warning: + E-ACSL construct `logic function application' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/string.h:144: Warning: + E-ACSL construct `logic function application' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/string.h:145: Warning: + E-ACSL construct `logic function application' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/string.h:145: Warning: + E-ACSL construct `assigns clause in behavior' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/string.h:147: Warning: + E-ACSL construct `logic function returning an integer' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/string.h:137: Warning: + E-ACSL construct `logic function application' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/string.h:138: Warning: + E-ACSL construct `logic function application' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/string.h:138: Warning: + E-ACSL construct `assigns clause in behavior' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/string.h:140: Warning: + E-ACSL construct `logic function returning an integer' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/string.h:140: Warning: + E-ACSL construct `assigns clause in behavior' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/stdlib.h:469: Warning: + E-ACSL construct `assigns clause in behavior' is not yet supported. + Ignoring annotation. +[e-acsl] translation done in project "e-acsl". +[eva] Analyzing a complete application starting at main +[eva] Computing initial state +[eva] Initial state computed +[eva:initial-state] Values of globals at initialization + __e_acsl_init ∈ [--..--] + __e_acsl_heap_allocation_size ∈ [--..--] + __e_acsl_math_HUGE_VAL ∈ [-1.79769313486e+308 .. 1.79769313486e+308] + __e_acsl_math_HUGE_VALF ∈ [-3.40282346639e+38 .. 3.40282346639e+38] + __e_acsl_math_INFINITY ∈ [-1.79769313486e+308 .. 1.79769313486e+308] + __e_acsl_sound_verdict ∈ [--..--] + __gen_e_acsl_literal_string ∈ {0} + __gen_e_acsl_literal_string_2 ∈ {0} + __gen_e_acsl_literal_string_3 ∈ {0} + __gen_e_acsl_literal_string_4 ∈ {0} + __gen_e_acsl_literal_string_5 ∈ {0} + __gen_e_acsl_literal_string_6 ∈ {0} + __gen_e_acsl_literal_string_7 ∈ {0} + __gen_e_acsl_literal_string_8 ∈ {0} + __gen_e_acsl_literal_string_9 ∈ {0} + __gen_e_acsl_literal_string_10 ∈ {0} + __gen_e_acsl_literal_string_11 ∈ {0} + __gen_e_acsl_literal_string_12 ∈ {0} + __gen_e_acsl_literal_string_13 ∈ {0} + __gen_e_acsl_literal_string_14 ∈ {0} + __gen_e_acsl_literal_string_15 ∈ {0} + __gen_e_acsl_literal_string_16 ∈ {0} + __gen_e_acsl_literal_string_17 ∈ {0} + __gen_e_acsl_literal_string_18 ∈ {0} + __gen_e_acsl_literal_string_19 ∈ {0} + __gen_e_acsl_literal_string_20 ∈ {0} + __gen_e_acsl_literal_string_21 ∈ {0} + __gen_e_acsl_literal_string_22 ∈ {0} + __gen_e_acsl_literal_string_23 ∈ {0} + __gen_e_acsl_literal_string_24 ∈ {0} + __gen_e_acsl_literal_string_25 ∈ {0} + __gen_e_acsl_literal_string_26 ∈ {0} + __gen_e_acsl_literal_string_27 ∈ {0} + __gen_e_acsl_literal_string_28 ∈ {0} +[eva] using specification for function __e_acsl_memory_init +[eva] using specification for function __e_acsl_store_block +[eva] using specification for function __e_acsl_full_init +[eva] using specification for function __e_acsl_mark_readonly +[eva] using specification for function strdup +[eva:libc:unsupported-spec] FRAMAC_SHARE/libc/string.h:466: Warning: + The specification of function 'strdup' is currently not supported by Eva. + Consider adding FRAMAC_SHARE/libc/string.c + to the analyzed source files. +[eva] FRAMAC_SHARE/libc/string.h:466: Warning: + ignoring unsupported \allocates clause +[eva] using specification for function __e_acsl_delete_block +[eva:alarm] FRAMAC_SHARE/libc/string.h:472: Warning: + function __gen_e_acsl_strdup, behavior allocation: postcondition 'allocation' got status unknown. (Behavior may be inactive, no reduction performed.) +[eva:alarm] FRAMAC_SHARE/libc/string.h:474: Warning: + function __gen_e_acsl_strdup, behavior allocation: postcondition 'result_valid_string_and_same_contents' got status invalid. (Behavior may be inactive, no reduction performed.) +[eva:alarm] FRAMAC_SHARE/libc/string.h:479: Warning: + function __gen_e_acsl_strdup, behavior no_allocation: postcondition 'result_null' got status unknown. (Behavior may be inactive, no reduction performed.) +[eva] using specification for function get_jmp_ctxt +[eva:alarm] tests/builtin/strcmp.c:32: Warning: + out of bounds read. assert \valid_read(jmp_ctxt); +[eva] done for function main diff --git a/src/plugins/e-acsl/tests/builtin/oracle_ci/strcpy.res.oracle b/src/plugins/e-acsl/tests/builtin/oracle_ci/strcpy.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..bfb97b289981bcf30441d74821038c0a8281eaad --- /dev/null +++ b/src/plugins/e-acsl/tests/builtin/oracle_ci/strcpy.res.oracle @@ -0,0 +1,125 @@ +[e-acsl] beginning translation. +[e-acsl] Warning: annotating undefined function `exit': + the generated program may miss memory instrumentation + if there are memory-related annotations. +[e-acsl] Warning: annotating undefined function `strcpy': + the generated program may miss memory instrumentation + if there are memory-related annotations. +[e-acsl] Warning: annotating undefined function `strncpy': + the generated program may miss memory instrumentation + if there are memory-related annotations. +[e-acsl] Warning: annotating undefined function `strdup': + the generated program may miss memory instrumentation + if there are memory-related annotations. +[kernel:annot:missing-spec] FRAMAC_SHARE/libc/stdio.h:169: Warning: + Neither code nor specification for function printf, generating default assigns from the prototype +[kernel:annot:missing-spec] FRAMAC_SHARE/libc/setjmp.h:47: Warning: + Neither code nor specification for function sigsetjmp, generating default assigns from the prototype +[kernel:annot:missing-spec] tests/builtin/signalled.h:14: Warning: + Neither code nor specification for function signal_eval, generating default assigns from the prototype +[kernel:annot:missing-spec] tests/builtin/signalled.h:18: Warning: + Neither code nor specification for function get_jmp_ctxt, generating default assigns from the prototype +[kernel:annot:missing-spec] tests/builtin/signalled.h:20: Warning: + Neither code nor specification for function set_handler, generating default assigns from the prototype +[kernel:annot:missing-spec] tests/builtin/signalled.h:22: Warning: + Neither code nor specification for function test_successful, generating default assigns from the prototype +[e-acsl] FRAMAC_SHARE/libc/stdlib.h:404: Warning: + E-ACSL construct `assigns clause in behavior' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/string.h:469: Warning: + E-ACSL construct `logic function application' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/string.h:469: Warning: + E-ACSL construct `assigns clause in behavior' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/string.h:476: Warning: + E-ACSL construct `logic function application' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/string.h:359: Warning: + E-ACSL construct `logic function application' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/string.h:362: Warning: + E-ACSL construct `\separated' is not yet supported. Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/string.h:368: Warning: + E-ACSL construct `logic function returning an integer' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/string.h:368: Warning: + E-ACSL construct `assigns clause in behavior' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/string.h:371: Warning: + E-ACSL construct `logic function returning an integer' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/string.h:347: Warning: + E-ACSL construct `logic function application' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/string.h:348: Warning: + E-ACSL construct `logic function returning an integer' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/string.h:350: Warning: + E-ACSL construct `\separated' is not yet supported. Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/string.h:350: Warning: + E-ACSL construct `assigns clause in behavior' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/string.h:353: Warning: + E-ACSL construct `logic function returning an integer' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/string.h:354: Warning: + E-ACSL construct `assigns clause in behavior' is not yet supported. + Ignoring annotation. +[e-acsl] translation done in project "e-acsl". +[eva] Analyzing a complete application starting at main +[eva] Computing initial state +[eva] Initial state computed +[eva:initial-state] Values of globals at initialization + __e_acsl_init ∈ [--..--] + __e_acsl_heap_allocation_size ∈ [--..--] + __e_acsl_math_HUGE_VAL ∈ [-1.79769313486e+308 .. 1.79769313486e+308] + __e_acsl_math_HUGE_VALF ∈ [-3.40282346639e+38 .. 3.40282346639e+38] + __e_acsl_math_INFINITY ∈ [-1.79769313486e+308 .. 1.79769313486e+308] + __e_acsl_sound_verdict ∈ [--..--] + __gen_e_acsl_literal_string ∈ {0} + __gen_e_acsl_literal_string_2 ∈ {0} + __gen_e_acsl_literal_string_3 ∈ {0} + __gen_e_acsl_literal_string_4 ∈ {0} + __gen_e_acsl_literal_string_5 ∈ {0} + __gen_e_acsl_literal_string_6 ∈ {0} + __gen_e_acsl_literal_string_7 ∈ {0} + __gen_e_acsl_literal_string_8 ∈ {0} + __gen_e_acsl_literal_string_9 ∈ {0} + __gen_e_acsl_literal_string_10 ∈ {0} + __gen_e_acsl_literal_string_11 ∈ {0} + __gen_e_acsl_literal_string_12 ∈ {0} + __gen_e_acsl_literal_string_13 ∈ {0} + __gen_e_acsl_literal_string_14 ∈ {0} + __gen_e_acsl_literal_string_15 ∈ {0} + __gen_e_acsl_literal_string_16 ∈ {0} + __gen_e_acsl_literal_string_17 ∈ {0} + __gen_e_acsl_literal_string_18 ∈ {0} + __gen_e_acsl_literal_string_19 ∈ {0} + __gen_e_acsl_literal_string_20 ∈ {0} +[eva] using specification for function __e_acsl_memory_init +[eva] using specification for function __e_acsl_store_block +[eva] using specification for function __e_acsl_full_init +[eva] using specification for function __e_acsl_mark_readonly +[eva] using specification for function strdup +[eva:libc:unsupported-spec] FRAMAC_SHARE/libc/string.h:466: Warning: + The specification of function 'strdup' is currently not supported by Eva. + Consider adding FRAMAC_SHARE/libc/string.c + to the analyzed source files. +[eva] FRAMAC_SHARE/libc/string.h:466: Warning: + ignoring unsupported \allocates clause +[eva] using specification for function __e_acsl_delete_block +[eva:alarm] FRAMAC_SHARE/libc/string.h:472: Warning: + function __gen_e_acsl_strdup, behavior allocation: postcondition 'allocation' got status unknown. (Behavior may be inactive, no reduction performed.) +[eva:alarm] FRAMAC_SHARE/libc/string.h:474: Warning: + function __gen_e_acsl_strdup, behavior allocation: postcondition 'result_valid_string_and_same_contents' got status invalid. (Behavior may be inactive, no reduction performed.) +[eva:alarm] FRAMAC_SHARE/libc/string.h:479: Warning: + function __gen_e_acsl_strdup, behavior no_allocation: postcondition 'result_null' got status unknown. (Behavior may be inactive, no reduction performed.) +[eva] tests/builtin/strcpy.c:13: allocating variable __malloc_main_l13 +[eva] tests/builtin/strcpy.c:14: allocating variable __malloc_main_l14 +[eva] tests/builtin/strcpy.c:18: allocating variable __malloc_main_l18 +[eva] tests/builtin/strcpy.c:18: allocating variable __malloc_main_l18_0 +[eva] using specification for function get_jmp_ctxt +[eva:alarm] tests/builtin/strcpy.c:21: Warning: + out of bounds read. assert \valid_read(jmp_ctxt); +[eva] done for function main diff --git a/src/plugins/e-acsl/tests/builtin/oracle_ci/strlen.res.oracle b/src/plugins/e-acsl/tests/builtin/oracle_ci/strlen.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..e0d81d086eed867d6131626321014fd72b2506b9 --- /dev/null +++ b/src/plugins/e-acsl/tests/builtin/oracle_ci/strlen.res.oracle @@ -0,0 +1,96 @@ +[e-acsl] beginning translation. +[e-acsl] Warning: annotating undefined function `abort': + the generated program may miss memory instrumentation + if there are memory-related annotations. +[e-acsl] Warning: annotating undefined function `exit': + the generated program may miss memory instrumentation + if there are memory-related annotations. +[e-acsl] Warning: annotating undefined function `strlen': + the generated program may miss memory instrumentation + if there are memory-related annotations. +[e-acsl] Warning: annotating undefined function `strdup': + the generated program may miss memory instrumentation + if there are memory-related annotations. +[kernel:annot:missing-spec] FRAMAC_SHARE/libc/stdio.h:169: Warning: + Neither code nor specification for function printf, generating default assigns from the prototype +[kernel:annot:missing-spec] FRAMAC_SHARE/libc/setjmp.h:47: Warning: + Neither code nor specification for function sigsetjmp, generating default assigns from the prototype +[kernel:annot:missing-spec] tests/builtin/signalled.h:14: Warning: + Neither code nor specification for function signal_eval, generating default assigns from the prototype +[kernel:annot:missing-spec] tests/builtin/signalled.h:18: Warning: + Neither code nor specification for function get_jmp_ctxt, generating default assigns from the prototype +[kernel:annot:missing-spec] tests/builtin/signalled.h:20: Warning: + Neither code nor specification for function set_handler, generating default assigns from the prototype +[kernel:annot:missing-spec] tests/builtin/signalled.h:22: Warning: + Neither code nor specification for function test_successful, generating default assigns from the prototype +[e-acsl] FRAMAC_SHARE/libc/stdlib.h:457: Warning: + E-ACSL construct `assigns clause in behavior' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/string.h:469: Warning: + E-ACSL construct `logic function application' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/string.h:469: Warning: + E-ACSL construct `assigns clause in behavior' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/string.h:476: Warning: + E-ACSL construct `logic function application' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/string.h:125: Warning: + E-ACSL construct `logic function application' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/string.h:125: Warning: + E-ACSL construct `assigns clause in behavior' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/string.h:127: Warning: + E-ACSL construct `logic function returning an integer' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/string.h:127: Warning: + E-ACSL construct `assigns clause in behavior' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/stdlib.h:469: Warning: + E-ACSL construct `assigns clause in behavior' is not yet supported. + Ignoring annotation. +[e-acsl] translation done in project "e-acsl". +[eva] Analyzing a complete application starting at main +[eva] Computing initial state +[eva] Initial state computed +[eva:initial-state] Values of globals at initialization + __e_acsl_init ∈ [--..--] + __e_acsl_heap_allocation_size ∈ [--..--] + __e_acsl_math_HUGE_VAL ∈ [-1.79769313486e+308 .. 1.79769313486e+308] + __e_acsl_math_HUGE_VALF ∈ [-3.40282346639e+38 .. 3.40282346639e+38] + __e_acsl_math_INFINITY ∈ [-1.79769313486e+308 .. 1.79769313486e+308] + __e_acsl_sound_verdict ∈ [--..--] + __gen_e_acsl_literal_string ∈ {0} + __gen_e_acsl_literal_string_2 ∈ {0} + __gen_e_acsl_literal_string_3 ∈ {0} + __gen_e_acsl_literal_string_4 ∈ {0} + __gen_e_acsl_literal_string_5 ∈ {0} + __gen_e_acsl_literal_string_6 ∈ {0} + __gen_e_acsl_literal_string_7 ∈ {0} + __gen_e_acsl_literal_string_8 ∈ {0} + __gen_e_acsl_literal_string_9 ∈ {0} + __gen_e_acsl_literal_string_10 ∈ {0} + __gen_e_acsl_literal_string_11 ∈ {0} +[eva] using specification for function __e_acsl_memory_init +[eva] using specification for function __e_acsl_store_block +[eva] using specification for function __e_acsl_full_init +[eva] using specification for function __e_acsl_mark_readonly +[eva] using specification for function strdup +[eva:libc:unsupported-spec] FRAMAC_SHARE/libc/string.h:466: Warning: + The specification of function 'strdup' is currently not supported by Eva. + Consider adding FRAMAC_SHARE/libc/string.c + to the analyzed source files. +[eva] FRAMAC_SHARE/libc/string.h:466: Warning: + ignoring unsupported \allocates clause +[eva] using specification for function __e_acsl_delete_block +[eva:alarm] FRAMAC_SHARE/libc/string.h:472: Warning: + function __gen_e_acsl_strdup, behavior allocation: postcondition 'allocation' got status unknown. (Behavior may be inactive, no reduction performed.) +[eva:alarm] FRAMAC_SHARE/libc/string.h:474: Warning: + function __gen_e_acsl_strdup, behavior allocation: postcondition 'result_valid_string_and_same_contents' got status invalid. (Behavior may be inactive, no reduction performed.) +[eva:alarm] FRAMAC_SHARE/libc/string.h:479: Warning: + function __gen_e_acsl_strdup, behavior no_allocation: postcondition 'result_null' got status unknown. (Behavior may be inactive, no reduction performed.) +[eva] using specification for function get_jmp_ctxt +[eva:alarm] tests/builtin/strlen.c:18: Warning: + out of bounds read. assert \valid_read(jmp_ctxt); +[eva] done for function main diff --git a/src/plugins/e-acsl/tests/builtin/signalled.c b/src/plugins/e-acsl/tests/builtin/signalled.c new file mode 100644 index 0000000000000000000000000000000000000000..ebb74f89b4b88c76804cf539f7502ac5aea991a8 --- /dev/null +++ b/src/plugins/e-acsl/tests/builtin/signalled.c @@ -0,0 +1,51 @@ +/* run.config +DONTRUN: auxiliary file use by tests +*/ +#include "signalled.h" + +static sigjmp_buf jmp_ctxt; +static int got_signal; +static int testno = 0; + +sigjmp_buf* get_jmp_ctxt(void) { return &jmp_ctxt; } + +void signalled(int sig) { + printf("signalled\n"); + struct sigaction sig_dfl; + sig_dfl.sa_handler = SIG_DFL; + sigemptyset(&sig_dfl.sa_mask); + sigaction(SIGABRT,&sig_dfl,NULL); + got_signal = 1; + siglongjmp(jmp_ctxt,EXE_SIGNAL); +} + +void signal_eval(int signalled, int expect_signal, const char* at) { + printf("TEST %d: ", ++testno); + if (signalled && expect_signal) + printf("OK: Expected signal at %s\n", at); + else if (!signalled && !expect_signal) + printf("OK: Expected execution at %s\n", at); + else if (!signalled && expect_signal) { + printf("FAIL: Unexpected execution at %s\n", at); + exit(1); + } else if (signalled && !expect_signal) { + printf("FAIL: Unexpected signal at %s\n", at); + exit(2); + } +} + +void set_handler(void) { + struct sigaction check_signal; + check_signal.sa_handler = signalled; + sigemptyset(&check_signal.sa_mask); + check_signal.sa_flags = 0; + sigaction(SIGABRT,&check_signal,NULL); +} + +void test_successful(void) { + struct sigaction sig_dfl; + sig_dfl.sa_handler = SIG_DFL; + sigemptyset(&sig_dfl.sa_mask); + sigaction(SIGABRT,&sig_dfl,NULL); + siglongjmp(jmp_ctxt,EXE_SUCCESS); +} diff --git a/src/plugins/e-acsl/tests/builtin/signalled.h b/src/plugins/e-acsl/tests/builtin/signalled.h new file mode 100644 index 0000000000000000000000000000000000000000..1a16fdf7c5a22c3fdab0766fe22a8d277932f925 --- /dev/null +++ b/src/plugins/e-acsl/tests/builtin/signalled.h @@ -0,0 +1,53 @@ +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <signal.h> +#include <setjmp.h> + +#define STRINGIFY(x) #x +#define TOSTRING(x) STRINGIFY(x) +#define AT __FILE__ ":" TOSTRING(__LINE__) + +#define EXE_SUCCESS 1 +#define EXE_SIGNAL 2 + +void signal_eval(int signalled, int expect_signal, const char *at); + +void signalled(int sig); + +sigjmp_buf* get_jmp_ctxt(void); + +void set_handler(void); + +void test_successful(void); + +/* The following macro runs a chunk of code in a subprocess and evaluates + the result. This macro assumes that fork is always successful. */ +#define SIGNALLED_AT(code, expect_signal, at) { \ + sigjmp_buf* jmp_ctxt = get_jmp_ctxt(); \ + switch (sigsetjmp(*jmp_ctxt,1)) { \ + case 0: { \ + set_handler(); \ + code; \ + test_successful(); \ + break; \ + } \ + case EXE_SUCCESS: { \ + signal_eval(0,expect_signal,at); \ + break; \ + } \ + case EXE_SIGNAL: { \ + signal_eval(1,expect_signal,at); \ + break; \ + } \ + default: { \ + printf("FAIL: Unexpected value return from test at %s\n", at); \ + exit(3); \ + } \ + } \ + } + +#define ABRT(code) SIGNALLED_AT(code, 1, AT) +#define OK(code) SIGNALLED_AT(code, 0, AT); +#define ABRT_AT(code,at) SIGNALLED_AT(code, 1, at) +#define OK_AT(code,at) SIGNALLED_AT(code, 0, at) diff --git a/src/plugins/e-acsl/tests/builtin/strcat.c b/src/plugins/e-acsl/tests/builtin/strcat.c new file mode 100644 index 0000000000000000000000000000000000000000..3edb44098d8a2a370612d97953a0ccded31a2819 --- /dev/null +++ b/src/plugins/e-acsl/tests/builtin/strcat.c @@ -0,0 +1,66 @@ +/* run.config + COMMENT: Test `strcat` and `strncat` E-ACSL built-ins +*/ + +#include "signalled.h" +#include <string.h> +#include <stdlib.h> + +int main(int argc, const char **argv) { + char *const_str = "abcd"; + char *unalloc_str = malloc(5); + char *_barrier = malloc(1); + char *empty_str = ""; + free(unalloc_str); + { + /* strcat */ + char dest1[9] = "dcba"; + char dest2[8] = "dcba"; + char dest3[5] = "----"; + char dest4[10] = "dcba"; + char *pd1 = &dest1; + char *pd2 = &dest2; + char *pd3 = &dest3; + char *pd4 = &dest4; + + /* strcat */ + OK(strcat(dest1, const_str)); // enough space in dest [ok] + OK(strcat(dest3, empty_str)); // enough space in dest (concat with empty) [ok] + ABRT(strcat(dest2, const_str)); // insufficient space in dest [abort] + ABRT(strcat(unalloc_str, const_str)); // unallocated in dest [abort] + ABRT(strcat(dest2, unalloc_str)); // unallocated in src [abort] + ABRT(strcat(NULL, "")); // NULL in dest [abort] + ABRT(strcat(dest1, NULL)); // NULL in src [abort] + ABRT(strcat(const_str, const_str)); // immutable in dest [abort] + ABRT(strcat(pd1, pd1)); // overlapping spaces (same address) [abort] + ABRT(strcat(pd1 + 3, pd1)); // overlapping spaces [abort] + ABRT(strcat(pd4 + 4, pd4)); // overlapping spaces [abort] + OK(pd4[5] = '\0'; strcat(pd4 + 5, pd4)); // non-overlapping + } + { + /* strncat */ + char dest1[9] = "dcba"; + char dest2[8] = "dcba"; + char dest3[5] = "----"; + char dest4[10] = "dcba"; + char *pd1 = &dest1; + char *pd2 = &dest2; + char *pd3 = &dest3; + char *pd4 = &dest4; + /* strncat */ + OK(strncat(dest1, const_str, 4)); // enough space in dest + ABRT(strncat(dest2, const_str, 4)); // insufficient space in dest + ABRT(strncat(unalloc_str, const_str, 1)); // unallocated in dest [abort] + ABRT(strncat(dest2, unalloc_str, 1)); // unallocated in src [abort] + ABRT(strncat(NULL, const_str, 1)); // NULL in dest [abort] + ABRT(strncat(dest2, NULL, 1)); // NULL in src [abort] + ABRT(strncat(const_str, const_str, 1)); // immutable in dest [abort] + + ABRT(strncat(pd1, pd1, 1)); // overlapping spaces (same address) [abort] + ABRT(strncat(pd1 + 3, pd1, 5)); // overlapping spaces [abort] + ABRT(strncat(pd4 + 4, pd4, 5)); // overlapping spaces [abort] + } + return 0; +} + + diff --git a/src/plugins/e-acsl/tests/builtin/strcmp.c b/src/plugins/e-acsl/tests/builtin/strcmp.c new file mode 100644 index 0000000000000000000000000000000000000000..eaf63cb7e24a981a225df14570dac5227b415d83 --- /dev/null +++ b/src/plugins/e-acsl/tests/builtin/strcmp.c @@ -0,0 +1,94 @@ +/* run.config + COMMENT: Test `strcmp` and `strncmp` E-ACSL built-ins +*/ + +#include "signalled.h" +#include <string.h> +#include <stdlib.h> + +static inline void fail_ncomp(int cond, char *fmt, int l, int r) { + if (cond) { + fprintf(stderr, fmt, l, r); + abort(); + } +} + +#define EQ(l,r) fail_ncomp(l != r, "comparison failure: %d == %d\n", l, r) +#define NEQ(l,r) fail_ncomp(l == r, "comparison failure: %d != %d\n", l, r) + +int main(int argc, const char **argv) { + const char *cl = "abc", + *cr = "abc"; + + char al[4] = "abc", + ar[4] = "abc"; + + char *dl = strdup("abc"), + *dr = strdup("abc"); + + int res; + /* strcmp {{{ */ + + OK(EQ(strcmp(cl, cr),0)); // valid comparison of constants [ok] + OK(EQ(strcmp(al, ar),0)); // valid comparison of stack strings [ok] + OK(EQ(strcmp(dl, dr),0)); // valid comparison of heap strings [ok] + + al[3] = 'a'; + ABRT(EQ(strcmp(al, ar),0)); // unterminated in left stack [ok] + ar[3] = 'a'; al[3] = 0; + ABRT(EQ(strcmp(al, ar),0)); // unterminated in right stack [ok] + dl[3] = 'a'; + ABRT(EQ(strcmp(dl, dr),0)); // unterminated in left heap [ok] + dr[3] = 'a'; dl[3] = 0; + ABRT(EQ(strcmp(dl, dr),0)); // unterminated in right heap [ok] + + ABRT(EQ(strcmp(dl, NULL),0)); // NULL in left [ok] + ABRT(EQ(strcmp(NULL, dr),0)); // NULL in right [ok] + + free(dl); + free(dr); + + ABRT(EQ(strcmp(dl, ar),0)); // dangling in left [ok] + ABRT(EQ(strcmp(al, dr),0)); // dangling in right [ok] + + /* }}} */ + + /* strncmp {{{ */ + + dl = strdup("abc"), + dr = strdup("abc"); + + char nal[4] = "abc", + nar[4] = "abc"; + + OK(EQ(strncmp(cl, cr, 3),0)); // valid comparison of constants [ok] + OK(EQ(strncmp(nal, nar, 3),0)); // valid comparison of stack strings [ok] + OK(EQ(strncmp(dl, dr, 3),0)); // valid comparison of heap strings [ok] + // Still ok because there is a terminator + OK(EQ(strncmp(nal, nar, 6),0)); // valid comparison of stack strings [ok] + OK(EQ(strncmp(dl, dr, 6),0)); // valid comparison of heap strings [ok] + + nal[3] = 'd'; + // no terminator but within allocated length [ok] + OK(NEQ(strncmp(nal, nar, 4),0)); + nar[3] = 'd'; nal[3] = 0; + OK(NEQ(strncmp(nal, nar, 4),0)); + dl[3] = 'd'; + OK(NEQ(strncmp(dl, dr, 4),0)); + dr[3] = 'd'; dl[3] = 0; + OK(NEQ(strncmp(dl, dr, 4),0)); + + // no terminator but outside allocated length [abort] + ABRT(res = strncmp(nal, nar, 5)); + nal[3] = 'd'; nar[3] = 0; + ABRT(res = strncmp(al, ar, 5)); + ABRT(res = strncmp(dl, dr, 5)); + dl[3] = 'd'; dr[3] = 0; + ABRT(res = strncmp(dl, dr, 5)); + + free(dl); + free(dr); + + /* }}} */ + return 0; +} diff --git a/src/plugins/e-acsl/tests/builtin/strcpy.c b/src/plugins/e-acsl/tests/builtin/strcpy.c new file mode 100644 index 0000000000000000000000000000000000000000..425d98815a41a2e103ef270f0abd3ce8f27a10d8 --- /dev/null +++ b/src/plugins/e-acsl/tests/builtin/strcpy.c @@ -0,0 +1,45 @@ +/* run.config + COMMENT: Test `strcpy` and `strncpy` E-ACSL built-ins +*/ + +#include "signalled.h" +#include <string.h> +#include <stdlib.h> + +int main(int argc, const char **argv) { + char empty_str[1] = ""; + char *const_str = "abcd"; + char *src = strdup("abcd"); + char *dest1 = malloc(5); + char *dest2 = malloc(4); + char dest3[256] = "abcd"; + size_t len = 0; + + char *unalloc_str = malloc(5); char* _barrier = malloc(1); free(unalloc_str); + + /* strcpy */ + OK(strcpy(dest1, src)); // heap allocated, sufficient space [ok] + OK(strcpy(empty_str, "")); // copy empty string [ok] + ABRT(strcpy(dest2, src)); // heap allocated, insufficient space [abort] + ABRT(strcpy(unalloc_str, src)); // unallocated [abort] + ABRT(strcpy(const_str, src)); // read-only in dest [abort] + OK(strcpy(src, const_str)); // read-only in src [ok] + ABRT(strcpy(src, src)); // same address, overlapping [abort] + OK(strcpy(dest3 + 5, dest3)); // same string, non-overlapping [ok] + ABRT(strcpy(dest3 + 4, dest3)); // same string, overlapping [abort] + + /* strncpy */ + OK(strncpy(dest1, src, 5)); // heap allocated, sufficient space [ok] + ABRT(strncpy(dest1, src, 6)); // heap allocated, insufficient space [abort] + ABRT(strncpy(unalloc_str, src, 5)); // unallocated [abort] + ABRT(strncpy(const_str, src, 5)); // read-only in dest [abort] + OK(strncpy(src, const_str, 5)); // read-only in src [ok] + ABRT(strncpy(src, src, 5)); // same address, overlapping [abort] + OK(strncpy(dest3 + 5, dest3, 5)); // same string, non-overlapping [ok] + ABRT(strncpy(dest3 + 4, dest3, 5)); // same string, overlapping [abort] + + free(src); + free(dest1); + free(dest2); + return 0; +} diff --git a/src/plugins/e-acsl/tests/builtin/strlen.c b/src/plugins/e-acsl/tests/builtin/strlen.c new file mode 100644 index 0000000000000000000000000000000000000000..fd95215e70851cce422ef894574e10be84c8f964 --- /dev/null +++ b/src/plugins/e-acsl/tests/builtin/strlen.c @@ -0,0 +1,32 @@ +/* run.config + COMMENT: Test `strlen` E-ACSL built-ins +*/ + +#include "signalled.h" +#include <string.h> +#include <stdlib.h> + +#define EQ(l,r) if (l != r) abort(); + +int main(int argc, const char **argv) { + int len; + char *empty_str = ""; + char *heap_str = strdup("the cat"); + char stack_str[] = "the dog"; + char *const_str = "the hog"; + + OK(EQ(len = strlen(empty_str),0)); // strlen on a valid (zero-length) string [ok] + OK(EQ(len = strlen(heap_str),7)); // strlen on a heap string [ok] + OK(EQ(len = strlen(stack_str),7)); // strlen on a stack string [ok] + OK(EQ(len = strlen(const_str),7)); // strlen on a const string [ok] + + heap_str[7] = 'a'; + stack_str[7] = 'a'; + ABRT(EQ(len = strlen(heap_str),7)); // strlen on unterminated heap string [abort] + ABRT(EQ(len = strlen(stack_str),7)); // strlen on unterminated stack string [abort] + free(heap_str); + ABRT(EQ(len = strlen(heap_str),7)); // strlen on invalid heap string [abort] + return 0; +} + + diff --git a/src/plugins/e-acsl/tests/builtin/test_config_ci b/src/plugins/e-acsl/tests/builtin/test_config_ci new file mode 100644 index 0000000000000000000000000000000000000000..5978357b4e5bba0940ff12302fdcd61c6d85eced --- /dev/null +++ b/src/plugins/e-acsl/tests/builtin/test_config_ci @@ -0,0 +1 @@ +STDOPT: #"-e-acsl-replace-libc-functions" diff --git a/src/plugins/e-acsl/tests/builtin/test_config_dev b/src/plugins/e-acsl/tests/builtin/test_config_dev new file mode 100644 index 0000000000000000000000000000000000000000..005fe8281f61d26966dd3001d194c045c994bd51 --- /dev/null +++ b/src/plugins/e-acsl/tests/builtin/test_config_dev @@ -0,0 +1,4 @@ +MACRO: DEST @PTEST_RESULT@/gen_@PTEST_NAME@ +MACRO: OUT @PTEST_NAME@.res.log +MACRO: ERR @PTEST_NAME@.err.log +EXEC: ./scripts/e-acsl-gcc.sh --libc-replacements -q -c -X --frama-c-extra="-journal-disable -verbose 0 -kernel-warn-key *=inactive" -o @DEST@.run.c -O @DEST@.out @PTEST_FILE@ > @PTEST_RESULT@/@OUT@ 2> @PTEST_RESULT@/@ERR@ && ./@DEST@.e-acsl > /dev/null diff --git a/src/plugins/e-acsl/tests/constructs/false.i b/src/plugins/e-acsl/tests/constructs/false.i new file mode 100644 index 0000000000000000000000000000000000000000..37de71490f85e836751d503498020cb626f4e9f8 --- /dev/null +++ b/src/plugins/e-acsl/tests/constructs/false.i @@ -0,0 +1,8 @@ +/* run.config + COMMENT: assert \false +*/ +int main(void) { + int x = 0; + if (x) /*@ assert \false; */ ; + return 0; +} diff --git a/src/plugins/e-acsl/tests/constructs/function_contract.i b/src/plugins/e-acsl/tests/constructs/function_contract.i new file mode 100644 index 0000000000000000000000000000000000000000..90eca5e7829d3e1e7911aca5d02d25ff4b61a872 --- /dev/null +++ b/src/plugins/e-acsl/tests/constructs/function_contract.i @@ -0,0 +1,86 @@ +/* run.config + COMMENT: function contract +*/ + +int X = 0, Y = 2; + +// one ensures +/*@ ensures X == 1; */ +void f(void) { X = 1; } + +// several ensures +/*@ ensures X == 2; + @ ensures Y == 2; */ +void g(void) { X = 2; } + +// one requires +/*@ requires X == 2; */ +void h(void) { X += 1; } + +// several requires +/*@ requires X == 3; + @ requires Y == 2; */ +void i(void) { X += Y; } + +// several behaviors +/*@ behavior b1: + @ requires X == 5; + @ ensures X == 3; + @ behavior b2: + @ requires X == 3 + Y; + @ requires Y == 2; + @ ensures X == Y + 1; */ +void j(void) { X = 3; } + +// mix requires and assumes +/*@ behavior b1: + @ assumes X == 1; + @ requires X == 0; + @ behavior b2: + @ assumes X == 3; + @ assumes Y == 2; + @ requires X == 3; + @ requires X + Y == 5; */ +void k(void) { X += Y; } + +// mix ensures + contract on return +/*@ ensures X == 5; */ +int l() { + /*@ assert Y == 2; */ + return X; +} + +// mix ensures and assumes +/*@ behavior b1: + @ assumes X == 7; + @ ensures X == 95; + @ behavior b2: + @ assumes X == 5; + @ assumes Y == 2; + @ ensures X == 7; + @ ensures X == \old(X) + Y; */ +void m(void) { X += Y; } + +// mix requires, ensures and assumes +/*@ requires X > 0; + @ requires X < 10; + @ behavior b1: + @ assumes X == 7; + @ ensures X == 8; + @ behavior b2: + @ assumes X == 5; + @ ensures X == 98; */ +void n(void) { X ++; } + +int main(void) { + f(); + g(); + h(); + i(); + j(); + k(); + l(); + m(); + n(); + return 0; +} diff --git a/src/plugins/e-acsl/tests/constructs/ghost.i b/src/plugins/e-acsl/tests/constructs/ghost.i new file mode 100644 index 0000000000000000000000000000000000000000..e7c4414b6b1a5f982a63d1616112f415c466d593 --- /dev/null +++ b/src/plugins/e-acsl/tests/constructs/ghost.i @@ -0,0 +1,17 @@ +/* run.config + COMMENT: ghost code +*/ + +/*@ ghost int G = 0; */ +/*@ ghost int *P; */ + +// /*@ ghost int foo(int *x) { return *x + 1; } */ + +int main(void) { + /*@ ghost P = &G; */ ; + /*@ ghost int *q = P; */ + /*@ ghost (*P)++; */ + /*@ assert *q == G; */ + // /*@ ghost G = foo(&G); */ + // /*@ assert G == 2; */ +} diff --git a/src/plugins/e-acsl/tests/constructs/invariant.i b/src/plugins/e-acsl/tests/constructs/invariant.i new file mode 100644 index 0000000000000000000000000000000000000000..76cbdb63c7169236217d0cb3a519aea09562eafd --- /dev/null +++ b/src/plugins/e-acsl/tests/constructs/invariant.i @@ -0,0 +1,14 @@ +/* run.config_ci + COMMENT: invariant + STDOPT: +"-slevel 11" +*/ + +int main(void) { + int x = 0; + for(int i = 0; i < 10; i++) { + /*@ invariant 0 <= i < 10; */ + x += i; + /*@ invariant i <= x; */ + } + return 0; +} diff --git a/src/plugins/e-acsl/tests/constructs/labeled_stmt.i b/src/plugins/e-acsl/tests/constructs/labeled_stmt.i new file mode 100644 index 0000000000000000000000000000000000000000..1c4be5a49017c78ada50299b0efa4ccd603a8084 --- /dev/null +++ b/src/plugins/e-acsl/tests/constructs/labeled_stmt.i @@ -0,0 +1,15 @@ +/* run.config + COMMENT: labeled stmt and gotos +*/ + +int X = 0; + +/*@ ensures X == 3; */ +int main(void) { + goto L1; + L1: /*@ assert X == 0; */ X = 1; + goto L2; + L2: /*@ requires X == 1; ensures X == 2; */ X = 2; + if (X) { X = 3; return 0; } + return 0; +} diff --git a/src/plugins/e-acsl/tests/constructs/lazy.i b/src/plugins/e-acsl/tests/constructs/lazy.i new file mode 100644 index 0000000000000000000000000000000000000000..c63e2764e36df8481c526a948655c46d7fcc35a1 --- /dev/null +++ b/src/plugins/e-acsl/tests/constructs/lazy.i @@ -0,0 +1,31 @@ +/* run.config + COMMENT: terms and predicates using lazy operators +*/ + +int main(void) { + int x = 0, y = 1; + + // lazy predicates + /*@ assert x == 0 && y == 1; */ + /*@ assert ! (x != 0 && y == 1/0); */ + /*@ assert y == 1 || x == 1; */ + /*@ assert x == 0 || y == 1/0; */ + /*@ assert x == 0 ==> y == 1; */ + /*@ assert x == 1 ==> y == 1/0; */ + /*@ assert x ? x : y; */ + /*@ assert y ? y : x; */ + /*@ assert x == 1 ? x == 18 : x == 0; */ + + // these predicates are not lazy, but are encoded by lazy ones + /*@ assert x == 2 <==> y == 3; */ + /*@ assert x == 0 <==> y == 1; */ + + // lazy terms + /*@ assert (x ? x : y) == (x == 0); */ + /*@ assert (x && y) || y; */ // converted into predicate by the kernel + /*@ assert (x || y) && y == 1; */ // converted into predicate by the kernel + /*@ assert (x || y) == y; */ + /*@ assert (x && y) == x; */ + + return 0; +} diff --git a/src/plugins/e-acsl/tests/constructs/loop.i b/src/plugins/e-acsl/tests/constructs/loop.i new file mode 100644 index 0000000000000000000000000000000000000000..4b0b3193ee1d889a17180daf26e085cd7a67cd0c --- /dev/null +++ b/src/plugins/e-acsl/tests/constructs/loop.i @@ -0,0 +1,37 @@ +/* run.config_ci + COMMENT: loop invariants + STDOPT: +"-slevel 160" +*/ + +void simple_loop() { + int sum = 0; + /*@ loop invariant 0 <= i <= 10; */ + for(int i = 0; i < 10; i++) + sum +=i; +} + +void nested_loops() { + int t[10][15]; + /*@ loop invariant 0 <= i <= 10; */ + for(int i = 0; i < 10; i++) + /*@ loop invariant 0 <= j <= 15; + @ loop invariant + @ \forall integer k,l; 0 <= k < i && 0 <= l < j ==> t[k][l] == k * l; */ + for(int j = 0; j < 15; j++) + t[i][j] = i * j; +} + +void unnatural_loop() { + int x = 0; + /*@ loop invariant 0 <= i <= 6; */ + for(int i = 0; i < 10; i++) { + if (x == 5) break; + x = i; + } +} + +int main(void) { + simple_loop(); + nested_loops(); + unnatural_loop(); +} diff --git a/src/plugins/e-acsl/tests/constructs/nested_code_annot.i b/src/plugins/e-acsl/tests/constructs/nested_code_annot.i new file mode 100644 index 0000000000000000000000000000000000000000..9e5f6cd72b5c6aeab1c25ab66040afdfbe450f76 --- /dev/null +++ b/src/plugins/e-acsl/tests/constructs/nested_code_annot.i @@ -0,0 +1,25 @@ +/* run.config + COMMENT: structured stmt with several code annotations inside +*/ + +int main(void) { + int x = 0, y = 1; + /*@ assert x < y; */ + /*@ requires x == 0; + @ ensures x >= 1; */ + { + if (x) /*@ assert \false; */ ; + else { + /*@ requires x == 0; + @ ensures x == 1; */ + x++; + if (x) { + /*@ requires x == 1; + @ ensures x == 2; */ + x++; + } + else /*@ assert \false; */ ; + } + } + return 0; +} diff --git a/src/plugins/e-acsl/tests/constructs/oracle_ci/false.res.oracle b/src/plugins/e-acsl/tests/constructs/oracle_ci/false.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..efd026311297e55d8fefb674326118e6ece88624 --- /dev/null +++ b/src/plugins/e-acsl/tests/constructs/oracle_ci/false.res.oracle @@ -0,0 +1,2 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". diff --git a/src/plugins/e-acsl/tests/constructs/oracle_ci/function_contract.res.oracle b/src/plugins/e-acsl/tests/constructs/oracle_ci/function_contract.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..efd026311297e55d8fefb674326118e6ece88624 --- /dev/null +++ b/src/plugins/e-acsl/tests/constructs/oracle_ci/function_contract.res.oracle @@ -0,0 +1,2 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". diff --git a/src/plugins/e-acsl/tests/constructs/oracle_ci/gen_false.c b/src/plugins/e-acsl/tests/constructs/oracle_ci/gen_false.c new file mode 100644 index 0000000000000000000000000000000000000000..9f3347b69ee042803f86d26a05a1a2fe85ba147f --- /dev/null +++ b/src/plugins/e-acsl/tests/constructs/oracle_ci/gen_false.c @@ -0,0 +1,16 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +int main(void) +{ + int __retres; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + int x = 0; + if (x) + /*@ assert \false; */ + __e_acsl_assert(0,(char *)"Assertion",(char *)"main",(char *)"\\false",6); + __retres = 0; + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/constructs/oracle_ci/gen_function_contract.c b/src/plugins/e-acsl/tests/constructs/oracle_ci/gen_function_contract.c new file mode 100644 index 0000000000000000000000000000000000000000..f760965e0b8a379eb5a1c6ac845bd1a434216aa6 --- /dev/null +++ b/src/plugins/e-acsl/tests/constructs/oracle_ci/gen_function_contract.c @@ -0,0 +1,348 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +extern int __e_acsl_sound_verdict; + +int X = 0; +int Y = 2; +/*@ ensures X ≡ 1; */ +void __gen_e_acsl_f(void); + +void f(void) +{ + X = 1; + return; +} + +/*@ ensures X ≡ 2; + ensures Y ≡ 2; */ +void __gen_e_acsl_g(void); + +void g(void) +{ + X = 2; + return; +} + +/*@ requires X ≡ 2; */ +void __gen_e_acsl_h(void); + +void h(void) +{ + X ++; + return; +} + +/*@ requires X ≡ 3; + requires Y ≡ 2; */ +void __gen_e_acsl_i(void); + +void i(void) +{ + X += Y; + return; +} + +/*@ behavior b1: + requires X ≡ 5; + ensures X ≡ 3; + + behavior b2: + requires X ≡ 3 + Y; + requires Y ≡ 2; + ensures X ≡ Y + 1; + */ +void __gen_e_acsl_j(void); + +void j(void) +{ + X = 3; + return; +} + +/*@ behavior b1: + assumes X ≡ 1; + requires X ≡ 0; + + behavior b2: + assumes X ≡ 3; + assumes Y ≡ 2; + requires X ≡ 3; + requires X + Y ≡ 5; + */ +void __gen_e_acsl_k(void); + +void k(void) +{ + X += Y; + return; +} + +/*@ ensures X ≡ 5; */ +int __gen_e_acsl_l(void); + +int l(void) +{ + /*@ assert Y ≡ 2; */ + __e_acsl_assert(Y == 2,(char *)"Assertion",(char *)"l",(char *)"Y == 2",49); + return X; +} + +/*@ behavior b1: + assumes X ≡ 7; + ensures X ≡ 95; + + behavior b2: + assumes X ≡ 5; + assumes Y ≡ 2; + ensures X ≡ 7; + ensures X ≡ \old(X) + Y; + */ +void __gen_e_acsl_m(void); + +void m(void) +{ + X += Y; + return; +} + +/*@ requires X > 0; + requires X < 10; + + behavior b1: + assumes X ≡ 7; + ensures X ≡ 8; + + behavior b2: + assumes X ≡ 5; + ensures X ≡ 98; + */ +void __gen_e_acsl_n(void); + +void n(void) +{ + X ++; + return; +} + +int main(void) +{ + int __retres; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + __gen_e_acsl_f(); + __gen_e_acsl_g(); + __gen_e_acsl_h(); + __gen_e_acsl_i(); + __gen_e_acsl_j(); + __gen_e_acsl_k(); + __gen_e_acsl_l(); + __gen_e_acsl_m(); + __gen_e_acsl_n(); + __retres = 0; + return __retres; +} + +/*@ requires X > 0; + requires X < 10; + + behavior b1: + assumes X ≡ 7; + ensures X ≡ 8; + + behavior b2: + assumes X ≡ 5; + ensures X ≡ 98; + */ +void __gen_e_acsl_n(void) +{ + int __gen_e_acsl_at_2; + int __gen_e_acsl_at; + __gen_e_acsl_at_2 = X == 5; + __gen_e_acsl_at = X == 7; + __e_acsl_assert(X > 0,(char *)"Precondition",(char *)"n",(char *)"X > 0", + 65); + __e_acsl_assert(X < 10,(char *)"Precondition",(char *)"n",(char *)"X < 10", + 66); + n(); + { + int __gen_e_acsl_implies; + int __gen_e_acsl_implies_2; + if (! __gen_e_acsl_at) __gen_e_acsl_implies = 1; + else __gen_e_acsl_implies = X == 8; + __e_acsl_assert(__gen_e_acsl_implies,(char *)"Postcondition",(char *)"n", + (char *)"\\old(X == 7) ==> X == 8",69); + if (! __gen_e_acsl_at_2) __gen_e_acsl_implies_2 = 1; + else __gen_e_acsl_implies_2 = X == 98; + __e_acsl_assert(__gen_e_acsl_implies_2,(char *)"Postcondition", + (char *)"n",(char *)"\\old(X == 5) ==> X == 98",72); + return; + } +} + +/*@ behavior b1: + assumes X ≡ 7; + ensures X ≡ 95; + + behavior b2: + assumes X ≡ 5; + assumes Y ≡ 2; + ensures X ≡ 7; + ensures X ≡ \old(X) + Y; + */ +void __gen_e_acsl_m(void) +{ + long __gen_e_acsl_at_4; + int __gen_e_acsl_at_3; + int __gen_e_acsl_at_2; + int __gen_e_acsl_at; + __gen_e_acsl_at_4 = (long)X; + { + int __gen_e_acsl_and_2; + if (X == 5) __gen_e_acsl_and_2 = Y == 2; else __gen_e_acsl_and_2 = 0; + __gen_e_acsl_at_3 = __gen_e_acsl_and_2; + } + { + int __gen_e_acsl_and; + if (X == 5) __gen_e_acsl_and = Y == 2; else __gen_e_acsl_and = 0; + __gen_e_acsl_at_2 = __gen_e_acsl_and; + } + __gen_e_acsl_at = X == 7; + m(); + { + int __gen_e_acsl_implies; + int __gen_e_acsl_implies_2; + int __gen_e_acsl_implies_3; + if (! __gen_e_acsl_at) __gen_e_acsl_implies = 1; + else __gen_e_acsl_implies = X == 95; + __e_acsl_assert(__gen_e_acsl_implies,(char *)"Postcondition",(char *)"m", + (char *)"\\old(X == 7) ==> X == 95",56); + if (! __gen_e_acsl_at_2) __gen_e_acsl_implies_2 = 1; + else __gen_e_acsl_implies_2 = X == 7; + __e_acsl_assert(__gen_e_acsl_implies_2,(char *)"Postcondition", + (char *)"m",(char *)"\\old(X == 5 && Y == 2) ==> X == 7", + 60); + if (! __gen_e_acsl_at_3) __gen_e_acsl_implies_3 = 1; + else __gen_e_acsl_implies_3 = (long)X == __gen_e_acsl_at_4 + Y; + __e_acsl_assert(__gen_e_acsl_implies_3,(char *)"Postcondition", + (char *)"m", + (char *)"\\old(X == 5 && Y == 2) ==> X == \\old(X) + Y", + 61); + return; + } +} + +/*@ ensures X ≡ 5; */ +int __gen_e_acsl_l(void) +{ + int __retres; + __retres = l(); + __e_acsl_assert(X == 5,(char *)"Postcondition",(char *)"l", + (char *)"X == 5",47); + return __retres; +} + +/*@ behavior b1: + assumes X ≡ 1; + requires X ≡ 0; + + behavior b2: + assumes X ≡ 3; + assumes Y ≡ 2; + requires X ≡ 3; + requires X + Y ≡ 5; + */ +void __gen_e_acsl_k(void) +{ + { + int __gen_e_acsl_implies; + int __gen_e_acsl_and; + int __gen_e_acsl_implies_2; + int __gen_e_acsl_and_2; + int __gen_e_acsl_implies_3; + if (! (X == 1)) __gen_e_acsl_implies = 1; + else __gen_e_acsl_implies = X == 0; + __e_acsl_assert(__gen_e_acsl_implies,(char *)"Precondition",(char *)"k", + (char *)"X == 1 ==> X == 0",38); + if (X == 3) __gen_e_acsl_and = Y == 2; else __gen_e_acsl_and = 0; + if (! __gen_e_acsl_and) __gen_e_acsl_implies_2 = 1; + else __gen_e_acsl_implies_2 = X == 3; + __e_acsl_assert(__gen_e_acsl_implies_2,(char *)"Precondition", + (char *)"k",(char *)"X == 3 && Y == 2 ==> X == 3",42); + if (X == 3) __gen_e_acsl_and_2 = Y == 2; else __gen_e_acsl_and_2 = 0; + if (! __gen_e_acsl_and_2) __gen_e_acsl_implies_3 = 1; + else __gen_e_acsl_implies_3 = X + (long)Y == 5L; + __e_acsl_assert(__gen_e_acsl_implies_3,(char *)"Precondition", + (char *)"k",(char *)"X == 3 && Y == 2 ==> X + Y == 5",43); + } + k(); + return; +} + +/*@ behavior b1: + requires X ≡ 5; + ensures X ≡ 3; + + behavior b2: + requires X ≡ 3 + Y; + requires Y ≡ 2; + ensures X ≡ Y + 1; + */ +void __gen_e_acsl_j(void) +{ + __e_acsl_assert(X == 5,(char *)"Precondition",(char *)"j",(char *)"X == 5", + 27); + __e_acsl_assert((long)X == 3L + Y,(char *)"Precondition",(char *)"j", + (char *)"X == 3 + Y",30); + __e_acsl_assert(Y == 2,(char *)"Precondition",(char *)"j",(char *)"Y == 2", + 31); + j(); + __e_acsl_assert(X == 3,(char *)"Postcondition",(char *)"j", + (char *)"X == 3",28); + __e_acsl_assert((long)X == Y + 1L,(char *)"Postcondition",(char *)"j", + (char *)"X == Y + 1",32); + return; +} + +/*@ requires X ≡ 3; + requires Y ≡ 2; */ +void __gen_e_acsl_i(void) +{ + __e_acsl_assert(X == 3,(char *)"Precondition",(char *)"i",(char *)"X == 3", + 21); + __e_acsl_assert(Y == 2,(char *)"Precondition",(char *)"i",(char *)"Y == 2", + 22); + i(); + return; +} + +/*@ requires X ≡ 2; */ +void __gen_e_acsl_h(void) +{ + __e_acsl_assert(X == 2,(char *)"Precondition",(char *)"h",(char *)"X == 2", + 17); + h(); + return; +} + +/*@ ensures X ≡ 2; + ensures Y ≡ 2; */ +void __gen_e_acsl_g(void) +{ + g(); + __e_acsl_assert(X == 2,(char *)"Postcondition",(char *)"g", + (char *)"X == 2",12); + __e_acsl_assert(Y == 2,(char *)"Postcondition",(char *)"g", + (char *)"Y == 2",13); + return; +} + +/*@ ensures X ≡ 1; */ +void __gen_e_acsl_f(void) +{ + f(); + __e_acsl_assert(X == 1,(char *)"Postcondition",(char *)"f", + (char *)"X == 1",8); + return; +} + + diff --git a/src/plugins/e-acsl/tests/constructs/oracle_ci/gen_ghost.c b/src/plugins/e-acsl/tests/constructs/oracle_ci/gen_ghost.c new file mode 100644 index 0000000000000000000000000000000000000000..739fa7d6e261508da085eabb09d62028f0e56f21 --- /dev/null +++ b/src/plugins/e-acsl/tests/constructs/oracle_ci/gen_ghost.c @@ -0,0 +1,69 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +int G = 0; +int *P; +void __e_acsl_globals_init(void) +{ + static char __e_acsl_already_run = 0; + if (! __e_acsl_already_run) { + __e_acsl_already_run = 1; + __e_acsl_store_block((void *)(& P),(size_t)8); + __e_acsl_full_init((void *)(& P)); + __e_acsl_store_block((void *)(& G),(size_t)4); + __e_acsl_full_init((void *)(& G)); + } + return; +} + +int main(void) +{ + int __retres; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + __e_acsl_globals_init(); + P = & G; + int *q = P; + __e_acsl_store_block((void *)(& q),(size_t)8); + __e_acsl_full_init((void *)(& q)); + { + int __gen_e_acsl_valid_read; + int __gen_e_acsl_valid; + __e_acsl_initialize((void *)P,sizeof(int)); + __gen_e_acsl_valid_read = __e_acsl_valid_read((void *)P,sizeof(int), + (void *)P,(void *)(& P)); + __e_acsl_assert(__gen_e_acsl_valid_read,(char *)"RTE",(char *)"main", + (char *)"mem_access: \\valid_read(P)",13); + __gen_e_acsl_valid = __e_acsl_valid((void *)P,sizeof(int),(void *)P, + (void *)(& P)); + __e_acsl_assert(__gen_e_acsl_valid,(char *)"RTE",(char *)"main", + (char *)"mem_access: \\valid(P)",13); + } + (*P) ++; + /*@ assert *q ≡ G; */ + { + int __gen_e_acsl_initialized; + int __gen_e_acsl_and; + __gen_e_acsl_initialized = __e_acsl_initialized((void *)(& q), + sizeof(int *)); + if (__gen_e_acsl_initialized) { + int __gen_e_acsl_valid_read_2; + __gen_e_acsl_valid_read_2 = __e_acsl_valid_read((void *)q,sizeof(int), + (void *)q, + (void *)(& q)); + __gen_e_acsl_and = __gen_e_acsl_valid_read_2; + } + else __gen_e_acsl_and = 0; + __e_acsl_assert(__gen_e_acsl_and,(char *)"RTE",(char *)"main", + (char *)"mem_access: \\valid_read(q)",14); + __e_acsl_assert(*q == G,(char *)"Assertion",(char *)"main", + (char *)"*q == G",14); + } + __retres = 0; + __e_acsl_delete_block((void *)(& P)); + __e_acsl_delete_block((void *)(& G)); + __e_acsl_delete_block((void *)(& q)); + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/constructs/oracle_ci/gen_invariant.c b/src/plugins/e-acsl/tests/constructs/oracle_ci/gen_invariant.c new file mode 100644 index 0000000000000000000000000000000000000000..e1ac038ae1dfed70bb62129533b15f7fc74269cf --- /dev/null +++ b/src/plugins/e-acsl/tests/constructs/oracle_ci/gen_invariant.c @@ -0,0 +1,30 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +int main(void) +{ + int __retres; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + int x = 0; + { + int i = 0; + while (i < 10) { + /*@ invariant 0 ≤ i < 10; */ + { + int __gen_e_acsl_and; + if (0 <= i) __gen_e_acsl_and = i < 10; else __gen_e_acsl_and = 0; + __e_acsl_assert(__gen_e_acsl_and,(char *)"Invariant",(char *)"main", + (char *)"0 <= i < 10",9); + } + x += i; + /*@ invariant i ≤ x; */ + __e_acsl_assert(i <= x,(char *)"Invariant",(char *)"main", + (char *)"i <= x",11); + i ++; + } + } + __retres = 0; + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/constructs/oracle_ci/gen_labeled_stmt.c b/src/plugins/e-acsl/tests/constructs/oracle_ci/gen_labeled_stmt.c new file mode 100644 index 0000000000000000000000000000000000000000..0ef6c89d829e50c190d93f0d7114905074753eca --- /dev/null +++ b/src/plugins/e-acsl/tests/constructs/oracle_ci/gen_labeled_stmt.c @@ -0,0 +1,50 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +extern int __e_acsl_sound_verdict; + +int X = 0; +/*@ ensures X ≡ 3; */ +int main(void); + +int __gen_e_acsl_main(void) +{ + int __retres; + goto L1; + L1: + /*@ assert X ≡ 0; */ + __e_acsl_assert(X == 0,(char *)"Assertion",(char *)"main",(char *)"X == 0", + 10); + X = 1; + goto L2; + L2: + /*@ requires X ≡ 1; + ensures X ≡ 2; */ + { + __e_acsl_assert(X == 1,(char *)"Precondition",(char *)"main", + (char *)"X == 1",12); + X = 2; + __e_acsl_assert(X == 2,(char *)"Postcondition",(char *)"main", + (char *)"X == 2",12); + } + if (X) { + X = 3; + __retres = 0; + goto return_label; + } + __retres = 0; + return_label: return __retres; +} + +/*@ ensures X ≡ 3; */ +int main(void) +{ + int __retres; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + __retres = __gen_e_acsl_main(); + __e_acsl_assert(X == 3,(char *)"Postcondition",(char *)"main", + (char *)"X == 3",7); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/constructs/oracle_ci/gen_lazy.c b/src/plugins/e-acsl/tests/constructs/oracle_ci/gen_lazy.c new file mode 100644 index 0000000000000000000000000000000000000000..7f13d27dcc9d5c0d4ac08e2bdcef6400bf925d66 --- /dev/null +++ b/src/plugins/e-acsl/tests/constructs/oracle_ci/gen_lazy.c @@ -0,0 +1,169 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +int main(void) +{ + int __retres; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + int x = 0; + int y = 1; + /*@ assert x ≡ 0 ∧ y ≡ 1; */ + { + int __gen_e_acsl_and; + if (x == 0) __gen_e_acsl_and = y == 1; else __gen_e_acsl_and = 0; + __e_acsl_assert(__gen_e_acsl_and,(char *)"Assertion",(char *)"main", + (char *)"x == 0 && y == 1",9); + } + /*@ assert ¬(x ≢ 0 ∧ y ≡ 1 / 0); */ + { + int __gen_e_acsl_and_2; + if (x != 0) { + __e_acsl_assert(0,(char *)"RTE",(char *)"main", + (char *)"division_by_zero: 0 != 0",10); + __gen_e_acsl_and_2 = y == 1 / 0; + } + else __gen_e_acsl_and_2 = 0; + __e_acsl_assert(! __gen_e_acsl_and_2,(char *)"Assertion",(char *)"main", + (char *)"!(x != 0 && y == 1 / 0)",10); + } + /*@ assert y ≡ 1 ∨ x ≡ 1; */ + { + int __gen_e_acsl_or; + if (y == 1) __gen_e_acsl_or = 1; else __gen_e_acsl_or = x == 1; + __e_acsl_assert(__gen_e_acsl_or,(char *)"Assertion",(char *)"main", + (char *)"y == 1 || x == 1",11); + } + /*@ assert x ≡ 0 ∨ y ≡ 1 / 0; */ + { + int __gen_e_acsl_or_2; + if (x == 0) __gen_e_acsl_or_2 = 1; + else { + __e_acsl_assert(0,(char *)"RTE",(char *)"main", + (char *)"division_by_zero: 0 != 0",12); + __gen_e_acsl_or_2 = y == 1 / 0; + } + __e_acsl_assert(__gen_e_acsl_or_2,(char *)"Assertion",(char *)"main", + (char *)"x == 0 || y == 1 / 0",12); + } + /*@ assert x ≡ 0 ⇒ y ≡ 1; */ + { + int __gen_e_acsl_implies; + if (! (x == 0)) __gen_e_acsl_implies = 1; + else __gen_e_acsl_implies = y == 1; + __e_acsl_assert(__gen_e_acsl_implies,(char *)"Assertion",(char *)"main", + (char *)"x == 0 ==> y == 1",13); + } + /*@ assert x ≡ 1 ⇒ y ≡ 1 / 0; */ + { + int __gen_e_acsl_implies_2; + if (! (x == 1)) __gen_e_acsl_implies_2 = 1; + else { + __e_acsl_assert(0,(char *)"RTE",(char *)"main", + (char *)"division_by_zero: 0 != 0",14); + __gen_e_acsl_implies_2 = y == 1 / 0; + } + __e_acsl_assert(__gen_e_acsl_implies_2,(char *)"Assertion", + (char *)"main",(char *)"x == 1 ==> y == 1 / 0",14); + } + /*@ assert x ≢ 0? x ≢ 0: y ≢ 0; */ + { + int __gen_e_acsl_if; + if (x != 0) __gen_e_acsl_if = x != 0; else __gen_e_acsl_if = y != 0; + __e_acsl_assert(__gen_e_acsl_if,(char *)"Assertion",(char *)"main", + (char *)"x != 0? x != 0: y != 0",15); + } + /*@ assert y ≢ 0? y ≢ 0: x ≢ 0; */ + { + int __gen_e_acsl_if_2; + if (y != 0) __gen_e_acsl_if_2 = y != 0; else __gen_e_acsl_if_2 = x != 0; + __e_acsl_assert(__gen_e_acsl_if_2,(char *)"Assertion",(char *)"main", + (char *)"y != 0? y != 0: x != 0",16); + } + /*@ assert x ≡ 1? x ≡ 18: x ≡ 0; */ + { + int __gen_e_acsl_if_3; + if (x == 1) __gen_e_acsl_if_3 = x == 18; else __gen_e_acsl_if_3 = x == 0; + __e_acsl_assert(__gen_e_acsl_if_3,(char *)"Assertion",(char *)"main", + (char *)"x == 1? x == 18: x == 0",17); + } + /*@ assert x ≡ 2 ⇔ y ≡ 3; */ + { + int __gen_e_acsl_implies_3; + int __gen_e_acsl_equiv; + if (! (x == 2)) __gen_e_acsl_implies_3 = 1; + else __gen_e_acsl_implies_3 = y == 3; + if (__gen_e_acsl_implies_3) { + int __gen_e_acsl_implies_4; + if (! (y == 3)) __gen_e_acsl_implies_4 = 1; + else __gen_e_acsl_implies_4 = x == 2; + __gen_e_acsl_equiv = __gen_e_acsl_implies_4; + } + else __gen_e_acsl_equiv = 0; + __e_acsl_assert(__gen_e_acsl_equiv,(char *)"Assertion",(char *)"main", + (char *)"x == 2 <==> y == 3",20); + } + /*@ assert x ≡ 0 ⇔ y ≡ 1; */ + { + int __gen_e_acsl_implies_5; + int __gen_e_acsl_equiv_2; + if (! (x == 0)) __gen_e_acsl_implies_5 = 1; + else __gen_e_acsl_implies_5 = y == 1; + if (__gen_e_acsl_implies_5) { + int __gen_e_acsl_implies_6; + if (! (y == 1)) __gen_e_acsl_implies_6 = 1; + else __gen_e_acsl_implies_6 = x == 0; + __gen_e_acsl_equiv_2 = __gen_e_acsl_implies_6; + } + else __gen_e_acsl_equiv_2 = 0; + __e_acsl_assert(__gen_e_acsl_equiv_2,(char *)"Assertion",(char *)"main", + (char *)"x == 0 <==> y == 1",21); + } + /*@ assert ((x ≢ 0? x: y) ≢ 0) ≡ (x ≡ 0); */ + { + int __gen_e_acsl_if_4; + if (x != 0) __gen_e_acsl_if_4 = x; else __gen_e_acsl_if_4 = y; + __e_acsl_assert((__gen_e_acsl_if_4 != 0) == (x == 0),(char *)"Assertion", + (char *)"main", + (char *)"((x != 0? x: y) != 0) == (x == 0)",24); + } + /*@ assert (x ≢ 0 ∧ y ≢ 0) ∨ y ≢ 0; */ + { + int __gen_e_acsl_and_3; + int __gen_e_acsl_or_3; + if (x != 0) __gen_e_acsl_and_3 = y != 0; else __gen_e_acsl_and_3 = 0; + if (__gen_e_acsl_and_3) __gen_e_acsl_or_3 = 1; + else __gen_e_acsl_or_3 = y != 0; + __e_acsl_assert(__gen_e_acsl_or_3,(char *)"Assertion",(char *)"main", + (char *)"(x != 0 && y != 0) || y != 0",25); + } + /*@ assert (x ≢ 0 ∨ y ≢ 0) ∧ y ≡ 1; */ + { + int __gen_e_acsl_or_4; + int __gen_e_acsl_and_4; + if (x != 0) __gen_e_acsl_or_4 = 1; else __gen_e_acsl_or_4 = y != 0; + if (__gen_e_acsl_or_4) __gen_e_acsl_and_4 = y == 1; + else __gen_e_acsl_and_4 = 0; + __e_acsl_assert(__gen_e_acsl_and_4,(char *)"Assertion",(char *)"main", + (char *)"(x != 0 || y != 0) && y == 1",26); + } + /*@ assert (x ≢ 0 ∨ y ≢ 0) ≡ (y ≢ 0); */ + { + int __gen_e_acsl_or_5; + if (x != 0) __gen_e_acsl_or_5 = 1; else __gen_e_acsl_or_5 = y != 0; + __e_acsl_assert(__gen_e_acsl_or_5 == (y != 0),(char *)"Assertion", + (char *)"main",(char *)"(x != 0 || y != 0) == (y != 0)", + 27); + } + /*@ assert (x ≢ 0 ∧ y ≢ 0) ≡ (x ≢ 0); */ + { + int __gen_e_acsl_and_5; + if (x != 0) __gen_e_acsl_and_5 = y != 0; else __gen_e_acsl_and_5 = 0; + __e_acsl_assert(__gen_e_acsl_and_5 == (x != 0),(char *)"Assertion", + (char *)"main",(char *)"(x != 0 && y != 0) == (x != 0)", + 28); + } + __retres = 0; + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/constructs/oracle_ci/gen_loop.c b/src/plugins/e-acsl/tests/constructs/oracle_ci/gen_loop.c new file mode 100644 index 0000000000000000000000000000000000000000..fec7a5f6f53723bc5e6364c8f304f7763a61d162 --- /dev/null +++ b/src/plugins/e-acsl/tests/constructs/oracle_ci/gen_loop.c @@ -0,0 +1,215 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +void simple_loop(void) +{ + int sum = 0; + { + int i = 0; + { + { + int __gen_e_acsl_and; + if (0 <= i) __gen_e_acsl_and = i <= 10; else __gen_e_acsl_and = 0; + __e_acsl_assert(__gen_e_acsl_and,(char *)"Invariant", + (char *)"simple_loop",(char *)"0 <= i <= 10",8); + } + /*@ loop invariant 0 ≤ i ≤ 10; */ + while (i < 10) { + sum += i; + { + int __gen_e_acsl_and_2; + i ++; + if (0 <= i) __gen_e_acsl_and_2 = i <= 10; + else __gen_e_acsl_and_2 = 0; + __e_acsl_assert(__gen_e_acsl_and_2,(char *)"Invariant", + (char *)"simple_loop",(char *)"0 <= i <= 10",8); + } + } + } + } + return; +} + +void nested_loops(void) +{ + int t[10][15]; + int i = 0; + { + { + int __gen_e_acsl_and; + if (0 <= i) __gen_e_acsl_and = i <= 10; else __gen_e_acsl_and = 0; + __e_acsl_assert(__gen_e_acsl_and,(char *)"Invariant", + (char *)"nested_loops",(char *)"0 <= i <= 10",15); + } + /*@ loop invariant 0 ≤ i ≤ 10; */ + while (i < 10) { + { + int j = 0; + { + { + int __gen_e_acsl_forall; + int __gen_e_acsl_k; + int __gen_e_acsl_l; + int __gen_e_acsl_and_2; + __gen_e_acsl_forall = 1; + __gen_e_acsl_k = 0; + while (1) { + if (__gen_e_acsl_k < i) ; else break; + __gen_e_acsl_l = 0; + while (1) { + if (__gen_e_acsl_l < j) ; else break; + __e_acsl_assert(__gen_e_acsl_l < 15,(char *)"RTE", + (char *)"nested_loops", + (char *)"index_bound: __gen_e_acsl_l < 15", + 19); + __e_acsl_assert(0 <= __gen_e_acsl_l,(char *)"RTE", + (char *)"nested_loops", + (char *)"index_bound: 0 <= __gen_e_acsl_l", + 19); + __e_acsl_assert(__gen_e_acsl_k < 10,(char *)"RTE", + (char *)"nested_loops", + (char *)"index_bound: __gen_e_acsl_k < 10", + 19); + __e_acsl_assert(0 <= __gen_e_acsl_k,(char *)"RTE", + (char *)"nested_loops", + (char *)"index_bound: 0 <= __gen_e_acsl_k", + 19); + if ((long)t[__gen_e_acsl_k][__gen_e_acsl_l] == __gen_e_acsl_k * (long)__gen_e_acsl_l) + ; + else { + __gen_e_acsl_forall = 0; + goto e_acsl_end_loop1; + } + __gen_e_acsl_l ++; + } + __gen_e_acsl_k ++; + } + e_acsl_end_loop1: ; + __e_acsl_assert(__gen_e_acsl_forall,(char *)"Invariant", + (char *)"nested_loops", + (char *)"\\forall integer k, integer l; 0 <= k < i && 0 <= l < j ==> t[k][l] == k * l", + 19); + if (0 <= j) __gen_e_acsl_and_2 = j <= 15; + else __gen_e_acsl_and_2 = 0; + __e_acsl_assert(__gen_e_acsl_and_2,(char *)"Invariant", + (char *)"nested_loops",(char *)"0 <= j <= 15",17); + } + /*@ loop invariant 0 ≤ j ≤ 15; + loop invariant + ∀ ℤ k, ℤ l; + 0 ≤ k < i ∧ 0 ≤ l < j ⇒ t[k][l] ≡ k * l; + */ + while (j < 15) { + t[i][j] = i * j; + { + int __gen_e_acsl_and_3; + int __gen_e_acsl_forall_2; + int __gen_e_acsl_k_2; + int __gen_e_acsl_l_2; + j ++; + if (0 <= j) __gen_e_acsl_and_3 = j <= 15; + else __gen_e_acsl_and_3 = 0; + __e_acsl_assert(__gen_e_acsl_and_3,(char *)"Invariant", + (char *)"nested_loops",(char *)"0 <= j <= 15", + 17); + __gen_e_acsl_forall_2 = 1; + __gen_e_acsl_k_2 = 0; + while (1) { + if (__gen_e_acsl_k_2 < i) ; else break; + __gen_e_acsl_l_2 = 0; + while (1) { + if (__gen_e_acsl_l_2 < j) ; else break; + __e_acsl_assert(__gen_e_acsl_l_2 < 15,(char *)"RTE", + (char *)"nested_loops", + (char *)"index_bound: __gen_e_acsl_l_2 < 15", + 19); + __e_acsl_assert(0 <= __gen_e_acsl_l_2,(char *)"RTE", + (char *)"nested_loops", + (char *)"index_bound: 0 <= __gen_e_acsl_l_2", + 19); + __e_acsl_assert(__gen_e_acsl_k_2 < 10,(char *)"RTE", + (char *)"nested_loops", + (char *)"index_bound: __gen_e_acsl_k_2 < 10", + 19); + __e_acsl_assert(0 <= __gen_e_acsl_k_2,(char *)"RTE", + (char *)"nested_loops", + (char *)"index_bound: 0 <= __gen_e_acsl_k_2", + 19); + /*@ assert + Eva: initialization: + \initialized(&t[__gen_e_acsl_k_2][__gen_e_acsl_l_2]); + */ + if ((long)t[__gen_e_acsl_k_2][__gen_e_acsl_l_2] == + __gen_e_acsl_k_2 * (long)__gen_e_acsl_l_2) ; + else { + __gen_e_acsl_forall_2 = 0; + goto e_acsl_end_loop2; + } + __gen_e_acsl_l_2 ++; + } + __gen_e_acsl_k_2 ++; + } + e_acsl_end_loop2: ; + __e_acsl_assert(__gen_e_acsl_forall_2,(char *)"Invariant", + (char *)"nested_loops", + (char *)"\\forall integer k, integer l; 0 <= k < i && 0 <= l < j ==> t[k][l] == k * l", + 19); + } + } + } + } + { + int __gen_e_acsl_and_4; + i ++; + if (0 <= i) __gen_e_acsl_and_4 = i <= 10; + else __gen_e_acsl_and_4 = 0; + __e_acsl_assert(__gen_e_acsl_and_4,(char *)"Invariant", + (char *)"nested_loops",(char *)"0 <= i <= 10",15); + } + } + } + return; +} + +void unnatural_loop(void) +{ + int x = 0; + { + int i = 0; + { + { + int __gen_e_acsl_and; + if (0 <= i) __gen_e_acsl_and = i <= 6; else __gen_e_acsl_and = 0; + __e_acsl_assert(__gen_e_acsl_and,(char *)"Invariant", + (char *)"unnatural_loop",(char *)"0 <= i <= 6",26); + } + /*@ loop invariant 0 ≤ i ≤ 6; */ + while (i < 10) { + if (x == 5) break; + x = i; + { + int __gen_e_acsl_and_2; + i ++; + if (0 <= i) __gen_e_acsl_and_2 = i <= 6; + else __gen_e_acsl_and_2 = 0; + __e_acsl_assert(__gen_e_acsl_and_2,(char *)"Invariant", + (char *)"unnatural_loop",(char *)"0 <= i <= 6",26); + } + } + } + } + return; +} + +int main(void) +{ + int __retres; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + simple_loop(); + nested_loops(); + unnatural_loop(); + __retres = 0; + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/constructs/oracle_ci/gen_nested_code_annot.c b/src/plugins/e-acsl/tests/constructs/oracle_ci/gen_nested_code_annot.c new file mode 100644 index 0000000000000000000000000000000000000000..d9ba989ebc1c7b35d587e8e63fbed1136d47d2fc --- /dev/null +++ b/src/plugins/e-acsl/tests/constructs/oracle_ci/gen_nested_code_annot.c @@ -0,0 +1,54 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +int main(void) +{ + int __retres; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + int x = 0; + int y = 1; + /*@ assert x < y; */ + __e_acsl_assert(x < y,(char *)"Assertion",(char *)"main",(char *)"x < y",7); + /*@ requires x ≡ 0; + ensures x ≥ 1; */ + { + __e_acsl_assert(x == 0,(char *)"Precondition",(char *)"main", + (char *)"x == 0",8); + if (x) + /*@ assert \false; */ + __e_acsl_assert(0,(char *)"Assertion",(char *)"main",(char *)"\\false", + 11); + else { + /*@ requires x ≡ 0; + ensures x ≡ 1; */ + { + __e_acsl_assert(x == 0,(char *)"Precondition",(char *)"main", + (char *)"x == 0",13); + x ++; + __e_acsl_assert(x == 1,(char *)"Postcondition",(char *)"main", + (char *)"x == 1",14); + } + if (x) { + /*@ requires x ≡ 1; + ensures x ≡ 2; */ + { + __e_acsl_assert(x == 1,(char *)"Precondition",(char *)"main", + (char *)"x == 1",17); + x ++; + __e_acsl_assert(x == 2,(char *)"Postcondition",(char *)"main", + (char *)"x == 2",18); + } + } + else + /*@ assert \false; */ + __e_acsl_assert(0,(char *)"Assertion",(char *)"main", + (char *)"\\false",21); + } + __e_acsl_assert(x >= 1,(char *)"Postcondition",(char *)"main", + (char *)"x >= 1",9); + } + __retres = 0; + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/constructs/oracle_ci/gen_result.c b/src/plugins/e-acsl/tests/constructs/oracle_ci/gen_result.c new file mode 100644 index 0000000000000000000000000000000000000000..fe66b29db23d30b6bfe5480ae673fc037920ed9a --- /dev/null +++ b/src/plugins/e-acsl/tests/constructs/oracle_ci/gen_result.c @@ -0,0 +1,86 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +extern int __e_acsl_sound_verdict; + +/*@ ensures \result ≡ (int)(\old(x) - \old(x)); */ +int __gen_e_acsl_f(int x); + +int f(int x) +{ + x = 0; + return x; +} + +int Y = 1; +/*@ ensures \result ≡ \old(x); + ensures \result ≡ Y; */ +int __gen_e_acsl_g(int x); + +int g(int x) +{ + return x; +} + +/*@ ensures \result ≡ 0; */ +int __gen_e_acsl_h(void); + +int h(void) +{ + int __retres; + __retres = 0; + return __retres; +} + +int main(void) +{ + int __retres; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + __gen_e_acsl_f(1); + __gen_e_acsl_g(Y); + __gen_e_acsl_h(); + __retres = 0; + return __retres; +} + +/*@ ensures \result ≡ 0; */ +int __gen_e_acsl_h(void) +{ + int __retres; + __retres = h(); + __e_acsl_assert(__retres == 0,(char *)"Postcondition",(char *)"h", + (char *)"\\result == 0",18); + return __retres; +} + +/*@ ensures \result ≡ \old(x); + ensures \result ≡ Y; */ +int __gen_e_acsl_g(int x) +{ + int __gen_e_acsl_at; + int __retres; + __gen_e_acsl_at = x; + __retres = g(x); + __e_acsl_assert(__retres == __gen_e_acsl_at,(char *)"Postcondition", + (char *)"g",(char *)"\\result == \\old(x)",12); + __e_acsl_assert(__retres == Y,(char *)"Postcondition",(char *)"g", + (char *)"\\result == Y",13); + return __retres; +} + +/*@ ensures \result ≡ (int)(\old(x) - \old(x)); */ +int __gen_e_acsl_f(int x) +{ + int __gen_e_acsl_at_2; + long __gen_e_acsl_at; + int __retres; + __gen_e_acsl_at_2 = x; + __gen_e_acsl_at = (long)x; + __retres = f(x); + __e_acsl_assert(__retres == (int)(__gen_e_acsl_at - __gen_e_acsl_at_2), + (char *)"Postcondition",(char *)"f", + (char *)"\\result == (int)(\\old(x) - \\old(x))",5); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/constructs/oracle_ci/gen_stmt_contract.c b/src/plugins/e-acsl/tests/constructs/oracle_ci/gen_stmt_contract.c new file mode 100644 index 0000000000000000000000000000000000000000..e9680da760b90a4a75717e36fdbf9c4a54943d3a --- /dev/null +++ b/src/plugins/e-acsl/tests/constructs/oracle_ci/gen_stmt_contract.c @@ -0,0 +1,127 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +int main(void) +{ + int __retres; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + int x = 0; + int y = 2; + /*@ ensures x ≡ 1; */ + { + x = 1; + __e_acsl_assert(x == 1,(char *)"Postcondition",(char *)"main", + (char *)"x == 1",8); + } + /*@ ensures x ≡ 2; + ensures y ≡ 2; + ensures x ≡ 2 ∧ y ≡ 2; */ + { + int __gen_e_acsl_and; + x = 2; + __e_acsl_assert(x == 2,(char *)"Postcondition",(char *)"main", + (char *)"x == 2",11); + __e_acsl_assert(y == 2,(char *)"Postcondition",(char *)"main", + (char *)"y == 2",12); + if (x == 2) __gen_e_acsl_and = y == 2; else __gen_e_acsl_and = 0; + __e_acsl_assert(__gen_e_acsl_and,(char *)"Postcondition",(char *)"main", + (char *)"x == 2 && y == 2",13); + } + /*@ requires x ≡ 2; */ + { + __e_acsl_assert(x == 2,(char *)"Precondition",(char *)"main", + (char *)"x == 2",17); + x ++; + } + /*@ requires x ≡ 3; + requires y ≡ 2; */ + { + __e_acsl_assert(x == 3,(char *)"Precondition",(char *)"main", + (char *)"x == 3",20); + __e_acsl_assert(y == 2,(char *)"Precondition",(char *)"main", + (char *)"y == 2",21); + x += y; + } + /*@ behavior b1: + requires x ≡ 5; + ensures x ≡ 3; + + behavior b2: + requires x ≡ 3 + y; + requires y ≡ 2; + ensures x ≡ y + 1; + */ + { + __e_acsl_assert(x == 5,(char *)"Precondition",(char *)"main", + (char *)"x == 5",25); + __e_acsl_assert((long)x == 3L + y,(char *)"Precondition",(char *)"main", + (char *)"x == 3 + y",28); + __e_acsl_assert(y == 2,(char *)"Precondition",(char *)"main", + (char *)"y == 2",29); + x = 3; + __e_acsl_assert(x == 3,(char *)"Postcondition",(char *)"main", + (char *)"x == 3",26); + __e_acsl_assert((long)x == y + 1L,(char *)"Postcondition",(char *)"main", + (char *)"x == y + 1",30); + } + /*@ behavior b1: + assumes x ≡ 1; + requires x ≡ 0; + + behavior b2: + assumes x ≡ 3; + assumes y ≡ 2; + requires x ≡ 3; + requires x + y ≡ 5; + */ + { + { + int __gen_e_acsl_implies; + int __gen_e_acsl_and_2; + int __gen_e_acsl_implies_2; + int __gen_e_acsl_and_3; + int __gen_e_acsl_implies_3; + if (! (x == 1)) __gen_e_acsl_implies = 1; + else __gen_e_acsl_implies = x == 0; + __e_acsl_assert(__gen_e_acsl_implies,(char *)"Precondition", + (char *)"main",(char *)"x == 1 ==> x == 0",35); + if (x == 3) __gen_e_acsl_and_2 = y == 2; else __gen_e_acsl_and_2 = 0; + if (! __gen_e_acsl_and_2) __gen_e_acsl_implies_2 = 1; + else __gen_e_acsl_implies_2 = x == 3; + __e_acsl_assert(__gen_e_acsl_implies_2,(char *)"Precondition", + (char *)"main",(char *)"x == 3 && y == 2 ==> x == 3", + 39); + if (x == 3) __gen_e_acsl_and_3 = y == 2; else __gen_e_acsl_and_3 = 0; + if (! __gen_e_acsl_and_3) __gen_e_acsl_implies_3 = 1; + else __gen_e_acsl_implies_3 = x + (long)y == 5L; + __e_acsl_assert(__gen_e_acsl_implies_3,(char *)"Precondition", + (char *)"main", + (char *)"x == 3 && y == 2 ==> x + y == 5",40); + } + x += y; + } + /*@ requires x ≡ 5; */ + { + __e_acsl_assert(x == 5,(char *)"Precondition",(char *)"main", + (char *)"x == 5",43); + /*@ requires y ≡ 2; */ + { + __e_acsl_assert(y == 2,(char *)"Precondition",(char *)"main", + (char *)"y == 2",44); + x += y; + } + } + /*@ requires x ≡ 7; + ensures x ≡ 7; */ + { + __e_acsl_assert(x == 7,(char *)"Precondition",(char *)"main", + (char *)"x == 7",47); + __retres = 0; + goto return_label; + __e_acsl_assert(x == 7,(char *)"Postcondition",(char *)"main", + (char *)"x == 7",48); + } + return_label: return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/constructs/oracle_ci/gen_true.c b/src/plugins/e-acsl/tests/constructs/oracle_ci/gen_true.c new file mode 100644 index 0000000000000000000000000000000000000000..9a2046bedd03b082c8bbdeb9d6df03a43dad4341 --- /dev/null +++ b/src/plugins/e-acsl/tests/constructs/oracle_ci/gen_true.c @@ -0,0 +1,16 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +int main(void) +{ + int __retres; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + int x = 0; + x ++; + /*@ assert \true; */ + __e_acsl_assert(1,(char *)"Assertion",(char *)"main",(char *)"\\true",8); + __retres = 0; + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/constructs/oracle_ci/gen_typedef.c b/src/plugins/e-acsl/tests/constructs/oracle_ci/gen_typedef.c new file mode 100644 index 0000000000000000000000000000000000000000..8c4b76f26827ecc33bad97d6eabe7c6eb645491a --- /dev/null +++ b/src/plugins/e-acsl/tests/constructs/oracle_ci/gen_typedef.c @@ -0,0 +1,17 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +typedef unsigned char uint8; +int main(void) +{ + int __retres; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + uint8 x = (unsigned char)0; + /*@ assert x ≡ 0; */ + __e_acsl_assert((int)x == 0,(char *)"Assertion",(char *)"main", + (char *)"x == 0",9); + __retres = 0; + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/constructs/oracle_ci/ghost.res.oracle b/src/plugins/e-acsl/tests/constructs/oracle_ci/ghost.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..efd026311297e55d8fefb674326118e6ece88624 --- /dev/null +++ b/src/plugins/e-acsl/tests/constructs/oracle_ci/ghost.res.oracle @@ -0,0 +1,2 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". diff --git a/src/plugins/e-acsl/tests/constructs/oracle_ci/invariant.res.oracle b/src/plugins/e-acsl/tests/constructs/oracle_ci/invariant.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..efd026311297e55d8fefb674326118e6ece88624 --- /dev/null +++ b/src/plugins/e-acsl/tests/constructs/oracle_ci/invariant.res.oracle @@ -0,0 +1,2 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". diff --git a/src/plugins/e-acsl/tests/constructs/oracle_ci/labeled_stmt.res.oracle b/src/plugins/e-acsl/tests/constructs/oracle_ci/labeled_stmt.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..efd026311297e55d8fefb674326118e6ece88624 --- /dev/null +++ b/src/plugins/e-acsl/tests/constructs/oracle_ci/labeled_stmt.res.oracle @@ -0,0 +1,2 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". diff --git a/src/plugins/e-acsl/tests/constructs/oracle_ci/lazy.res.oracle b/src/plugins/e-acsl/tests/constructs/oracle_ci/lazy.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..efd026311297e55d8fefb674326118e6ece88624 --- /dev/null +++ b/src/plugins/e-acsl/tests/constructs/oracle_ci/lazy.res.oracle @@ -0,0 +1,2 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". diff --git a/src/plugins/e-acsl/tests/constructs/oracle_ci/loop.res.oracle b/src/plugins/e-acsl/tests/constructs/oracle_ci/loop.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..3ddc088c016438543c25b2cfac66013881da6335 --- /dev/null +++ b/src/plugins/e-acsl/tests/constructs/oracle_ci/loop.res.oracle @@ -0,0 +1,9 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". +[eva:alarm] tests/constructs/loop.i:19: Warning: + loop invariant got status unknown. +[eva:alarm] tests/constructs/loop.i:19: Warning: + function __e_acsl_assert: precondition got status invalid. +[eva:alarm] tests/constructs/loop.i:19: Warning: + accessing uninitialized left-value. + assert \initialized(&t[__gen_e_acsl_k_2][__gen_e_acsl_l_2]); diff --git a/src/plugins/e-acsl/tests/constructs/oracle_ci/nested_code_annot.res.oracle b/src/plugins/e-acsl/tests/constructs/oracle_ci/nested_code_annot.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..efd026311297e55d8fefb674326118e6ece88624 --- /dev/null +++ b/src/plugins/e-acsl/tests/constructs/oracle_ci/nested_code_annot.res.oracle @@ -0,0 +1,2 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". diff --git a/src/plugins/e-acsl/tests/constructs/oracle_ci/result.res.oracle b/src/plugins/e-acsl/tests/constructs/oracle_ci/result.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..efd026311297e55d8fefb674326118e6ece88624 --- /dev/null +++ b/src/plugins/e-acsl/tests/constructs/oracle_ci/result.res.oracle @@ -0,0 +1,2 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". diff --git a/src/plugins/e-acsl/tests/constructs/oracle_ci/stmt_contract.res.oracle b/src/plugins/e-acsl/tests/constructs/oracle_ci/stmt_contract.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..efd026311297e55d8fefb674326118e6ece88624 --- /dev/null +++ b/src/plugins/e-acsl/tests/constructs/oracle_ci/stmt_contract.res.oracle @@ -0,0 +1,2 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". diff --git a/src/plugins/e-acsl/tests/constructs/oracle_ci/true.res.oracle b/src/plugins/e-acsl/tests/constructs/oracle_ci/true.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..efd026311297e55d8fefb674326118e6ece88624 --- /dev/null +++ b/src/plugins/e-acsl/tests/constructs/oracle_ci/true.res.oracle @@ -0,0 +1,2 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". diff --git a/src/plugins/e-acsl/tests/constructs/oracle_ci/typedef.res.oracle b/src/plugins/e-acsl/tests/constructs/oracle_ci/typedef.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..efd026311297e55d8fefb674326118e6ece88624 --- /dev/null +++ b/src/plugins/e-acsl/tests/constructs/oracle_ci/typedef.res.oracle @@ -0,0 +1,2 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". diff --git a/src/plugins/e-acsl/tests/constructs/oracle_dev/false.res.oracle b/src/plugins/e-acsl/tests/constructs/oracle_dev/false.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..7b03a368b78507b4138ef777b52cfbb963f7a0a8 --- /dev/null +++ b/src/plugins/e-acsl/tests/constructs/oracle_dev/false.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/constructs/false.i (no preprocessing) diff --git a/src/plugins/e-acsl/tests/constructs/oracle_dev/function_contract.res.oracle b/src/plugins/e-acsl/tests/constructs/oracle_dev/function_contract.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..a26972504fc11c11cb0b4cef5dc3098de33f50f9 --- /dev/null +++ b/src/plugins/e-acsl/tests/constructs/oracle_dev/function_contract.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/constructs/function_contract.i (no preprocessing) diff --git a/src/plugins/e-acsl/tests/constructs/oracle_dev/ghost.res.oracle b/src/plugins/e-acsl/tests/constructs/oracle_dev/ghost.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..c88d3077a73d1a0859eb8b27a861254b12c7b37e --- /dev/null +++ b/src/plugins/e-acsl/tests/constructs/oracle_dev/ghost.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/constructs/ghost.i (no preprocessing) diff --git a/src/plugins/e-acsl/tests/constructs/oracle_dev/invariant.res.oracle b/src/plugins/e-acsl/tests/constructs/oracle_dev/invariant.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..bf1ef00efd5c9ce675530be79c853f6c7f5dc661 --- /dev/null +++ b/src/plugins/e-acsl/tests/constructs/oracle_dev/invariant.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/constructs/invariant.i (no preprocessing) diff --git a/src/plugins/e-acsl/tests/constructs/oracle_dev/labeled_stmt.res.oracle b/src/plugins/e-acsl/tests/constructs/oracle_dev/labeled_stmt.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..f970d17171ee2581d7d7f6be3d0fae73707be8d2 --- /dev/null +++ b/src/plugins/e-acsl/tests/constructs/oracle_dev/labeled_stmt.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/constructs/labeled_stmt.i (no preprocessing) diff --git a/src/plugins/e-acsl/tests/constructs/oracle_dev/lazy.res.oracle b/src/plugins/e-acsl/tests/constructs/oracle_dev/lazy.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..ade1e36d99e66024de2eda4d09cfd72bc0377643 --- /dev/null +++ b/src/plugins/e-acsl/tests/constructs/oracle_dev/lazy.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/constructs/lazy.i (no preprocessing) diff --git a/src/plugins/e-acsl/tests/constructs/oracle_dev/loop.res.oracle b/src/plugins/e-acsl/tests/constructs/oracle_dev/loop.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..84d2f0dd9410127e39335170feab7597534b1c14 --- /dev/null +++ b/src/plugins/e-acsl/tests/constructs/oracle_dev/loop.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/constructs/loop.i (no preprocessing) diff --git a/src/plugins/e-acsl/tests/constructs/oracle_dev/nested_code_annot.res.oracle b/src/plugins/e-acsl/tests/constructs/oracle_dev/nested_code_annot.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..79c41e376ff4d3e3a59dca0bf24993370504d131 --- /dev/null +++ b/src/plugins/e-acsl/tests/constructs/oracle_dev/nested_code_annot.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/constructs/nested_code_annot.i (no preprocessing) diff --git a/src/plugins/e-acsl/tests/constructs/oracle_dev/result.res.oracle b/src/plugins/e-acsl/tests/constructs/oracle_dev/result.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..b7000fff6c16bad99f08ac1e17b2f329a6292ead --- /dev/null +++ b/src/plugins/e-acsl/tests/constructs/oracle_dev/result.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/constructs/result.i (no preprocessing) diff --git a/src/plugins/e-acsl/tests/constructs/oracle_dev/stmt_contract.res.oracle b/src/plugins/e-acsl/tests/constructs/oracle_dev/stmt_contract.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..908fd31137c0504497dbb0b32676afc8e843b780 --- /dev/null +++ b/src/plugins/e-acsl/tests/constructs/oracle_dev/stmt_contract.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/constructs/stmt_contract.i (no preprocessing) diff --git a/src/plugins/e-acsl/tests/constructs/oracle_dev/true.res.oracle b/src/plugins/e-acsl/tests/constructs/oracle_dev/true.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..3b950952f857555f940f059c2ba5ff05d023283a --- /dev/null +++ b/src/plugins/e-acsl/tests/constructs/oracle_dev/true.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/constructs/true.i (no preprocessing) diff --git a/src/plugins/e-acsl/tests/constructs/oracle_dev/typedef.res.oracle b/src/plugins/e-acsl/tests/constructs/oracle_dev/typedef.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..bc4b2fca8240d19b78ea23ba7f785c8c25e90178 --- /dev/null +++ b/src/plugins/e-acsl/tests/constructs/oracle_dev/typedef.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/constructs/typedef.i (no preprocessing) diff --git a/src/plugins/e-acsl/tests/constructs/result.i b/src/plugins/e-acsl/tests/constructs/result.i new file mode 100644 index 0000000000000000000000000000000000000000..bae320b69ff040d389d0a712c98ad690f109ccc0 --- /dev/null +++ b/src/plugins/e-acsl/tests/constructs/result.i @@ -0,0 +1,26 @@ +/* run.config + COMMENT: \result +*/ + +/*@ ensures \result == (int)(x - x); */ +int f(int x) { + x = 0; + return x; } + +int Y = 1; + +/*@ ensures \result == x; + @ ensures \result == Y; */ +int g(int x) { + return x; +} + +/*@ ensures \result == 0; */ +int h() { return 0; } + +int main(void) { + f(1); + g(Y); + h(); + return 0; +} diff --git a/src/plugins/e-acsl/tests/constructs/stmt_contract.i b/src/plugins/e-acsl/tests/constructs/stmt_contract.i new file mode 100644 index 0000000000000000000000000000000000000000..3d105913dedf80485537533a730982636ee6ac4b --- /dev/null +++ b/src/plugins/e-acsl/tests/constructs/stmt_contract.i @@ -0,0 +1,50 @@ +/* run.config + COMMENT: stmt contract +*/ + +int main(void) { + int x = 0, y = 2; + // one ensures + /*@ ensures x == 1; */ + x = 1; + // several ensures + /*@ ensures x == 2; + @ ensures y == 2; + @ ensures x == 2 && y == 2; // generate local variables: see BTS #2339 + @*/ + x = 2; + // one requires + /*@ requires x == 2; */ + x = x + 1; + // several requires + /*@ requires x == 3; + @ requires y == 2; */ + x = x + y; + // several behaviors + /*@ behavior b1: + @ requires x == 5; + @ ensures x == 3; + @ behavior b2: + @ requires x == 3+y; + @ requires y == 2; + @ ensures x == y+1; */ + x = 3; + // mix requires and assumes + /*@ behavior b1: + @ assumes x == 1; + @ requires x == 0; + @ behavior b2: + @ assumes x == 3; + @ assumes y == 2; + @ requires x == 3; + @ requires x + y == 5; */ + x = x + y; + + /*@ requires x == 5; */ + /*@ requires y == 2; */ + x = x + y; + + /*@ requires x == 7; + @ ensures x == 7; */ + return 0; +} diff --git a/src/plugins/e-acsl/tests/constructs/true.i b/src/plugins/e-acsl/tests/constructs/true.i new file mode 100644 index 0000000000000000000000000000000000000000..d1624aa2f4f730b24a3d5299672c0ada2d3e77fd --- /dev/null +++ b/src/plugins/e-acsl/tests/constructs/true.i @@ -0,0 +1,10 @@ +/* run.config + COMMENT: assert \true +*/ +int main(void) { + int x = 0; + x++; /* prevent GCC's warning */ + ///*@ assert \true == 0; */ // \true as a term: not yet implemented + /*@ assert \true; */ + return 0; +} diff --git a/src/plugins/e-acsl/tests/constructs/typedef.i b/src/plugins/e-acsl/tests/constructs/typedef.i new file mode 100644 index 0000000000000000000000000000000000000000..afbbc15a43a2494579bbadc35c131c2e4f2590b8 --- /dev/null +++ b/src/plugins/e-acsl/tests/constructs/typedef.i @@ -0,0 +1,11 @@ +/* run.config + COMMENT: typedef (from a Bernard's bug report) +*/ + +typedef unsigned char uint8; + +int main(void) { + uint8 x = 0; + /*@ assert x == 0; */ ; + return 0; +} diff --git a/src/plugins/e-acsl/tests/examples/functions_contiki.c b/src/plugins/e-acsl/tests/examples/functions_contiki.c new file mode 100644 index 0000000000000000000000000000000000000000..382a1a64b9ef6fd97bc358a2ca031e1238d32935 --- /dev/null +++ b/src/plugins/e-acsl/tests/examples/functions_contiki.c @@ -0,0 +1,28 @@ +/* run.config + COMMENT: functions used in Contiki +*/ + +#include <stdlib.h> +#include <limits.h> + +struct list { + struct list *next; + int value; +}; + +/*@ + logic integer length_aux(struct list *l, integer n) = + n < 0 ? -1 : + l == NULL ? n : + n < INT_MAX ? length_aux(l->next, n+1) : + -1; + logic integer length(struct list *l) = length_aux(l, 0); +*/ + +int main (void) { + struct list node1, node2, node3; + node1.next = &node2; + node2.next = &node3; + struct list *l = &node1; + /*@ assert length(l) == 3; */ ; +} \ No newline at end of file diff --git a/src/plugins/e-acsl/tests/examples/linear_search.i b/src/plugins/e-acsl/tests/examples/linear_search.i new file mode 100644 index 0000000000000000000000000000000000000000..deaecad449293967d541cf34c15763192f8397e7 --- /dev/null +++ b/src/plugins/e-acsl/tests/examples/linear_search.i @@ -0,0 +1,37 @@ +/* run.config + COMMENT: linear search (example from the SAC'13 article) +*/ + +int A[10]; + +/*@ requires \forall integer i; 0 <= i < 9 ==> A[i] <= A[i+1]; + behavior exists: + assumes \exists integer j; 0 <= j < 10 && A[j] == elt; + ensures \result == 1; + behavior not_exists: + assumes \forall integer j; 0 <= j < 10 ==> A[j] != elt; + ensures \result == 0; */ +int search(int elt){ + int k; + // linear search in a sorted array + /*@ loop invariant 0 <= k <= 10; + @ loop invariant \forall integer i; 0 <= i < k ==> A[i] < elt; */ + for(k = 0; k < 10; k++) + if(A[k] == elt) return 1; // element found + else if(A[k] > elt) return 0; // element not found (sorted array) + return 0; // element not found +} + +int main(void) { + + int found; + for(int i = 0; i < 10; i++) A[i] = i * i; + + found = search(36); + /*@ assert found == 1; */ + + found = search(5); + /*@ assert found == 0; */ + + return 0; +} diff --git a/src/plugins/e-acsl/tests/examples/oracle_ci/functions_contiki.res.oracle b/src/plugins/e-acsl/tests/examples/oracle_ci/functions_contiki.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..2327ee08af4c360fa7edbcefdb921c527b678be7 --- /dev/null +++ b/src/plugins/e-acsl/tests/examples/oracle_ci/functions_contiki.res.oracle @@ -0,0 +1,7 @@ +[e-acsl] beginning translation. +[e-acsl] tests/examples/functions_contiki.c:27: Warning: + E-ACSL construct `logic functions with labels' is not yet supported. + Ignoring annotation. +[e-acsl] translation done in project "e-acsl". +[eva:alarm] tests/examples/functions_contiki.c:27: Warning: + assertion got status unknown. diff --git a/src/plugins/e-acsl/tests/examples/oracle_ci/gen_functions_contiki.c b/src/plugins/e-acsl/tests/examples/oracle_ci/gen_functions_contiki.c new file mode 100644 index 0000000000000000000000000000000000000000..259afb2e7cf7aff685e3f821c94a0a230968a678 --- /dev/null +++ b/src/plugins/e-acsl/tests/examples/oracle_ci/gen_functions_contiki.c @@ -0,0 +1,45 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +struct list { + struct list *next ; + int value ; +}; +/*@ +logic ℤ length_aux{L}(struct list *l, ℤ n) = + \at(n < 0? -1: + (l ≡ (struct list *)((void *)0)? n: + (n < 2147483647? length_aux(l->next, n + 1): -1)), + L); + */ +/*@ logic ℤ length{L}(struct list *l) = \at(length_aux(l, 0),L); + +*/ +int main(void) +{ + int __retres; + struct list node1; + struct list node2; + struct list node3; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + __e_acsl_store_block((void *)(& node3),(size_t)16); + __e_acsl_store_block((void *)(& node2),(size_t)16); + __e_acsl_store_block((void *)(& node1),(size_t)16); + __e_acsl_initialize((void *)(& node1.next),sizeof(struct list *)); + node1.next = & node2; + __e_acsl_initialize((void *)(& node2.next),sizeof(struct list *)); + node2.next = & node3; + struct list *l = & node1; + __e_acsl_store_block((void *)(& l),(size_t)8); + __e_acsl_full_init((void *)(& l)); + /*@ assert length(l) ≡ 3; */ ; + __retres = 0; + __e_acsl_delete_block((void *)(& l)); + __e_acsl_delete_block((void *)(& node3)); + __e_acsl_delete_block((void *)(& node2)); + __e_acsl_delete_block((void *)(& node1)); + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/examples/oracle_ci/gen_linear_search.c b/src/plugins/e-acsl/tests/examples/oracle_ci/gen_linear_search.c new file mode 100644 index 0000000000000000000000000000000000000000..462863825830545d0a0cc5ef18a83741e951c3b2 --- /dev/null +++ b/src/plugins/e-acsl/tests/examples/oracle_ci/gen_linear_search.c @@ -0,0 +1,237 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +extern int __e_acsl_sound_verdict; + +int A[10]; +/*@ requires ∀ ℤ i; 0 ≤ i < 9 ⇒ A[i] ≤ A[i + 1]; + + behavior exists: + assumes ∃ ℤ j; 0 ≤ j < 10 ∧ A[j] ≡ elt; + ensures \result ≡ 1; + + behavior not_exists: + assumes ∀ ℤ j; 0 ≤ j < 10 ⇒ A[j] ≢ elt; + ensures \result ≡ 0; + */ +int __gen_e_acsl_search(int elt); + +int search(int elt) +{ + int __retres; + int k; + k = 0; + { + { + int __gen_e_acsl_forall; + int __gen_e_acsl_i; + int __gen_e_acsl_and; + __gen_e_acsl_forall = 1; + __gen_e_acsl_i = 0; + while (1) { + if (__gen_e_acsl_i < k) ; else break; + __e_acsl_assert(__gen_e_acsl_i < 10,(char *)"RTE",(char *)"search", + (char *)"index_bound: __gen_e_acsl_i < 10",18); + __e_acsl_assert(0 <= __gen_e_acsl_i,(char *)"RTE",(char *)"search", + (char *)"index_bound: 0 <= __gen_e_acsl_i",18); + if (A[__gen_e_acsl_i] < elt) ; + else { + __gen_e_acsl_forall = 0; + goto e_acsl_end_loop1; + } + __gen_e_acsl_i ++; + } + e_acsl_end_loop1: ; + __e_acsl_assert(__gen_e_acsl_forall,(char *)"Invariant", + (char *)"search", + (char *)"\\forall integer i; 0 <= i < k ==> A[i] < elt", + 18); + if (0 <= k) __gen_e_acsl_and = k <= 10; else __gen_e_acsl_and = 0; + __e_acsl_assert(__gen_e_acsl_and,(char *)"Invariant",(char *)"search", + (char *)"0 <= k <= 10",17); + } + /*@ loop invariant 0 ≤ k ≤ 10; + loop invariant ∀ ℤ i; 0 ≤ i < k ⇒ A[i] < elt; + */ + while (k < 10) { + if (A[k] == elt) { + __retres = 1; + goto return_label; + } + else + if (A[k] > elt) { + __retres = 0; + goto return_label; + } + { + int __gen_e_acsl_and_2; + int __gen_e_acsl_forall_2; + int __gen_e_acsl_i_2; + k ++; + if (0 <= k) __gen_e_acsl_and_2 = k <= 10; + else __gen_e_acsl_and_2 = 0; + __e_acsl_assert(__gen_e_acsl_and_2,(char *)"Invariant", + (char *)"search",(char *)"0 <= k <= 10",17); + __gen_e_acsl_forall_2 = 1; + __gen_e_acsl_i_2 = 0; + while (1) { + if (__gen_e_acsl_i_2 < k) ; else break; + __e_acsl_assert(__gen_e_acsl_i_2 < 10,(char *)"RTE", + (char *)"search", + (char *)"index_bound: __gen_e_acsl_i_2 < 10",18); + __e_acsl_assert(0 <= __gen_e_acsl_i_2,(char *)"RTE", + (char *)"search", + (char *)"index_bound: 0 <= __gen_e_acsl_i_2",18); + if (A[__gen_e_acsl_i_2] < elt) ; + else { + __gen_e_acsl_forall_2 = 0; + goto e_acsl_end_loop2; + } + __gen_e_acsl_i_2 ++; + } + e_acsl_end_loop2: ; + __e_acsl_assert(__gen_e_acsl_forall_2,(char *)"Invariant", + (char *)"search", + (char *)"\\forall integer i; 0 <= i < k ==> A[i] < elt", + 18); + } + } + } + __retres = 0; + return_label: return __retres; +} + +int main(void) +{ + int __retres; + int found; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + { + int i = 0; + while (i < 10) { + A[i] = i * i; + i ++; + } + } + found = __gen_e_acsl_search(36); + /*@ assert found ≡ 1; */ + __e_acsl_assert(found == 1,(char *)"Assertion",(char *)"main", + (char *)"found == 1",31); + found = __gen_e_acsl_search(5); + /*@ assert found ≡ 0; */ + __e_acsl_assert(found == 0,(char *)"Assertion",(char *)"main", + (char *)"found == 0",34); + __retres = 0; + return __retres; +} + +/*@ requires ∀ ℤ i; 0 ≤ i < 9 ⇒ A[i] ≤ A[i + 1]; + + behavior exists: + assumes ∃ ℤ j; 0 ≤ j < 10 ∧ A[j] ≡ elt; + ensures \result ≡ 1; + + behavior not_exists: + assumes ∀ ℤ j; 0 ≤ j < 10 ⇒ A[j] ≢ elt; + ensures \result ≡ 0; + */ +int __gen_e_acsl_search(int elt) +{ + int __gen_e_acsl_at_2; + int __gen_e_acsl_at; + int __retres; + { + int __gen_e_acsl_forall_2; + int __gen_e_acsl_j_2; + __gen_e_acsl_forall_2 = 1; + __gen_e_acsl_j_2 = 0; + while (1) { + if (__gen_e_acsl_j_2 < 10) ; else break; + __e_acsl_assert(__gen_e_acsl_j_2 < 10,(char *)"RTE",(char *)"search", + (char *)"index_bound: __gen_e_acsl_j_2 < 10",12); + __e_acsl_assert(0 <= __gen_e_acsl_j_2,(char *)"RTE",(char *)"search", + (char *)"index_bound: 0 <= __gen_e_acsl_j_2",12); + if (A[__gen_e_acsl_j_2] != elt) ; + else { + __gen_e_acsl_forall_2 = 0; + goto e_acsl_end_loop5; + } + __gen_e_acsl_j_2 ++; + } + e_acsl_end_loop5: ; + __gen_e_acsl_at_2 = __gen_e_acsl_forall_2; + } + { + int __gen_e_acsl_exists; + int __gen_e_acsl_j; + __gen_e_acsl_exists = 0; + __gen_e_acsl_j = 0; + while (1) { + if (__gen_e_acsl_j < 10) ; else break; + __e_acsl_assert(__gen_e_acsl_j < 10,(char *)"RTE",(char *)"search", + (char *)"index_bound: __gen_e_acsl_j < 10",9); + __e_acsl_assert(0 <= __gen_e_acsl_j,(char *)"RTE",(char *)"search", + (char *)"index_bound: 0 <= __gen_e_acsl_j",9); + if (! (A[__gen_e_acsl_j] == elt)) ; + else { + __gen_e_acsl_exists = 1; + goto e_acsl_end_loop4; + } + __gen_e_acsl_j ++; + } + e_acsl_end_loop4: ; + __gen_e_acsl_at = __gen_e_acsl_exists; + } + { + int __gen_e_acsl_forall; + int __gen_e_acsl_i; + __gen_e_acsl_forall = 1; + __gen_e_acsl_i = 0; + while (1) { + if (__gen_e_acsl_i < 9) ; else break; + __e_acsl_assert((int)(__gen_e_acsl_i + 1L) < 10,(char *)"RTE", + (char *)"search", + (char *)"index_bound: (int)(__gen_e_acsl_i + 1) < 10", + 7); + __e_acsl_assert(0 <= (int)(__gen_e_acsl_i + 1L),(char *)"RTE", + (char *)"search", + (char *)"index_bound: 0 <= (int)(__gen_e_acsl_i + 1)", + 7); + __e_acsl_assert(__gen_e_acsl_i < 10,(char *)"RTE",(char *)"search", + (char *)"index_bound: __gen_e_acsl_i < 10",7); + __e_acsl_assert(0 <= __gen_e_acsl_i,(char *)"RTE",(char *)"search", + (char *)"index_bound: 0 <= __gen_e_acsl_i",7); + if (A[__gen_e_acsl_i] <= A[__gen_e_acsl_i + 1]) ; + else { + __gen_e_acsl_forall = 0; + goto e_acsl_end_loop3; + } + __gen_e_acsl_i ++; + } + e_acsl_end_loop3: ; + __e_acsl_assert(__gen_e_acsl_forall,(char *)"Precondition", + (char *)"search", + (char *)"\\forall integer i; 0 <= i < 9 ==> A[i] <= A[i + 1]", + 7); + } + __retres = search(elt); + { + int __gen_e_acsl_implies; + int __gen_e_acsl_implies_2; + if (! __gen_e_acsl_at) __gen_e_acsl_implies = 1; + else __gen_e_acsl_implies = __retres == 1; + __e_acsl_assert(__gen_e_acsl_implies,(char *)"Postcondition", + (char *)"search", + (char *)"\\old(\\exists integer j; 0 <= j < 10 && A[j] == elt) ==> \\result == 1", + 10); + if (! __gen_e_acsl_at_2) __gen_e_acsl_implies_2 = 1; + else __gen_e_acsl_implies_2 = __retres == 0; + __e_acsl_assert(__gen_e_acsl_implies_2,(char *)"Postcondition", + (char *)"search", + (char *)"\\old(\\forall integer j; 0 <= j < 10 ==> A[j] != elt) ==> \\result == 0", + 13); + return __retres; + } +} + + diff --git a/src/plugins/e-acsl/tests/examples/oracle_ci/linear_search.res.oracle b/src/plugins/e-acsl/tests/examples/oracle_ci/linear_search.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..b63983be3e17ae3ca463ebecfc05a67f9a78d337 --- /dev/null +++ b/src/plugins/e-acsl/tests/examples/oracle_ci/linear_search.res.oracle @@ -0,0 +1,24 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". +[eva:alarm] tests/examples/linear_search.i:30: Warning: + function __gen_e_acsl_search: precondition got status unknown. +[eva:alarm] tests/examples/linear_search.i:7: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/examples/linear_search.i:18: Warning: + loop invariant got status unknown. +[eva:alarm] tests/examples/linear_search.i:18: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/examples/linear_search.i:10: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/examples/linear_search.i:13: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/examples/linear_search.i:10: Warning: + function __gen_e_acsl_search, behavior exists: postcondition got status unknown. (Behavior may be inactive, no reduction performed.) +[eva:alarm] tests/examples/linear_search.i:13: Warning: + function __gen_e_acsl_search, behavior not_exists: postcondition got status unknown. (Behavior may be inactive, no reduction performed.) +[eva:alarm] tests/examples/linear_search.i:31: Warning: + assertion got status unknown. +[eva:alarm] tests/examples/linear_search.i:33: Warning: + function __gen_e_acsl_search: precondition got status unknown. +[eva:alarm] tests/examples/linear_search.i:34: Warning: + assertion got status unknown. diff --git a/src/plugins/e-acsl/tests/examples/oracle_dev/functions_contiki.res.oracle b/src/plugins/e-acsl/tests/examples/oracle_dev/functions_contiki.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..56f5b9ce5503a767bb5f388ef9430ee5c135e7a2 --- /dev/null +++ b/src/plugins/e-acsl/tests/examples/oracle_dev/functions_contiki.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/examples/functions_contiki.c (with preprocessing) diff --git a/src/plugins/e-acsl/tests/examples/oracle_dev/linear_search.res.oracle b/src/plugins/e-acsl/tests/examples/oracle_dev/linear_search.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..9e5f8b0f3d2f462c08830f4fbec1f7cb555bde52 --- /dev/null +++ b/src/plugins/e-acsl/tests/examples/oracle_dev/linear_search.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/examples/linear_search.i (no preprocessing) diff --git a/src/plugins/e-acsl/tests/format/README.md b/src/plugins/e-acsl/tests/format/README.md new file mode 100644 index 0000000000000000000000000000000000000000..af446c2caa0e919cbe91d86f72b15371e112dd2d --- /dev/null +++ b/src/plugins/e-acsl/tests/format/README.md @@ -0,0 +1 @@ +Like full-model, but also test instrumentation with -e-acsl-validate-format-strings diff --git a/src/plugins/e-acsl/tests/format/fprintf.c b/src/plugins/e-acsl/tests/format/fprintf.c new file mode 100644 index 0000000000000000000000000000000000000000..11678d9695f8207fecdf7e48d94187406a21a042 --- /dev/null +++ b/src/plugins/e-acsl/tests/format/fprintf.c @@ -0,0 +1,49 @@ +/* run.config_dev + COMMENT: Check behaviours of format functions + DONTRUN: +*/ + +#include <stdlib.h> +#include <stdio.h> +#include "signalled.h" + +int main(int argc, const char **argv) { + char *pstr = "Hello world!"; + char template [256]; + + /* *** fprintf *** */ + // The first argument to printf should be allocated valid FILE + OK(fprintf(stdout, "foobar\n")); + ABRT(fprintf(NULL, "foobar\n")); + FILE *fh = tmpfile(); + if (fh) { + OK(fprintf(fh, "foobar %s\n", "foobar")); + fclose(fh); + ABRT(fprintf(fh, "foobar %s\n", "foobar")); + ABRT(fprintf(&argc, "foobar %s\n", "foobar")); + } + + /* *** dprintf *** */ + // The first argument to dprintf should be opened file descriptor + OK(dprintf(1, "foobar\n")); + ABRT(dprintf(3, "foobar\n")); + + /* *** sprintf *** */ + // The buffer used with sprintf should be allocated, writeable and large + // enough + char buf[5]; + OK(sprintf(buf, "-%s-", "1")); // 4 chars, fits + OK(sprintf(buf, "-%s-", "12")); // 5 chars, still fits + ABRT(sprintf(buf, "-%s-", "123")); // 6 chars, no space for NUL + ABRT(sprintf(NULL, "-%s-", "123")); // try NULL + ABRT(sprintf(pstr, "-%s-", "123")); // try read-only + + /* *** snprintf *** */ + OK(snprintf(buf, 4, "-%s-", "123")); // 4 chars, fits + OK(snprintf(buf, 5, "-%s-", "123")); // 4 chars, fits + ABRT(snprintf(pstr, 6, "-%s-", "123")); // try read-only + ABRT(snprintf(buf, 6, "-%s-", "123")); // not enough space + ABRT(snprintf(NULL, 6, "-%s-", "123")); // not enough space + OK(snprintf(NULL, 0, "-%s-", "123")); // NULL should be file because of 0 chars to write + return 0; +} diff --git a/src/plugins/e-acsl/tests/format/oracle_ci/fprintf.res.oracle b/src/plugins/e-acsl/tests/format/oracle_ci/fprintf.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..583fc99475b649161b51302faad0c327832a4d4f --- /dev/null +++ b/src/plugins/e-acsl/tests/format/oracle_ci/fprintf.res.oracle @@ -0,0 +1,119 @@ +[kernel:typing:implicit-function-declaration] tests/format/fprintf.c:16: Warning: + Calling undeclared function fork. Old style K&R code? +[kernel:typing:incompatible-types-call] tests/format/fprintf.c:23: Warning: + expected 'FILE *' but got argument of type 'int *': & argc +[e-acsl] beginning translation. +[e-acsl] Warning: annotating undefined function `exit': + the generated program may miss memory instrumentation + if there are memory-related annotations. +[e-acsl] Warning: annotating undefined function `tmpfile': + the generated program may miss memory instrumentation + if there are memory-related annotations. +[e-acsl] Warning: annotating undefined function `fclose': + the generated program may miss memory instrumentation + if there are memory-related annotations. +[e-acsl] Warning: annotating undefined function `waitpid': + the generated program may miss memory instrumentation + if there are memory-related annotations. +[kernel:annot:missing-spec] FRAMAC_SHARE/libc/stdio.h:165: Warning: + Neither code nor specification for function fprintf, generating default assigns from the prototype +[kernel:annot:missing-spec] FRAMAC_SHARE/libc/stdio.h:169: Warning: + Neither code nor specification for function printf, generating default assigns from the prototype +[kernel:annot:missing-spec] FRAMAC_SHARE/libc/stdio.h:171: Warning: + Neither code nor specification for function snprintf, generating default assigns from the prototype +[kernel:annot:missing-spec] FRAMAC_SHARE/libc/stdio.h:173: Warning: + Neither code nor specification for function sprintf, generating default assigns from the prototype +[kernel:annot:missing-spec] FRAMAC_SHARE/libc/stdio.h:369: Warning: + Neither code nor specification for function dprintf, generating default assigns from the prototype +[kernel:annot:missing-spec] tests/format/fprintf.c:16: Warning: + Neither code nor specification for function fork, generating default assigns from the prototype +[e-acsl] FRAMAC_SHARE/libc/sys/wait.h:92: Warning: + E-ACSL construct `assigns clause in behavior' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/sys/wait.h:86: Warning: + E-ACSL construct `assigns clause in behavior' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/stdio.h:94: Warning: + E-ACSL construct `assigns clause in behavior' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/stdio.h:96: Warning: + E-ACSL construct `assigns clause in behavior' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/stdio.h:82: Warning: + E-ACSL construct `predicate with no definition nor reads clause' + is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/stdio.h:82: Warning: + E-ACSL construct `assigns clause in behavior' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/stdio.h:82: Warning: + E-ACSL construct `abnormal termination case in behavior' + is not yet supported. + Ignoring annotation. +[e-acsl] translation done in project "e-acsl". +[kernel:annot:missing-spec] tests/format/fprintf.c:16: Warning: + Neither code nor specification for function __e_acsl_builtin_fprintf, generating default assigns from the prototype +[eva:alarm] FRAMAC_SHARE/libc/sys/wait.h:86: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] FRAMAC_SHARE/libc/sys/wait.h:86: Warning: + function __gen_e_acsl_waitpid: postcondition 'initialization,stat_loc_init_on_success' got status unknown. +[eva:alarm] tests/format/fprintf.c:16: Warning: + accessing uninitialized left-value. assert \initialized(&process_status); +[kernel:annot:missing-spec] tests/format/signalled.h:12: Warning: + Neither code nor specification for function __e_acsl_builtin_printf, generating default assigns from the prototype +[eva:invalid-assigns] tests/format/fprintf.c:17: + Completely invalid destination for assigns clause *stream. Ignoring. +[eva:alarm] tests/format/fprintf.c:17: Warning: + accessing uninitialized left-value. assert \initialized(&process_status_0); +[eva:alarm] tests/format/fprintf.c:20: Warning: + accessing uninitialized left-value. assert \initialized(&process_status_1); +[eva:alarm] FRAMAC_SHARE/libc/stdio.h:94: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/format/fprintf.c:22: Warning: + accessing uninitialized left-value. assert \initialized(&process_status_2); +[eva:invalid-assigns] tests/format/fprintf.c:23: + Completely invalid destination for assigns clause *stream. Ignoring. +[eva:alarm] tests/format/fprintf.c:23: Warning: + accessing uninitialized left-value. assert \initialized(&process_status_3); +[kernel:annot:missing-spec] tests/format/fprintf.c:28: Warning: + Neither code nor specification for function __e_acsl_builtin_dprintf, generating default assigns from the prototype +[eva:alarm] tests/format/fprintf.c:28: Warning: + accessing uninitialized left-value. assert \initialized(&process_status_4); +[eva:alarm] tests/format/fprintf.c:29: Warning: + accessing uninitialized left-value. assert \initialized(&process_status_5); +[kernel:annot:missing-spec] tests/format/fprintf.c:35: Warning: + Neither code nor specification for function __e_acsl_builtin_sprintf, generating default assigns from the prototype +[eva:alarm] tests/format/fprintf.c:35: Warning: + accessing uninitialized left-value. assert \initialized(&process_status_6); +[eva:alarm] tests/format/fprintf.c:36: Warning: + accessing uninitialized left-value. assert \initialized(&process_status_7); +[eva:alarm] tests/format/fprintf.c:37: Warning: + accessing uninitialized left-value. assert \initialized(&process_status_8); +[eva:invalid-assigns] tests/format/fprintf.c:38: + Completely invalid destination for assigns clause *(str + (0 ..)). Ignoring. +[eva:alarm] tests/format/fprintf.c:38: Warning: + accessing uninitialized left-value. assert \initialized(&process_status_9); +[eva:invalid-assigns] tests/format/fprintf.c:39: + Completely invalid destination for assigns clause *(str + (0 ..)). Ignoring. +[eva:alarm] tests/format/fprintf.c:39: Warning: + accessing uninitialized left-value. assert \initialized(&process_status_10); +[kernel:annot:missing-spec] tests/format/fprintf.c:42: Warning: + Neither code nor specification for function __e_acsl_builtin_snprintf, generating default assigns from the prototype +[eva:alarm] tests/format/fprintf.c:42: Warning: + accessing uninitialized left-value. assert \initialized(&process_status_11); +[eva:alarm] tests/format/fprintf.c:43: Warning: + accessing uninitialized left-value. assert \initialized(&process_status_12); +[eva:invalid-assigns] tests/format/fprintf.c:44: + Completely invalid destination for assigns clause *(str + (0 ..)). Ignoring. +[eva:alarm] tests/format/fprintf.c:44: Warning: + accessing uninitialized left-value. assert \initialized(&process_status_13); +[eva:alarm] tests/format/fprintf.c:45: Warning: + accessing uninitialized left-value. assert \initialized(&process_status_14); +[eva:invalid-assigns] tests/format/fprintf.c:46: + Completely invalid destination for assigns clause *(str + (0 ..)). Ignoring. +[eva:alarm] tests/format/fprintf.c:46: Warning: + accessing uninitialized left-value. assert \initialized(&process_status_15); +[eva:invalid-assigns] tests/format/fprintf.c:47: + Completely invalid destination for assigns clause *(str + (0 ..)). Ignoring. +[eva:alarm] tests/format/fprintf.c:47: Warning: + accessing uninitialized left-value. assert \initialized(&process_status_16); diff --git a/src/plugins/e-acsl/tests/format/oracle_ci/gen_fprintf.c b/src/plugins/e-acsl/tests/format/oracle_ci/gen_fprintf.c new file mode 100644 index 0000000000000000000000000000000000000000..493d424dacffd43e58c07d463e0fd07064e3907d --- /dev/null +++ b/src/plugins/e-acsl/tests/format/oracle_ci/gen_fprintf.c @@ -0,0 +1,512 @@ +/* Generated by Frama-C */ +#include "signal.h" +#include "stdio.h" +#include "stdlib.h" +#include "sys/select.h" +#include "sys/time.h" +#include "sys/wait.h" +char *__gen_e_acsl_literal_string_30; +char *__gen_e_acsl_literal_string_29; +char *__gen_e_acsl_literal_string_28; +char *__gen_e_acsl_literal_string_27; +char *__gen_e_acsl_literal_string_26; +char *__gen_e_acsl_literal_string_25; +char *__gen_e_acsl_literal_string_24; +char *__gen_e_acsl_literal_string_23; +char *__gen_e_acsl_literal_string_22; +char *__gen_e_acsl_literal_string_20; +char *__gen_e_acsl_literal_string_18; +char *__gen_e_acsl_literal_string_15; +char *__gen_e_acsl_literal_string_14; +char *__gen_e_acsl_literal_string_13; +char *__gen_e_acsl_literal_string_12; +char *__gen_e_acsl_literal_string_11; +char *__gen_e_acsl_literal_string_8; +char *__gen_e_acsl_literal_string_7; +char *__gen_e_acsl_literal_string_9; +char *__gen_e_acsl_literal_string_6; +char *__gen_e_acsl_literal_string_10; +char *__gen_e_acsl_literal_string; +char *__gen_e_acsl_literal_string_2; +char *__gen_e_acsl_literal_string_3; +char *__gen_e_acsl_literal_string_5; +char *__gen_e_acsl_literal_string_4; +char *__gen_e_acsl_literal_string_21; +char *__gen_e_acsl_literal_string_19; +char *__gen_e_acsl_literal_string_17; +char *__gen_e_acsl_literal_string_16; +extern int __e_acsl_sound_verdict; + +/*@ assigns \result; + assigns \result \from \nothing; */ +extern int ( /* missing proto */ fork)(void); + +void __e_acsl_globals_init(void) +{ + static char __e_acsl_already_run = 0; + if (! __e_acsl_already_run) { + __e_acsl_already_run = 1; + __gen_e_acsl_literal_string_30 = "tests/format/fprintf.c:47"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_30, + sizeof("tests/format/fprintf.c:47")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_30); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_30); + __gen_e_acsl_literal_string_29 = "tests/format/fprintf.c:46"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_29, + sizeof("tests/format/fprintf.c:46")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_29); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_29); + __gen_e_acsl_literal_string_28 = "tests/format/fprintf.c:45"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_28, + sizeof("tests/format/fprintf.c:45")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_28); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_28); + __gen_e_acsl_literal_string_27 = "tests/format/fprintf.c:44"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_27, + sizeof("tests/format/fprintf.c:44")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_27); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_27); + __gen_e_acsl_literal_string_26 = "tests/format/fprintf.c:43"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_26, + sizeof("tests/format/fprintf.c:43")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_26); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_26); + __gen_e_acsl_literal_string_25 = "tests/format/fprintf.c:42"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_25, + sizeof("tests/format/fprintf.c:42")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_25); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_25); + __gen_e_acsl_literal_string_24 = "tests/format/fprintf.c:39"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_24, + sizeof("tests/format/fprintf.c:39")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_24); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_24); + __gen_e_acsl_literal_string_23 = "tests/format/fprintf.c:38"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_23, + sizeof("tests/format/fprintf.c:38")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_23); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_23); + __gen_e_acsl_literal_string_22 = "tests/format/fprintf.c:37"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_22, + sizeof("tests/format/fprintf.c:37")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_22); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_22); + __gen_e_acsl_literal_string_20 = "tests/format/fprintf.c:36"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_20, + sizeof("tests/format/fprintf.c:36")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_20); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_20); + __gen_e_acsl_literal_string_18 = "tests/format/fprintf.c:35"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_18, + sizeof("tests/format/fprintf.c:35")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_18); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_18); + __gen_e_acsl_literal_string_15 = "tests/format/fprintf.c:29"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_15, + sizeof("tests/format/fprintf.c:29")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_15); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_15); + __gen_e_acsl_literal_string_14 = "tests/format/fprintf.c:28"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_14, + sizeof("tests/format/fprintf.c:28")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_14); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_14); + __gen_e_acsl_literal_string_13 = "tests/format/fprintf.c:23"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_13, + sizeof("tests/format/fprintf.c:23")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_13); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_13); + __gen_e_acsl_literal_string_12 = "tests/format/fprintf.c:22"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_12, + sizeof("tests/format/fprintf.c:22")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_12); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_12); + __gen_e_acsl_literal_string_11 = "tests/format/fprintf.c:20"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_11, + sizeof("tests/format/fprintf.c:20")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_11); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_11); + __gen_e_acsl_literal_string_8 = "tests/format/fprintf.c:17"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_8, + sizeof("tests/format/fprintf.c:17")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_8); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_8); + __gen_e_acsl_literal_string_7 = "tests/format/fprintf.c:16"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_7, + sizeof("tests/format/fprintf.c:16")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_7); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_7); + __gen_e_acsl_literal_string_9 = "foobar %s\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_9, + sizeof("foobar %s\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_9); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_9); + __gen_e_acsl_literal_string_6 = "foobar\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_6, + sizeof("foobar\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_6); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_6); + __gen_e_acsl_literal_string_10 = "foobar"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_10, + sizeof("foobar")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_10); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_10); + __gen_e_acsl_literal_string = "TEST %d: "; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string, + sizeof("TEST %d: ")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string); + __gen_e_acsl_literal_string_2 = "OK: Expected signal at %s\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_2, + sizeof("OK: Expected signal at %s\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_2); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_2); + __gen_e_acsl_literal_string_3 = "OK: Expected execution at %s\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_3, + sizeof("OK: Expected execution at %s\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_3); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_3); + __gen_e_acsl_literal_string_5 = "FAIL: Unexpected signal at %s\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_5, + sizeof("FAIL: Unexpected signal at %s\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_5); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_5); + __gen_e_acsl_literal_string_4 = "FAIL: Unexpected execution at %s\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_4, + sizeof("FAIL: Unexpected execution at %s\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_4); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_4); + __gen_e_acsl_literal_string_21 = "123"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_21, + sizeof("123")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_21); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_21); + __gen_e_acsl_literal_string_19 = "12"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_19,sizeof("12")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_19); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_19); + __gen_e_acsl_literal_string_17 = "1"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_17,sizeof("1")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_17); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_17); + __gen_e_acsl_literal_string_16 = "-%s-"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_16, + sizeof("-%s-")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_16); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_16); + } + return; +} + +int main(int argc, char const **argv) +{ + int __retres; + char template[256]; + char buf[5]; + __e_acsl_memory_init(& argc,(char ***)(& argv),(size_t)8); + __e_acsl_globals_init(); + char *pstr = (char *)"Hello world!"; + { + pid_t pid = fork(); + if (! pid) { + __e_acsl_builtin_fprintf("",stdout,__gen_e_acsl_literal_string_6); + __gen_e_acsl_exit(0); + } + else { + int process_status; + __e_acsl_store_block((void *)(& process_status),(size_t)4); + __gen_e_acsl_waitpid(pid,& process_status,0); + /*@ assert Eva: initialization: \initialized(&process_status); */ + signal_eval(process_status,0,__gen_e_acsl_literal_string_7); + __e_acsl_delete_block((void *)(& process_status)); + } + } + { + pid_t pid_0 = fork(); + if (! pid_0) { + __e_acsl_builtin_fprintf("",(FILE *)0,__gen_e_acsl_literal_string_6); + __gen_e_acsl_exit(0); + } + else { + int process_status_0; + __e_acsl_store_block((void *)(& process_status_0),(size_t)4); + __gen_e_acsl_waitpid(pid_0,& process_status_0,0); + /*@ assert Eva: initialization: \initialized(&process_status_0); */ + signal_eval(process_status_0,1,__gen_e_acsl_literal_string_8); + __e_acsl_delete_block((void *)(& process_status_0)); + } + } + FILE *fh = __gen_e_acsl_tmpfile(); + __e_acsl_store_block((void *)(& fh),(size_t)8); + __e_acsl_full_init((void *)(& fh)); + if (fh) { + { + pid_t pid_1 = fork(); + if (! pid_1) { + __e_acsl_builtin_fprintf("s",fh,__gen_e_acsl_literal_string_9, + __gen_e_acsl_literal_string_10); + __gen_e_acsl_exit(0); + } + else { + int process_status_1; + __e_acsl_store_block((void *)(& process_status_1),(size_t)4); + __gen_e_acsl_waitpid(pid_1,& process_status_1,0); + /*@ assert Eva: initialization: \initialized(&process_status_1); */ + signal_eval(process_status_1,0,__gen_e_acsl_literal_string_11); + __e_acsl_delete_block((void *)(& process_status_1)); + } + } + __gen_e_acsl_fclose(fh); + { + pid_t pid_2 = fork(); + if (! pid_2) { + __e_acsl_builtin_fprintf("s",fh,__gen_e_acsl_literal_string_9, + __gen_e_acsl_literal_string_10); + __gen_e_acsl_exit(0); + } + else { + int process_status_2; + __e_acsl_store_block((void *)(& process_status_2),(size_t)4); + __gen_e_acsl_waitpid(pid_2,& process_status_2,0); + /*@ assert Eva: initialization: \initialized(&process_status_2); */ + signal_eval(process_status_2,1,__gen_e_acsl_literal_string_12); + __e_acsl_delete_block((void *)(& process_status_2)); + } + } + { + pid_t pid_3 = fork(); + if (! pid_3) { + __e_acsl_builtin_fprintf("s",(FILE *)(& argc), + __gen_e_acsl_literal_string_9, + __gen_e_acsl_literal_string_10); + __gen_e_acsl_exit(0); + } + else { + int process_status_3; + __e_acsl_store_block((void *)(& process_status_3),(size_t)4); + __gen_e_acsl_waitpid(pid_3,& process_status_3,0); + /*@ assert Eva: initialization: \initialized(&process_status_3); */ + signal_eval(process_status_3,1,__gen_e_acsl_literal_string_13); + __e_acsl_delete_block((void *)(& process_status_3)); + } + } + } + { + pid_t pid_4 = fork(); + if (! pid_4) { + __e_acsl_builtin_dprintf("",1,__gen_e_acsl_literal_string_6); + __gen_e_acsl_exit(0); + } + else { + int process_status_4; + __e_acsl_store_block((void *)(& process_status_4),(size_t)4); + __gen_e_acsl_waitpid(pid_4,& process_status_4,0); + /*@ assert Eva: initialization: \initialized(&process_status_4); */ + signal_eval(process_status_4,0,__gen_e_acsl_literal_string_14); + __e_acsl_delete_block((void *)(& process_status_4)); + } + } + { + pid_t pid_5 = fork(); + if (! pid_5) { + __e_acsl_builtin_dprintf("",3,__gen_e_acsl_literal_string_6); + __gen_e_acsl_exit(0); + } + else { + int process_status_5; + __e_acsl_store_block((void *)(& process_status_5),(size_t)4); + __gen_e_acsl_waitpid(pid_5,& process_status_5,0); + /*@ assert Eva: initialization: \initialized(&process_status_5); */ + signal_eval(process_status_5,1,__gen_e_acsl_literal_string_15); + __e_acsl_delete_block((void *)(& process_status_5)); + } + } + { + pid_t pid_6 = fork(); + if (! pid_6) { + __e_acsl_builtin_sprintf("s",buf,__gen_e_acsl_literal_string_16, + __gen_e_acsl_literal_string_17); + __gen_e_acsl_exit(0); + } + else { + int process_status_6; + __e_acsl_store_block((void *)(& process_status_6),(size_t)4); + __gen_e_acsl_waitpid(pid_6,& process_status_6,0); + /*@ assert Eva: initialization: \initialized(&process_status_6); */ + signal_eval(process_status_6,0,__gen_e_acsl_literal_string_18); + __e_acsl_delete_block((void *)(& process_status_6)); + } + } + { + pid_t pid_7 = fork(); + if (! pid_7) { + __e_acsl_builtin_sprintf("s",buf,__gen_e_acsl_literal_string_16, + __gen_e_acsl_literal_string_19); + __gen_e_acsl_exit(0); + } + else { + int process_status_7; + __e_acsl_store_block((void *)(& process_status_7),(size_t)4); + __gen_e_acsl_waitpid(pid_7,& process_status_7,0); + /*@ assert Eva: initialization: \initialized(&process_status_7); */ + signal_eval(process_status_7,0,__gen_e_acsl_literal_string_20); + __e_acsl_delete_block((void *)(& process_status_7)); + } + } + { + pid_t pid_8 = fork(); + if (! pid_8) { + __e_acsl_builtin_sprintf("s",buf,__gen_e_acsl_literal_string_16, + __gen_e_acsl_literal_string_21); + __gen_e_acsl_exit(0); + } + else { + int process_status_8; + __e_acsl_store_block((void *)(& process_status_8),(size_t)4); + __gen_e_acsl_waitpid(pid_8,& process_status_8,0); + /*@ assert Eva: initialization: \initialized(&process_status_8); */ + signal_eval(process_status_8,1,__gen_e_acsl_literal_string_22); + __e_acsl_delete_block((void *)(& process_status_8)); + } + } + { + pid_t pid_9 = fork(); + if (! pid_9) { + __e_acsl_builtin_sprintf("s",(char *)0,__gen_e_acsl_literal_string_16, + __gen_e_acsl_literal_string_21); + __gen_e_acsl_exit(0); + } + else { + int process_status_9; + __e_acsl_store_block((void *)(& process_status_9),(size_t)4); + __gen_e_acsl_waitpid(pid_9,& process_status_9,0); + /*@ assert Eva: initialization: \initialized(&process_status_9); */ + signal_eval(process_status_9,1,__gen_e_acsl_literal_string_23); + __e_acsl_delete_block((void *)(& process_status_9)); + } + } + { + pid_t pid_10 = fork(); + if (! pid_10) { + __e_acsl_builtin_sprintf("s",pstr,__gen_e_acsl_literal_string_16, + __gen_e_acsl_literal_string_21); + __gen_e_acsl_exit(0); + } + else { + int process_status_10; + __e_acsl_store_block((void *)(& process_status_10),(size_t)4); + __gen_e_acsl_waitpid(pid_10,& process_status_10,0); + /*@ assert Eva: initialization: \initialized(&process_status_10); */ + signal_eval(process_status_10,1,__gen_e_acsl_literal_string_24); + __e_acsl_delete_block((void *)(& process_status_10)); + } + } + { + pid_t pid_11 = fork(); + if (! pid_11) { + __e_acsl_builtin_snprintf("s",buf,(unsigned long)4, + __gen_e_acsl_literal_string_16, + __gen_e_acsl_literal_string_21); + __gen_e_acsl_exit(0); + } + else { + int process_status_11; + __e_acsl_store_block((void *)(& process_status_11),(size_t)4); + __gen_e_acsl_waitpid(pid_11,& process_status_11,0); + /*@ assert Eva: initialization: \initialized(&process_status_11); */ + signal_eval(process_status_11,0,__gen_e_acsl_literal_string_25); + __e_acsl_delete_block((void *)(& process_status_11)); + } + } + { + pid_t pid_12 = fork(); + if (! pid_12) { + __e_acsl_builtin_snprintf("s",buf,(unsigned long)5, + __gen_e_acsl_literal_string_16, + __gen_e_acsl_literal_string_21); + __gen_e_acsl_exit(0); + } + else { + int process_status_12; + __e_acsl_store_block((void *)(& process_status_12),(size_t)4); + __gen_e_acsl_waitpid(pid_12,& process_status_12,0); + /*@ assert Eva: initialization: \initialized(&process_status_12); */ + signal_eval(process_status_12,0,__gen_e_acsl_literal_string_26); + __e_acsl_delete_block((void *)(& process_status_12)); + } + } + { + pid_t pid_13 = fork(); + if (! pid_13) { + __e_acsl_builtin_snprintf("s",pstr,(unsigned long)6, + __gen_e_acsl_literal_string_16, + __gen_e_acsl_literal_string_21); + __gen_e_acsl_exit(0); + } + else { + int process_status_13; + __e_acsl_store_block((void *)(& process_status_13),(size_t)4); + __gen_e_acsl_waitpid(pid_13,& process_status_13,0); + /*@ assert Eva: initialization: \initialized(&process_status_13); */ + signal_eval(process_status_13,1,__gen_e_acsl_literal_string_27); + __e_acsl_delete_block((void *)(& process_status_13)); + } + } + { + pid_t pid_14 = fork(); + if (! pid_14) { + __e_acsl_builtin_snprintf("s",buf,(unsigned long)6, + __gen_e_acsl_literal_string_16, + __gen_e_acsl_literal_string_21); + __gen_e_acsl_exit(0); + } + else { + int process_status_14; + __e_acsl_store_block((void *)(& process_status_14),(size_t)4); + __gen_e_acsl_waitpid(pid_14,& process_status_14,0); + /*@ assert Eva: initialization: \initialized(&process_status_14); */ + signal_eval(process_status_14,1,__gen_e_acsl_literal_string_28); + __e_acsl_delete_block((void *)(& process_status_14)); + } + } + { + pid_t pid_15 = fork(); + if (! pid_15) { + __e_acsl_builtin_snprintf("s",(char *)0,(unsigned long)6, + __gen_e_acsl_literal_string_16, + __gen_e_acsl_literal_string_21); + __gen_e_acsl_exit(0); + } + else { + int process_status_15; + __e_acsl_store_block((void *)(& process_status_15),(size_t)4); + __gen_e_acsl_waitpid(pid_15,& process_status_15,0); + /*@ assert Eva: initialization: \initialized(&process_status_15); */ + signal_eval(process_status_15,1,__gen_e_acsl_literal_string_29); + __e_acsl_delete_block((void *)(& process_status_15)); + } + } + { + pid_t pid_16 = fork(); + if (! pid_16) { + __e_acsl_builtin_snprintf("s",(char *)0,(unsigned long)0, + __gen_e_acsl_literal_string_16, + __gen_e_acsl_literal_string_21); + __gen_e_acsl_exit(0); + } + else { + int process_status_16; + __e_acsl_store_block((void *)(& process_status_16),(size_t)4); + __gen_e_acsl_waitpid(pid_16,& process_status_16,0); + /*@ assert Eva: initialization: \initialized(&process_status_16); */ + signal_eval(process_status_16,0,__gen_e_acsl_literal_string_30); + __e_acsl_delete_block((void *)(& process_status_16)); + } + } + __retres = 0; + __e_acsl_delete_block((void *)(& fh)); + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/format/oracle_ci/gen_printf.c b/src/plugins/e-acsl/tests/format/oracle_ci/gen_printf.c new file mode 100644 index 0000000000000000000000000000000000000000..861d5131479c83c2f29636cbf95f70ecf4bad248 --- /dev/null +++ b/src/plugins/e-acsl/tests/format/oracle_ci/gen_printf.c @@ -0,0 +1,6900 @@ +/* Generated by Frama-C */ +#include "signal.h" +#include "stddef.h" +#include "stdint.h" +#include "stdio.h" +#include "stdlib.h" +#include "string.h" +#include "sys/time.h" +#include "sys/wait.h" +#include "time.h" +#include "unistd.h" +#include "wchar.h" +char *__gen_e_acsl_literal_string_7; +char *__gen_e_acsl_literal_string_337; +char *__gen_e_acsl_literal_string_335; +char *__gen_e_acsl_literal_string_333; +char *__gen_e_acsl_literal_string_332; +char *__gen_e_acsl_literal_string_330; +char *__gen_e_acsl_literal_string_328; +char *__gen_e_acsl_literal_string_326; +char *__gen_e_acsl_literal_string_324; +char *__gen_e_acsl_literal_string_322; +char *__gen_e_acsl_literal_string_320; +char *__gen_e_acsl_literal_string_318; +char *__gen_e_acsl_literal_string_316; +char *__gen_e_acsl_literal_string_315; +char *__gen_e_acsl_literal_string_314; +char *__gen_e_acsl_literal_string_313; +char *__gen_e_acsl_literal_string_311; +char *__gen_e_acsl_literal_string_310; +char *__gen_e_acsl_literal_string_309; +char *__gen_e_acsl_literal_string_307; +char *__gen_e_acsl_literal_string_305; +char *__gen_e_acsl_literal_string_303; +char *__gen_e_acsl_literal_string_301; +char *__gen_e_acsl_literal_string_299; +char *__gen_e_acsl_literal_string_297; +char *__gen_e_acsl_literal_string_296; +char *__gen_e_acsl_literal_string_295; +char *__gen_e_acsl_literal_string_294; +char *__gen_e_acsl_literal_string_293; +char *__gen_e_acsl_literal_string_292; +char *__gen_e_acsl_literal_string_291; +char *__gen_e_acsl_literal_string_290; +char *__gen_e_acsl_literal_string_288; +char *__gen_e_acsl_literal_string_287; +char *__gen_e_acsl_literal_string_285; +char *__gen_e_acsl_literal_string_284; +char *__gen_e_acsl_literal_string_283; +char *__gen_e_acsl_literal_string_282; +char *__gen_e_acsl_literal_string_281; +char *__gen_e_acsl_literal_string_280; +char *__gen_e_acsl_literal_string_279; +char *__gen_e_acsl_literal_string_277; +char *__gen_e_acsl_literal_string_276; +char *__gen_e_acsl_literal_string_275; +char *__gen_e_acsl_literal_string_273; +char *__gen_e_acsl_literal_string_271; +char *__gen_e_acsl_literal_string_270; +char *__gen_e_acsl_literal_string_269; +char *__gen_e_acsl_literal_string_267; +char *__gen_e_acsl_literal_string_265; +char *__gen_e_acsl_literal_string_264; +char *__gen_e_acsl_literal_string_263; +char *__gen_e_acsl_literal_string_261; +char *__gen_e_acsl_literal_string_259; +char *__gen_e_acsl_literal_string_258; +char *__gen_e_acsl_literal_string_257; +char *__gen_e_acsl_literal_string_255; +char *__gen_e_acsl_literal_string_253; +char *__gen_e_acsl_literal_string_252; +char *__gen_e_acsl_literal_string_251; +char *__gen_e_acsl_literal_string_249; +char *__gen_e_acsl_literal_string_247; +char *__gen_e_acsl_literal_string_246; +char *__gen_e_acsl_literal_string_245; +char *__gen_e_acsl_literal_string_243; +char *__gen_e_acsl_literal_string_241; +char *__gen_e_acsl_literal_string_240; +char *__gen_e_acsl_literal_string_239; +char *__gen_e_acsl_literal_string_237; +char *__gen_e_acsl_literal_string_235; +char *__gen_e_acsl_literal_string_234; +char *__gen_e_acsl_literal_string_233; +char *__gen_e_acsl_literal_string_231; +char *__gen_e_acsl_literal_string_226; +char *__gen_e_acsl_literal_string_221; +char *__gen_e_acsl_literal_string_216; +char *__gen_e_acsl_literal_string_211; +char *__gen_e_acsl_literal_string_206; +char *__gen_e_acsl_literal_string_201; +char *__gen_e_acsl_literal_string_196; +char *__gen_e_acsl_literal_string_194; +char *__gen_e_acsl_literal_string_193; +char *__gen_e_acsl_literal_string_192; +char *__gen_e_acsl_literal_string_191; +char *__gen_e_acsl_literal_string_190; +char *__gen_e_acsl_literal_string_186; +char *__gen_e_acsl_literal_string_183; +char *__gen_e_acsl_literal_string_180; +char *__gen_e_acsl_literal_string_177; +char *__gen_e_acsl_literal_string_174; +char *__gen_e_acsl_literal_string_172; +char *__gen_e_acsl_literal_string_170; +char *__gen_e_acsl_literal_string_168; +char *__gen_e_acsl_literal_string_167; +char *__gen_e_acsl_literal_string_166; +char *__gen_e_acsl_literal_string_165; +char *__gen_e_acsl_literal_string_164; +char *__gen_e_acsl_literal_string_163; +char *__gen_e_acsl_literal_string_161; +char *__gen_e_acsl_literal_string_159; +char *__gen_e_acsl_literal_string_157; +char *__gen_e_acsl_literal_string_155; +char *__gen_e_acsl_literal_string_152; +char *__gen_e_acsl_literal_string_149; +char *__gen_e_acsl_literal_string_146; +char *__gen_e_acsl_literal_string_143; +char *__gen_e_acsl_literal_string_141; +char *__gen_e_acsl_literal_string_138; +char *__gen_e_acsl_literal_string_135; +char *__gen_e_acsl_literal_string_133; +char *__gen_e_acsl_literal_string_130; +char *__gen_e_acsl_literal_string_128; +char *__gen_e_acsl_literal_string_125; +char *__gen_e_acsl_literal_string_122; +char *__gen_e_acsl_literal_string_119; +char *__gen_e_acsl_literal_string_117; +char *__gen_e_acsl_literal_string_114; +char *__gen_e_acsl_literal_string_111; +char *__gen_e_acsl_literal_string_108; +char *__gen_e_acsl_literal_string_106; +char *__gen_e_acsl_literal_string_102; +char *__gen_e_acsl_literal_string_99; +char *__gen_e_acsl_literal_string_96; +char *__gen_e_acsl_literal_string_94; +char *__gen_e_acsl_literal_string_92; +char *__gen_e_acsl_literal_string_89; +char *__gen_e_acsl_literal_string_86; +char *__gen_e_acsl_literal_string_83; +char *__gen_e_acsl_literal_string_80; +char *__gen_e_acsl_literal_string_78; +char *__gen_e_acsl_literal_string_75; +char *__gen_e_acsl_literal_string_72; +char *__gen_e_acsl_literal_string_70; +char *__gen_e_acsl_literal_string_66; +char *__gen_e_acsl_literal_string_63; +char *__gen_e_acsl_literal_string_60; +char *__gen_e_acsl_literal_string_58; +char *__gen_e_acsl_literal_string_55; +char *__gen_e_acsl_literal_string_52; +char *__gen_e_acsl_literal_string_49; +char *__gen_e_acsl_literal_string_47; +char *__gen_e_acsl_literal_string_44; +char *__gen_e_acsl_literal_string_42; +char *__gen_e_acsl_literal_string_40; +char *__gen_e_acsl_literal_string_38; +char *__gen_e_acsl_literal_string_35; +char *__gen_e_acsl_literal_string_32; +char *__gen_e_acsl_literal_string_29; +char *__gen_e_acsl_literal_string_27; +char *__gen_e_acsl_literal_string_25; +char *__gen_e_acsl_literal_string_23; +char *__gen_e_acsl_literal_string_21; +char *__gen_e_acsl_literal_string_19; +char *__gen_e_acsl_literal_string_18; +char *__gen_e_acsl_literal_string_16; +char *__gen_e_acsl_literal_string_14; +char *__gen_e_acsl_literal_string_12; +char *__gen_e_acsl_literal_string_33; +char *__gen_e_acsl_literal_string_9; +char *__gen_e_acsl_literal_string_6; +char *__gen_e_acsl_literal_string_338; +char *__gen_e_acsl_literal_string_68; +char *__gen_e_acsl_literal_string_45; +char *__gen_e_acsl_literal_string_30; +char *__gen_e_acsl_literal_string_36; +char *__gen_e_acsl_literal_string_8; +char *__gen_e_acsl_literal_string_139; +char *__gen_e_acsl_literal_string; +char *__gen_e_acsl_literal_string_2; +char *__gen_e_acsl_literal_string_3; +char *__gen_e_acsl_literal_string_10; +char *__gen_e_acsl_literal_string_11; +char *__gen_e_acsl_literal_string_5; +char *__gen_e_acsl_literal_string_4; +char *__gen_e_acsl_literal_string_223; +char *__gen_e_acsl_literal_string_124; +char *__gen_e_acsl_literal_string_220; +char *__gen_e_acsl_literal_string_121; +char *__gen_e_acsl_literal_string_222; +char *__gen_e_acsl_literal_string_123; +char *__gen_e_acsl_literal_string_126; +char *__gen_e_acsl_literal_string_120; +char *__gen_e_acsl_literal_string_118; +char *__gen_e_acsl_literal_string_224; +char *__gen_e_acsl_literal_string_116; +char *__gen_e_acsl_literal_string_188; +char *__gen_e_acsl_literal_string_185; +char *__gen_e_acsl_literal_string_228; +char *__gen_e_acsl_literal_string_132; +char *__gen_e_acsl_literal_string_225; +char *__gen_e_acsl_literal_string_129; +char *__gen_e_acsl_literal_string_227; +char *__gen_e_acsl_literal_string_131; +char *__gen_e_acsl_literal_string_137; +char *__gen_e_acsl_literal_string_182; +char *__gen_e_acsl_literal_string_136; +char *__gen_e_acsl_literal_string_184; +char *__gen_e_acsl_literal_string_134; +char *__gen_e_acsl_literal_string_229; +char *__gen_e_acsl_literal_string_127; +char *__gen_e_acsl_literal_string_26; +char *__gen_e_acsl_literal_string_17; +char *__gen_e_acsl_literal_string_13; +char *__gen_e_acsl_literal_string_15; +char *__gen_e_acsl_literal_string_289; +char *__gen_e_acsl_literal_string_308; +char *__gen_e_acsl_literal_string_187; +char *__gen_e_acsl_literal_string_312; +char *__gen_e_acsl_literal_string_158; +char *__gen_e_acsl_literal_string_198; +char *__gen_e_acsl_literal_string_77; +char *__gen_e_acsl_literal_string_195; +char *__gen_e_acsl_literal_string_74; +char *__gen_e_acsl_literal_string_197; +char *__gen_e_acsl_literal_string_76; +char *__gen_e_acsl_literal_string_91; +char *__gen_e_acsl_literal_string_203; +char *__gen_e_acsl_literal_string_101; +char *__gen_e_acsl_literal_string_200; +char *__gen_e_acsl_literal_string_98; +char *__gen_e_acsl_literal_string_202; +char *__gen_e_acsl_literal_string_100; +char *__gen_e_acsl_literal_string_104; +char *__gen_e_acsl_literal_string_43; +char *__gen_e_acsl_literal_string_171; +char *__gen_e_acsl_literal_string_97; +char *__gen_e_acsl_literal_string_41; +char *__gen_e_acsl_literal_string_95; +char *__gen_e_acsl_literal_string_204; +char *__gen_e_acsl_literal_string_103; +char *__gen_e_acsl_literal_string_169; +char *__gen_e_acsl_literal_string_73; +char *__gen_e_acsl_literal_string_39; +char *__gen_e_acsl_literal_string_71; +char *__gen_e_acsl_literal_string_286; +char *__gen_e_acsl_literal_string_93; +char *__gen_e_acsl_literal_string_199; +char *__gen_e_acsl_literal_string_69; +char *__gen_e_acsl_literal_string_218; +char *__gen_e_acsl_literal_string_113; +char *__gen_e_acsl_literal_string_215; +char *__gen_e_acsl_literal_string_110; +char *__gen_e_acsl_literal_string_217; +char *__gen_e_acsl_literal_string_112; +char *__gen_e_acsl_literal_string_115; +char *__gen_e_acsl_literal_string_179; +char *__gen_e_acsl_literal_string_109; +char *__gen_e_acsl_literal_string_181; +char *__gen_e_acsl_literal_string_107; +char *__gen_e_acsl_literal_string_219; +char *__gen_e_acsl_literal_string_105; +char *__gen_e_acsl_literal_string_160; +char *__gen_e_acsl_literal_string_208; +char *__gen_e_acsl_literal_string_65; +char *__gen_e_acsl_literal_string_205; +char *__gen_e_acsl_literal_string_62; +char *__gen_e_acsl_literal_string_207; +char *__gen_e_acsl_literal_string_64; +char *__gen_e_acsl_literal_string_67; +char *__gen_e_acsl_literal_string_173; +char *__gen_e_acsl_literal_string_61; +char *__gen_e_acsl_literal_string_213; +char *__gen_e_acsl_literal_string_54; +char *__gen_e_acsl_literal_string_210; +char *__gen_e_acsl_literal_string_51; +char *__gen_e_acsl_literal_string_212; +char *__gen_e_acsl_literal_string_53; +char *__gen_e_acsl_literal_string_56; +char *__gen_e_acsl_literal_string_176; +char *__gen_e_acsl_literal_string_50; +char *__gen_e_acsl_literal_string_178; +char *__gen_e_acsl_literal_string_48; +char *__gen_e_acsl_literal_string_214; +char *__gen_e_acsl_literal_string_46; +char *__gen_e_acsl_literal_string_175; +char *__gen_e_acsl_literal_string_59; +char *__gen_e_acsl_literal_string_209; +char *__gen_e_acsl_literal_string_57; +char *__gen_e_acsl_literal_string_248; +char *__gen_e_acsl_literal_string_88; +char *__gen_e_acsl_literal_string_230; +char *__gen_e_acsl_literal_string_79; +char *__gen_e_acsl_literal_string_242; +char *__gen_e_acsl_literal_string_82; +char *__gen_e_acsl_literal_string_336; +char *__gen_e_acsl_literal_string_162; +char *__gen_e_acsl_literal_string_278; +char *__gen_e_acsl_literal_string_236; +char *__gen_e_acsl_literal_string_85; +char *__gen_e_acsl_literal_string_189; +char *__gen_e_acsl_literal_string_156; +char *__gen_e_acsl_literal_string_272; +char *__gen_e_acsl_literal_string_151; +char *__gen_e_acsl_literal_string_254; +char *__gen_e_acsl_literal_string_142; +char *__gen_e_acsl_literal_string_266; +char *__gen_e_acsl_literal_string_145; +char *__gen_e_acsl_literal_string_260; +char *__gen_e_acsl_literal_string_148; +char *__gen_e_acsl_literal_string_140; +char *__gen_e_acsl_literal_string_274; +char *__gen_e_acsl_literal_string_153; +char *__gen_e_acsl_literal_string_256; +char *__gen_e_acsl_literal_string_144; +char *__gen_e_acsl_literal_string_268; +char *__gen_e_acsl_literal_string_147; +char *__gen_e_acsl_literal_string_262; +char *__gen_e_acsl_literal_string_150; +char *__gen_e_acsl_literal_string_250; +char *__gen_e_acsl_literal_string_90; +char *__gen_e_acsl_literal_string_232; +char *__gen_e_acsl_literal_string_81; +char *__gen_e_acsl_literal_string_244; +char *__gen_e_acsl_literal_string_84; +char *__gen_e_acsl_literal_string_154; +char *__gen_e_acsl_literal_string_238; +char *__gen_e_acsl_literal_string_87; +char *__gen_e_acsl_literal_string_22; +char *__gen_e_acsl_literal_string_20; +char *__gen_e_acsl_literal_string_334; +char *__gen_e_acsl_literal_string_28; +char *__gen_e_acsl_literal_string_319; +char *__gen_e_acsl_literal_string_37; +char *__gen_e_acsl_literal_string_24; +char *__gen_e_acsl_literal_string_298; +char *__gen_e_acsl_literal_string_329; +char *__gen_e_acsl_literal_string_306; +char *__gen_e_acsl_literal_string_304; +char *__gen_e_acsl_literal_string_302; +char *__gen_e_acsl_literal_string_31; +char *__gen_e_acsl_literal_string_331; +char *__gen_e_acsl_literal_string_300; +char *__gen_e_acsl_literal_string_327; +char *__gen_e_acsl_literal_string_325; +char *__gen_e_acsl_literal_string_317; +char *__gen_e_acsl_literal_string_321; +char *__gen_e_acsl_literal_string_34; +char *__gen_e_acsl_literal_string_323; +char const *valid_specifiers = "diouxfFeEgGaAcspn"; +void apply_specifier(char *format, int spec) +{ + int n; + char *tmp_1; + __e_acsl_store_block((void *)(& tmp_1),(size_t)8); + __e_acsl_store_block((void *)(& n),(size_t)4); + __e_acsl_store_block((void *)(& spec),(size_t)4); + __e_acsl_store_block((void *)(& format),(size_t)8); + void *p = (void *)0; + __e_acsl_store_block((void *)(& p),(size_t)8); + __e_acsl_full_init((void *)(& p)); + __e_acsl_full_init((void *)(& tmp_1)); + tmp_1 = __gen_e_acsl_strchr(__gen_e_acsl_literal_string_6,spec); + if (tmp_1 != (char *)0) __e_acsl_builtin_printf("e",(char const *)format, + 1.0); + else { + char *tmp_0; + __e_acsl_store_block((void *)(& tmp_0),(size_t)8); + __e_acsl_full_init((void *)(& tmp_0)); + tmp_0 = __gen_e_acsl_strchr(__gen_e_acsl_literal_string_7,spec); + if (tmp_0 != (char *)0) __e_acsl_builtin_printf("D",(char const *)format, + 1U); + else { + char *tmp; + __e_acsl_store_block((void *)(& tmp),(size_t)8); + __e_acsl_full_init((void *)(& tmp)); + tmp = __gen_e_acsl_strchr(__gen_e_acsl_literal_string_8,spec); + if (tmp != (char *)0) __e_acsl_builtin_printf("d",(char const *)format, + 97); + else + if (spec == 's') __e_acsl_builtin_printf("s",(char const *)format, + __gen_e_acsl_literal_string_9); + else + if (spec == 'n') __e_acsl_builtin_printf("i",(char const *)format, + & n); + else + if (spec == 'p') __e_acsl_builtin_printf("p", + (char const *)format,p); + else __gen_e_acsl_abort(); + __e_acsl_delete_block((void *)(& tmp)); + } + __e_acsl_delete_block((void *)(& tmp_0)); + } + __e_acsl_delete_block((void *)(& spec)); + __e_acsl_delete_block((void *)(& format)); + __e_acsl_delete_block((void *)(& tmp_1)); + __e_acsl_delete_block((void *)(& p)); + __e_acsl_delete_block((void *)(& n)); + return; +} + +/*@ assigns \nothing; + frees p; */ + __attribute__((__FC_BUILTIN__)) void __e_acsl_delete_block(void *p); + +/* compiler builtin: + __attribute__((__FC_BUILTIN__)) void *__builtin_alloca(unsigned long size); */ +void test_specifier_application(char const *allowed, char const *fmt, + int only_negative, char *at) +{ + size_t tmp; + unsigned long __lengthof_format; + int i; + __e_acsl_store_block((void *)(& i),(size_t)4); + __e_acsl_store_block((void *)(& __lengthof_format),(size_t)8); + __e_acsl_store_block((void *)(& tmp),(size_t)8); + __e_acsl_store_block((void *)(& at),(size_t)8); + __e_acsl_store_block((void *)(& only_negative),(size_t)4); + __e_acsl_store_block((void *)(& fmt),(size_t)8); + __e_acsl_store_block((void *)(& allowed),(size_t)8); + __e_acsl_full_init((void *)(& tmp)); + tmp = __gen_e_acsl_strlen(fmt); + int len = (int)tmp; + __e_acsl_store_block((void *)(& len),(size_t)4); + __e_acsl_full_init((void *)(& len)); + /*@ assert + alloca_bounds: 0 < sizeof(char) * (len + 1) ≤ 18446744073709551615; + */ + { + int __gen_e_acsl_and; + if (0L < len + 1L) { + __e_acsl_mpz_t __gen_e_acsl_; + __e_acsl_mpz_t __gen_e_acsl__2; + int __gen_e_acsl_le; + __gmpz_init_set_si(__gen_e_acsl_,1L * (len + 1L)); + __gmpz_init_set_ui(__gen_e_acsl__2,18446744073709551615UL); + __gen_e_acsl_le = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__2)); + __gen_e_acsl_and = __gen_e_acsl_le <= 0; + __gmpz_clear(__gen_e_acsl_); + __gmpz_clear(__gen_e_acsl__2); + } + else __gen_e_acsl_and = 0; + __e_acsl_assert(__gen_e_acsl_and,(char *)"Assertion", + (char *)"test_specifier_application", + (char *)"alloca_bounds: 0 < sizeof(char) * (len + 1) <= 18446744073709551615", + 50); + } + __e_acsl_full_init((void *)(& __lengthof_format)); + __lengthof_format = (unsigned long)(len + 1); + char *format = __builtin_alloca(sizeof(char) * __lengthof_format); + __e_acsl_store_block((void *)format,sizeof(char) * __lengthof_format); + __e_acsl_store_block((void *)(& format),(size_t)8); + __e_acsl_full_init((void *)(& format)); + __gen_e_acsl_strcpy(format,fmt); + { + int i_0 = 0; + __e_acsl_store_block((void *)(& i_0),(size_t)4); + __e_acsl_full_init((void *)(& i_0)); + while (1) { + size_t tmp_3; + __e_acsl_store_block((void *)(& tmp_3),(size_t)8); + __e_acsl_full_init((void *)(& tmp_3)); + tmp_3 = __gen_e_acsl_strlen(valid_specifiers); + ; + if (! ((size_t)i_0 < tmp_3)) { + __e_acsl_delete_block((void *)(& tmp_3)); + break; + } + { + char *tmp_2; + __e_acsl_store_block((void *)(& tmp_2),(size_t)8); + int c = (int)*(valid_specifiers + i_0); + __e_acsl_store_block((void *)(& c),(size_t)4); + __e_acsl_full_init((void *)(& c)); + __e_acsl_initialize((void *)(format + (len - 1)),sizeof(char)); + *(format + (len - 1)) = (char)c; + __e_acsl_full_init((void *)(& tmp_2)); + tmp_2 = __gen_e_acsl_strchr(allowed,c); + if (tmp_2) { + if (! only_negative) { + { + pid_t pid = fork(); + __e_acsl_store_block((void *)(& pid),(size_t)4); + __e_acsl_full_init((void *)(& pid)); + if (! pid) { + apply_specifier(format,c); + __gen_e_acsl_exit(0); + } + else { + int process_status; + __e_acsl_store_block((void *)(& process_status),(size_t)4); + waitpid(pid,& process_status,0); + signal_eval(process_status,0,(char const *)at); + __e_acsl_delete_block((void *)(& process_status)); + } + __e_acsl_delete_block((void *)(& pid)); + } + } + } + else { + { + pid_t pid_0 = fork(); + __e_acsl_store_block((void *)(& pid_0),(size_t)4); + __e_acsl_full_init((void *)(& pid_0)); + if (! pid_0) { + apply_specifier(format,c); + __gen_e_acsl_exit(0); + } + else { + int process_status_0; + __e_acsl_store_block((void *)(& process_status_0),(size_t)4); + waitpid(pid_0,& process_status_0,0); + signal_eval(process_status_0,1,(char const *)at); + __e_acsl_delete_block((void *)(& process_status_0)); + } + __e_acsl_delete_block((void *)(& pid_0)); + } + } + __e_acsl_delete_block((void *)(& tmp_2)); + __e_acsl_delete_block((void *)(& c)); + } + __e_acsl_full_init((void *)(& i_0)); + i_0 ++; + __e_acsl_delete_block((void *)(& tmp_3)); + } + __e_acsl_delete_block((void *)(& i_0)); + } + __e_acsl_delete_block((void *)format); + __e_acsl_delete_block((void *)(& at)); + __e_acsl_delete_block((void *)(& only_negative)); + __e_acsl_delete_block((void *)(& fmt)); + __e_acsl_delete_block((void *)(& allowed)); + __e_acsl_delete_block((void *)(& i)); + __e_acsl_delete_block((void *)(& __lengthof_format)); + __e_acsl_delete_block((void *)(& format)); + __e_acsl_delete_block((void *)(& tmp)); + __e_acsl_delete_block((void *)(& len)); + return; +} + +void __e_acsl_globals_init(void) +{ + __gen_e_acsl_literal_string_7 = "uoxX"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_7,sizeof("uoxX")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_7); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_7); + __gen_e_acsl_literal_string_337 = "tests/format/printf.c:475"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_337, + sizeof("tests/format/printf.c:475")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_337); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_337); + __gen_e_acsl_literal_string_335 = "tests/format/printf.c:472"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_335, + sizeof("tests/format/printf.c:472")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_335); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_335); + __gen_e_acsl_literal_string_333 = "tests/format/printf.c:471"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_333, + sizeof("tests/format/printf.c:471")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_333); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_333); + __gen_e_acsl_literal_string_332 = "tests/format/printf.c:470"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_332, + sizeof("tests/format/printf.c:470")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_332); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_332); + __gen_e_acsl_literal_string_330 = "tests/format/printf.c:469"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_330, + sizeof("tests/format/printf.c:469")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_330); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_330); + __gen_e_acsl_literal_string_328 = "tests/format/printf.c:468"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_328, + sizeof("tests/format/printf.c:468")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_328); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_328); + __gen_e_acsl_literal_string_326 = "tests/format/printf.c:467"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_326, + sizeof("tests/format/printf.c:467")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_326); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_326); + __gen_e_acsl_literal_string_324 = "tests/format/printf.c:466"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_324, + sizeof("tests/format/printf.c:466")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_324); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_324); + __gen_e_acsl_literal_string_322 = "tests/format/printf.c:465"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_322, + sizeof("tests/format/printf.c:465")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_322); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_322); + __gen_e_acsl_literal_string_320 = "tests/format/printf.c:464"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_320, + sizeof("tests/format/printf.c:464")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_320); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_320); + __gen_e_acsl_literal_string_318 = "tests/format/printf.c:463"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_318, + sizeof("tests/format/printf.c:463")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_318); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_318); + __gen_e_acsl_literal_string_316 = "tests/format/printf.c:460"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_316, + sizeof("tests/format/printf.c:460")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_316); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_316); + __gen_e_acsl_literal_string_315 = "tests/format/printf.c:459"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_315, + sizeof("tests/format/printf.c:459")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_315); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_315); + __gen_e_acsl_literal_string_314 = "tests/format/printf.c:458"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_314, + sizeof("tests/format/printf.c:458")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_314); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_314); + __gen_e_acsl_literal_string_313 = "tests/format/printf.c:457"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_313, + sizeof("tests/format/printf.c:457")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_313); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_313); + __gen_e_acsl_literal_string_311 = "tests/format/printf.c:454"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_311, + sizeof("tests/format/printf.c:454")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_311); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_311); + __gen_e_acsl_literal_string_310 = "tests/format/printf.c:453"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_310, + sizeof("tests/format/printf.c:453")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_310); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_310); + __gen_e_acsl_literal_string_309 = "tests/format/printf.c:452"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_309, + sizeof("tests/format/printf.c:452")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_309); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_309); + __gen_e_acsl_literal_string_307 = "tests/format/printf.c:427"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_307, + sizeof("tests/format/printf.c:427")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_307); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_307); + __gen_e_acsl_literal_string_305 = "tests/format/printf.c:426"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_305, + sizeof("tests/format/printf.c:426")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_305); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_305); + __gen_e_acsl_literal_string_303 = "tests/format/printf.c:425"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_303, + sizeof("tests/format/printf.c:425")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_303); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_303); + __gen_e_acsl_literal_string_301 = "tests/format/printf.c:424"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_301, + sizeof("tests/format/printf.c:424")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_301); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_301); + __gen_e_acsl_literal_string_299 = "tests/format/printf.c:423"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_299, + sizeof("tests/format/printf.c:423")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_299); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_299); + __gen_e_acsl_literal_string_297 = "tests/format/printf.c:420"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_297, + sizeof("tests/format/printf.c:420")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_297); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_297); + __gen_e_acsl_literal_string_296 = "tests/format/printf.c:418"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_296, + sizeof("tests/format/printf.c:418")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_296); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_296); + __gen_e_acsl_literal_string_295 = "tests/format/printf.c:415"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_295, + sizeof("tests/format/printf.c:415")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_295); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_295); + __gen_e_acsl_literal_string_294 = "tests/format/printf.c:414"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_294, + sizeof("tests/format/printf.c:414")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_294); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_294); + __gen_e_acsl_literal_string_293 = "tests/format/printf.c:409"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_293, + sizeof("tests/format/printf.c:409")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_293); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_293); + __gen_e_acsl_literal_string_292 = "tests/format/printf.c:408"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_292, + sizeof("tests/format/printf.c:408")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_292); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_292); + __gen_e_acsl_literal_string_291 = "tests/format/printf.c:407"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_291, + sizeof("tests/format/printf.c:407")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_291); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_291); + __gen_e_acsl_literal_string_290 = "tests/format/printf.c:406"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_290, + sizeof("tests/format/printf.c:406")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_290); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_290); + __gen_e_acsl_literal_string_288 = "tests/format/printf.c:399"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_288, + sizeof("tests/format/printf.c:399")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_288); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_288); + __gen_e_acsl_literal_string_287 = "tests/format/printf.c:398"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_287, + sizeof("tests/format/printf.c:398")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_287); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_287); + __gen_e_acsl_literal_string_285 = "tests/format/printf.c:395"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_285, + sizeof("tests/format/printf.c:395")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_285); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_285); + __gen_e_acsl_literal_string_284 = "tests/format/printf.c:394"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_284, + sizeof("tests/format/printf.c:394")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_284); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_284); + __gen_e_acsl_literal_string_283 = "tests/format/printf.c:393"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_283, + sizeof("tests/format/printf.c:393")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_283); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_283); + __gen_e_acsl_literal_string_282 = "tests/format/printf.c:392"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_282, + sizeof("tests/format/printf.c:392")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_282); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_282); + __gen_e_acsl_literal_string_281 = "tests/format/printf.c:391"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_281, + sizeof("tests/format/printf.c:391")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_281); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_281); + __gen_e_acsl_literal_string_280 = "tests/format/printf.c:390"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_280, + sizeof("tests/format/printf.c:390")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_280); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_280); + __gen_e_acsl_literal_string_279 = "tests/format/printf.c:389"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_279, + sizeof("tests/format/printf.c:389")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_279); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_279); + __gen_e_acsl_literal_string_277 = "tests/format/printf.c:386"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_277, + sizeof("tests/format/printf.c:386")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_277); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_277); + __gen_e_acsl_literal_string_276 = "tests/format/printf.c:385"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_276, + sizeof("tests/format/printf.c:385")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_276); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_276); + __gen_e_acsl_literal_string_275 = "tests/format/printf.c:384"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_275, + sizeof("tests/format/printf.c:384")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_275); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_275); + __gen_e_acsl_literal_string_273 = "tests/format/printf.c:383"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_273, + sizeof("tests/format/printf.c:383")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_273); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_273); + __gen_e_acsl_literal_string_271 = "tests/format/printf.c:382"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_271, + sizeof("tests/format/printf.c:382")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_271); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_271); + __gen_e_acsl_literal_string_270 = "tests/format/printf.c:381"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_270, + sizeof("tests/format/printf.c:381")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_270); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_270); + __gen_e_acsl_literal_string_269 = "tests/format/printf.c:380"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_269, + sizeof("tests/format/printf.c:380")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_269); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_269); + __gen_e_acsl_literal_string_267 = "tests/format/printf.c:379"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_267, + sizeof("tests/format/printf.c:379")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_267); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_267); + __gen_e_acsl_literal_string_265 = "tests/format/printf.c:378"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_265, + sizeof("tests/format/printf.c:378")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_265); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_265); + __gen_e_acsl_literal_string_264 = "tests/format/printf.c:377"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_264, + sizeof("tests/format/printf.c:377")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_264); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_264); + __gen_e_acsl_literal_string_263 = "tests/format/printf.c:376"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_263, + sizeof("tests/format/printf.c:376")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_263); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_263); + __gen_e_acsl_literal_string_261 = "tests/format/printf.c:375"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_261, + sizeof("tests/format/printf.c:375")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_261); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_261); + __gen_e_acsl_literal_string_259 = "tests/format/printf.c:374"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_259, + sizeof("tests/format/printf.c:374")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_259); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_259); + __gen_e_acsl_literal_string_258 = "tests/format/printf.c:373"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_258, + sizeof("tests/format/printf.c:373")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_258); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_258); + __gen_e_acsl_literal_string_257 = "tests/format/printf.c:372"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_257, + sizeof("tests/format/printf.c:372")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_257); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_257); + __gen_e_acsl_literal_string_255 = "tests/format/printf.c:371"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_255, + sizeof("tests/format/printf.c:371")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_255); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_255); + __gen_e_acsl_literal_string_253 = "tests/format/printf.c:368"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_253, + sizeof("tests/format/printf.c:368")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_253); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_253); + __gen_e_acsl_literal_string_252 = "tests/format/printf.c:367"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_252, + sizeof("tests/format/printf.c:367")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_252); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_252); + __gen_e_acsl_literal_string_251 = "tests/format/printf.c:366"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_251, + sizeof("tests/format/printf.c:366")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_251); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_251); + __gen_e_acsl_literal_string_249 = "tests/format/printf.c:365"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_249, + sizeof("tests/format/printf.c:365")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_249); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_249); + __gen_e_acsl_literal_string_247 = "tests/format/printf.c:364"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_247, + sizeof("tests/format/printf.c:364")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_247); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_247); + __gen_e_acsl_literal_string_246 = "tests/format/printf.c:363"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_246, + sizeof("tests/format/printf.c:363")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_246); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_246); + __gen_e_acsl_literal_string_245 = "tests/format/printf.c:362"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_245, + sizeof("tests/format/printf.c:362")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_245); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_245); + __gen_e_acsl_literal_string_243 = "tests/format/printf.c:361"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_243, + sizeof("tests/format/printf.c:361")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_243); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_243); + __gen_e_acsl_literal_string_241 = "tests/format/printf.c:360"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_241, + sizeof("tests/format/printf.c:360")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_241); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_241); + __gen_e_acsl_literal_string_240 = "tests/format/printf.c:359"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_240, + sizeof("tests/format/printf.c:359")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_240); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_240); + __gen_e_acsl_literal_string_239 = "tests/format/printf.c:358"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_239, + sizeof("tests/format/printf.c:358")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_239); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_239); + __gen_e_acsl_literal_string_237 = "tests/format/printf.c:357"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_237, + sizeof("tests/format/printf.c:357")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_237); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_237); + __gen_e_acsl_literal_string_235 = "tests/format/printf.c:356"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_235, + sizeof("tests/format/printf.c:356")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_235); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_235); + __gen_e_acsl_literal_string_234 = "tests/format/printf.c:355"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_234, + sizeof("tests/format/printf.c:355")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_234); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_234); + __gen_e_acsl_literal_string_233 = "tests/format/printf.c:354"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_233, + sizeof("tests/format/printf.c:354")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_233); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_233); + __gen_e_acsl_literal_string_231 = "tests/format/printf.c:353"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_231, + sizeof("tests/format/printf.c:353")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_231); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_231); + __gen_e_acsl_literal_string_226 = "tests/format/printf.c:349"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_226, + sizeof("tests/format/printf.c:349")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_226); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_226); + __gen_e_acsl_literal_string_221 = "tests/format/printf.c:347"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_221, + sizeof("tests/format/printf.c:347")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_221); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_221); + __gen_e_acsl_literal_string_216 = "tests/format/printf.c:346"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_216, + sizeof("tests/format/printf.c:346")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_216); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_216); + __gen_e_acsl_literal_string_211 = "tests/format/printf.c:345"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_211, + sizeof("tests/format/printf.c:345")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_211); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_211); + __gen_e_acsl_literal_string_206 = "tests/format/printf.c:343"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_206, + sizeof("tests/format/printf.c:343")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_206); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_206); + __gen_e_acsl_literal_string_201 = "tests/format/printf.c:341"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_201, + sizeof("tests/format/printf.c:341")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_201); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_201); + __gen_e_acsl_literal_string_196 = "tests/format/printf.c:340"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_196, + sizeof("tests/format/printf.c:340")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_196); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_196); + __gen_e_acsl_literal_string_194 = "tests/format/printf.c:337"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_194, + sizeof("tests/format/printf.c:337")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_194); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_194); + __gen_e_acsl_literal_string_193 = "tests/format/printf.c:336"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_193, + sizeof("tests/format/printf.c:336")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_193); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_193); + __gen_e_acsl_literal_string_192 = "tests/format/printf.c:335"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_192, + sizeof("tests/format/printf.c:335")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_192); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_192); + __gen_e_acsl_literal_string_191 = "tests/format/printf.c:334"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_191, + sizeof("tests/format/printf.c:334")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_191); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_191); + __gen_e_acsl_literal_string_190 = "tests/format/printf.c:333"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_190, + sizeof("tests/format/printf.c:333")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_190); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_190); + __gen_e_acsl_literal_string_186 = "tests/format/printf.c:332"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_186, + sizeof("tests/format/printf.c:332")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_186); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_186); + __gen_e_acsl_literal_string_183 = "tests/format/printf.c:329"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_183, + sizeof("tests/format/printf.c:329")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_183); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_183); + __gen_e_acsl_literal_string_180 = "tests/format/printf.c:325"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_180, + sizeof("tests/format/printf.c:325")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_180); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_180); + __gen_e_acsl_literal_string_177 = "tests/format/printf.c:323"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_177, + sizeof("tests/format/printf.c:323")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_177); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_177); + __gen_e_acsl_literal_string_174 = "tests/format/printf.c:322"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_174, + sizeof("tests/format/printf.c:322")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_174); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_174); + __gen_e_acsl_literal_string_172 = "tests/format/printf.c:321"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_172, + sizeof("tests/format/printf.c:321")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_172); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_172); + __gen_e_acsl_literal_string_170 = "tests/format/printf.c:320"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_170, + sizeof("tests/format/printf.c:320")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_170); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_170); + __gen_e_acsl_literal_string_168 = "tests/format/printf.c:317"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_168, + sizeof("tests/format/printf.c:317")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_168); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_168); + __gen_e_acsl_literal_string_167 = "tests/format/printf.c:316"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_167, + sizeof("tests/format/printf.c:316")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_167); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_167); + __gen_e_acsl_literal_string_166 = "tests/format/printf.c:315"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_166, + sizeof("tests/format/printf.c:315")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_166); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_166); + __gen_e_acsl_literal_string_165 = "tests/format/printf.c:314"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_165, + sizeof("tests/format/printf.c:314")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_165); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_165); + __gen_e_acsl_literal_string_164 = "tests/format/printf.c:313"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_164, + sizeof("tests/format/printf.c:313")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_164); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_164); + __gen_e_acsl_literal_string_163 = "tests/format/printf.c:312"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_163, + sizeof("tests/format/printf.c:312")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_163); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_163); + __gen_e_acsl_literal_string_161 = "tests/format/printf.c:311"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_161, + sizeof("tests/format/printf.c:311")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_161); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_161); + __gen_e_acsl_literal_string_159 = "tests/format/printf.c:308"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_159, + sizeof("tests/format/printf.c:308")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_159); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_159); + __gen_e_acsl_literal_string_157 = "tests/format/printf.c:307"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_157, + sizeof("tests/format/printf.c:307")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_157); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_157); + __gen_e_acsl_literal_string_155 = "tests/format/printf.c:306"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_155, + sizeof("tests/format/printf.c:306")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_155); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_155); + __gen_e_acsl_literal_string_152 = "tests/format/printf.c:302"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_152, + sizeof("tests/format/printf.c:302")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_152); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_152); + __gen_e_acsl_literal_string_149 = "tests/format/printf.c:301"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_149, + sizeof("tests/format/printf.c:301")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_149); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_149); + __gen_e_acsl_literal_string_146 = "tests/format/printf.c:300"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_146, + sizeof("tests/format/printf.c:300")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_146); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_146); + __gen_e_acsl_literal_string_143 = "tests/format/printf.c:299"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_143, + sizeof("tests/format/printf.c:299")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_143); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_143); + __gen_e_acsl_literal_string_141 = "tests/format/printf.c:298"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_141, + sizeof("tests/format/printf.c:298")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_141); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_141); + __gen_e_acsl_literal_string_138 = "tests/format/printf.c:295"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_138, + sizeof("tests/format/printf.c:295")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_138); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_138); + __gen_e_acsl_literal_string_135 = "tests/format/printf.c:294"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_135, + sizeof("tests/format/printf.c:294")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_135); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_135); + __gen_e_acsl_literal_string_133 = "tests/format/printf.c:289"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_133, + sizeof("tests/format/printf.c:289")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_133); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_133); + __gen_e_acsl_literal_string_130 = "tests/format/printf.c:288"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_130, + sizeof("tests/format/printf.c:288")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_130); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_130); + __gen_e_acsl_literal_string_128 = "tests/format/printf.c:286"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_128, + sizeof("tests/format/printf.c:286")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_128); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_128); + __gen_e_acsl_literal_string_125 = "tests/format/printf.c:281"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_125, + sizeof("tests/format/printf.c:281")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_125); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_125); + __gen_e_acsl_literal_string_122 = "tests/format/printf.c:280"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_122, + sizeof("tests/format/printf.c:280")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_122); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_122); + __gen_e_acsl_literal_string_119 = "tests/format/printf.c:276"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_119, + sizeof("tests/format/printf.c:276")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_119); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_119); + __gen_e_acsl_literal_string_117 = "tests/format/printf.c:271"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_117, + sizeof("tests/format/printf.c:271")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_117); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_117); + __gen_e_acsl_literal_string_114 = "tests/format/printf.c:268"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_114, + sizeof("tests/format/printf.c:268")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_114); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_114); + __gen_e_acsl_literal_string_111 = "tests/format/printf.c:267"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_111, + sizeof("tests/format/printf.c:267")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_111); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_111); + __gen_e_acsl_literal_string_108 = "tests/format/printf.c:266"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_108, + sizeof("tests/format/printf.c:266")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_108); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_108); + __gen_e_acsl_literal_string_106 = "tests/format/printf.c:265"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_106, + sizeof("tests/format/printf.c:265")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_106); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_106); + __gen_e_acsl_literal_string_102 = "tests/format/printf.c:262"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_102, + sizeof("tests/format/printf.c:262")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_102); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_102); + __gen_e_acsl_literal_string_99 = "tests/format/printf.c:261"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_99, + sizeof("tests/format/printf.c:261")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_99); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_99); + __gen_e_acsl_literal_string_96 = "tests/format/printf.c:260"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_96, + sizeof("tests/format/printf.c:260")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_96); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_96); + __gen_e_acsl_literal_string_94 = "tests/format/printf.c:256"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_94, + sizeof("tests/format/printf.c:256")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_94); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_94); + __gen_e_acsl_literal_string_92 = "tests/format/printf.c:253"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_92, + sizeof("tests/format/printf.c:253")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_92); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_92); + __gen_e_acsl_literal_string_89 = "tests/format/printf.c:251"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_89, + sizeof("tests/format/printf.c:251")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_89); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_89); + __gen_e_acsl_literal_string_86 = "tests/format/printf.c:250"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_86, + sizeof("tests/format/printf.c:250")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_86); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_86); + __gen_e_acsl_literal_string_83 = "tests/format/printf.c:249"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_83, + sizeof("tests/format/printf.c:249")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_83); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_83); + __gen_e_acsl_literal_string_80 = "tests/format/printf.c:248"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_80, + sizeof("tests/format/printf.c:248")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_80); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_80); + __gen_e_acsl_literal_string_78 = "tests/format/printf.c:246"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_78, + sizeof("tests/format/printf.c:246")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_78); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_78); + __gen_e_acsl_literal_string_75 = "tests/format/printf.c:245"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_75, + sizeof("tests/format/printf.c:245")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_75); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_75); + __gen_e_acsl_literal_string_72 = "tests/format/printf.c:244"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_72, + sizeof("tests/format/printf.c:244")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_72); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_72); + __gen_e_acsl_literal_string_70 = "tests/format/printf.c:243"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_70, + sizeof("tests/format/printf.c:243")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_70); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_70); + __gen_e_acsl_literal_string_66 = "tests/format/printf.c:240"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_66, + sizeof("tests/format/printf.c:240")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_66); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_66); + __gen_e_acsl_literal_string_63 = "tests/format/printf.c:239"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_63, + sizeof("tests/format/printf.c:239")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_63); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_63); + __gen_e_acsl_literal_string_60 = "tests/format/printf.c:238"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_60, + sizeof("tests/format/printf.c:238")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_60); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_60); + __gen_e_acsl_literal_string_58 = "tests/format/printf.c:237"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_58, + sizeof("tests/format/printf.c:237")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_58); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_58); + __gen_e_acsl_literal_string_55 = "tests/format/printf.c:234"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_55, + sizeof("tests/format/printf.c:234")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_55); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_55); + __gen_e_acsl_literal_string_52 = "tests/format/printf.c:233"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_52, + sizeof("tests/format/printf.c:233")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_52); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_52); + __gen_e_acsl_literal_string_49 = "tests/format/printf.c:232"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_49, + sizeof("tests/format/printf.c:232")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_49); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_49); + __gen_e_acsl_literal_string_47 = "tests/format/printf.c:231"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_47, + sizeof("tests/format/printf.c:231")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_47); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_47); + __gen_e_acsl_literal_string_44 = "tests/format/printf.c:225"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_44, + sizeof("tests/format/printf.c:225")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_44); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_44); + __gen_e_acsl_literal_string_42 = "tests/format/printf.c:224"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_42, + sizeof("tests/format/printf.c:224")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_42); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_42); + __gen_e_acsl_literal_string_40 = "tests/format/printf.c:223"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_40, + sizeof("tests/format/printf.c:223")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_40); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_40); + __gen_e_acsl_literal_string_38 = "tests/format/printf.c:217"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_38, + sizeof("tests/format/printf.c:217")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_38); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_38); + __gen_e_acsl_literal_string_35 = "tests/format/printf.c:214"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_35, + sizeof("tests/format/printf.c:214")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_35); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_35); + __gen_e_acsl_literal_string_32 = "tests/format/printf.c:208"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_32, + sizeof("tests/format/printf.c:208")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_32); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_32); + __gen_e_acsl_literal_string_29 = "tests/format/printf.c:205"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_29, + sizeof("tests/format/printf.c:205")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_29); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_29); + __gen_e_acsl_literal_string_27 = "tests/format/printf.c:203"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_27, + sizeof("tests/format/printf.c:203")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_27); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_27); + __gen_e_acsl_literal_string_25 = "tests/format/printf.c:200"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_25, + sizeof("tests/format/printf.c:200")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_25); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_25); + __gen_e_acsl_literal_string_23 = "tests/format/printf.c:198"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_23, + sizeof("tests/format/printf.c:198")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_23); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_23); + __gen_e_acsl_literal_string_21 = "tests/format/printf.c:196"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_21, + sizeof("tests/format/printf.c:196")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_21); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_21); + __gen_e_acsl_literal_string_19 = "tests/format/printf.c:193"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_19, + sizeof("tests/format/printf.c:193")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_19); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_19); + __gen_e_acsl_literal_string_18 = "tests/format/printf.c:188"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_18, + sizeof("tests/format/printf.c:188")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_18); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_18); + __gen_e_acsl_literal_string_16 = "tests/format/printf.c:185"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_16, + sizeof("tests/format/printf.c:185")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_16); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_16); + __gen_e_acsl_literal_string_14 = "tests/format/printf.c:182"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_14, + sizeof("tests/format/printf.c:182")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_14); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_14); + __gen_e_acsl_literal_string_12 = "tests/format/printf.c:179"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_12, + sizeof("tests/format/printf.c:179")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_12); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_12); + __gen_e_acsl_literal_string_33 = "oxXaAeEfFgG"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_33, + sizeof("oxXaAeEfFgG")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_33); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_33); + __gen_e_acsl_literal_string_9 = "foo"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_9,sizeof("foo")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_9); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_9); + __gen_e_acsl_literal_string_6 = "fFeEgGaA"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_6, + sizeof("fFeEgGaA")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_6); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_6); + __gen_e_acsl_literal_string_338 = "diouxfFeEgGaAcspn"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_338, + sizeof("diouxfFeEgGaAcspn")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_338); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_338); + __gen_e_acsl_literal_string_68 = "diouxXncsaAeEfFgG"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_68, + sizeof("diouxXncsaAeEfFgG")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_68); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_68); + __gen_e_acsl_literal_string_45 = "diouxXn"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_45, + sizeof("diouxXn")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_45); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_45); + __gen_e_acsl_literal_string_30 = "diouxXaAeEfFgGs"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_30, + sizeof("diouxXaAeEfFgGs")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_30); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_30); + __gen_e_acsl_literal_string_36 = "diouxXaAeEfFgG"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_36, + sizeof("diouxXaAeEfFgG")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_36); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_36); + __gen_e_acsl_literal_string_8 = "dic"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_8,sizeof("dic")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_8); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_8); + __gen_e_acsl_literal_string_139 = "aAeEfFgG"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_139, + sizeof("aAeEfFgG")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_139); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_139); + __gen_e_acsl_literal_string = "TEST %d: "; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string, + sizeof("TEST %d: ")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string); + __gen_e_acsl_literal_string_2 = "OK: Expected signal at %s\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_2, + sizeof("OK: Expected signal at %s\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_2); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_2); + __gen_e_acsl_literal_string_3 = "OK: Expected execution at %s\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_3, + sizeof("OK: Expected execution at %s\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_3); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_3); + __gen_e_acsl_literal_string_10 = "Hello world!"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_10, + sizeof("Hello world!")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_10); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_10); + __gen_e_acsl_literal_string_11 = "Hello world\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_11, + sizeof("Hello world\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_11); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_11); + __gen_e_acsl_literal_string_5 = "FAIL: Unexpected signal at %s\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_5, + sizeof("FAIL: Unexpected signal at %s\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_5); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_5); + __gen_e_acsl_literal_string_4 = "FAIL: Unexpected execution at %s\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_4, + sizeof("FAIL: Unexpected execution at %s\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_4); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_4); + __gen_e_acsl_literal_string_223 = "%zx\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_223, + sizeof("%zx\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_223); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_223); + __gen_e_acsl_literal_string_124 = "%zx"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_124,sizeof("%zx")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_124); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_124); + __gen_e_acsl_literal_string_220 = "%zu\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_220, + sizeof("%zu\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_220); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_220); + __gen_e_acsl_literal_string_121 = "%zu"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_121,sizeof("%zu")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_121); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_121); + __gen_e_acsl_literal_string_222 = "%zo\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_222, + sizeof("%zo\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_222); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_222); + __gen_e_acsl_literal_string_123 = "%zo"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_123,sizeof("%zo")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_123); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_123); + __gen_e_acsl_literal_string_126 = "%zn"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_126,sizeof("%zn")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_126); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_126); + __gen_e_acsl_literal_string_120 = "%zi"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_120,sizeof("%zi")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_120); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_120); + __gen_e_acsl_literal_string_118 = "%zd"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_118,sizeof("%zd")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_118); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_118); + __gen_e_acsl_literal_string_224 = "%zX\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_224, + sizeof("%zX\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_224); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_224); + __gen_e_acsl_literal_string_116 = "%zX"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_116,sizeof("%zX")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_116); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_116); + __gen_e_acsl_literal_string_188 = "%x\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_188, + sizeof("%x\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_188); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_188); + __gen_e_acsl_literal_string_185 = "%u\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_185, + sizeof("%u\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_185); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_185); + __gen_e_acsl_literal_string_228 = "%tx\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_228, + sizeof("%tx\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_228); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_228); + __gen_e_acsl_literal_string_132 = "%tx"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_132,sizeof("%tx")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_132); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_132); + __gen_e_acsl_literal_string_225 = "%tu\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_225, + sizeof("%tu\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_225); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_225); + __gen_e_acsl_literal_string_129 = "%tu"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_129,sizeof("%tu")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_129); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_129); + __gen_e_acsl_literal_string_227 = "%to\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_227, + sizeof("%to\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_227); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_227); + __gen_e_acsl_literal_string_131 = "%to"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_131,sizeof("%to")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_131); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_131); + __gen_e_acsl_literal_string_137 = "%tn"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_137,sizeof("%tn")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_137); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_137); + __gen_e_acsl_literal_string_182 = "%ti\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_182, + sizeof("%ti\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_182); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_182); + __gen_e_acsl_literal_string_136 = "%ti"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_136,sizeof("%ti")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_136); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_136); + __gen_e_acsl_literal_string_184 = "%td\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_184, + sizeof("%td\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_184); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_184); + __gen_e_acsl_literal_string_134 = "%td"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_134,sizeof("%td")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_134); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_134); + __gen_e_acsl_literal_string_229 = "%tX\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_229, + sizeof("%tX\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_229); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_229); + __gen_e_acsl_literal_string_127 = "%tX"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_127,sizeof("%tX")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_127); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_127); + __gen_e_acsl_literal_string_26 = "%s Say it %2$d or %3$u times \n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_26, + sizeof("%s Say it %2$d or %3$u times \n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_26); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_26); + __gen_e_acsl_literal_string_17 = "%s - %s. Say it %d or %u times \n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_17, + sizeof("%s - %s. Say it %d or %u times \n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_17); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_17); + __gen_e_acsl_literal_string_13 = "%s - %s! Say it %d or %u times \n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_13, + sizeof("%s - %s! Say it %d or %u times \n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_13); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_13); + __gen_e_acsl_literal_string_15 = "%s - %s and say it %d or %u more times \n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_15, + sizeof("%s - %s and say it %d or %u more times \n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_15); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_15); + __gen_e_acsl_literal_string_289 = "%s\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_289, + sizeof("%s\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_289); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_289); + __gen_e_acsl_literal_string_308 = "%p"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_308,sizeof("%p")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_308); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_308); + __gen_e_acsl_literal_string_187 = "%o\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_187, + sizeof("%o\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_187); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_187); + __gen_e_acsl_literal_string_312 = "%n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_312,sizeof("%n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_312); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_312); + __gen_e_acsl_literal_string_158 = "%m\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_158, + sizeof("%m\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_158); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_158); + __gen_e_acsl_literal_string_198 = "%lx\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_198, + sizeof("%lx\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_198); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_198); + __gen_e_acsl_literal_string_77 = "%lx"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_77,sizeof("%lx")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_77); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_77); + __gen_e_acsl_literal_string_195 = "%lu\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_195, + sizeof("%lu\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_195); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_195); + __gen_e_acsl_literal_string_74 = "%lu"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_74,sizeof("%lu")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_74); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_74); + __gen_e_acsl_literal_string_197 = "%lo\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_197, + sizeof("%lo\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_197); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_197); + __gen_e_acsl_literal_string_76 = "%lo"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_76,sizeof("%lo")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_76); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_76); + __gen_e_acsl_literal_string_91 = "%ln"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_91,sizeof("%ln")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_91); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_91); + __gen_e_acsl_literal_string_203 = "%llx\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_203, + sizeof("%llx\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_203); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_203); + __gen_e_acsl_literal_string_101 = "%llx"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_101, + sizeof("%llx")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_101); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_101); + __gen_e_acsl_literal_string_200 = "%llu\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_200, + sizeof("%llu\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_200); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_200); + __gen_e_acsl_literal_string_98 = "%llu"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_98,sizeof("%llu")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_98); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_98); + __gen_e_acsl_literal_string_202 = "%llo\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_202, + sizeof("%llo\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_202); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_202); + __gen_e_acsl_literal_string_100 = "%llo"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_100, + sizeof("%llo")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_100); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_100); + __gen_e_acsl_literal_string_104 = "%lln"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_104, + sizeof("%lln")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_104); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_104); + __gen_e_acsl_literal_string_43 = "%llld\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_43, + sizeof("%llld\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_43); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_43); + __gen_e_acsl_literal_string_171 = "%lli\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_171, + sizeof("%lli\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_171); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_171); + __gen_e_acsl_literal_string_97 = "%lli"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_97,sizeof("%lli")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_97); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_97); + __gen_e_acsl_literal_string_41 = "%lld\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_41, + sizeof("%lld\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_41); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_41); + __gen_e_acsl_literal_string_95 = "%lld"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_95,sizeof("%lld")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_95); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_95); + __gen_e_acsl_literal_string_204 = "%llX\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_204, + sizeof("%llX\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_204); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_204); + __gen_e_acsl_literal_string_103 = "%llX"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_103, + sizeof("%llX")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_103); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_103); + __gen_e_acsl_literal_string_169 = "%li\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_169, + sizeof("%li\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_169); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_169); + __gen_e_acsl_literal_string_73 = "%li"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_73,sizeof("%li")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_73); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_73); + __gen_e_acsl_literal_string_39 = "%ld\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_39, + sizeof("%ld\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_39); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_39); + __gen_e_acsl_literal_string_71 = "%ld"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_71,sizeof("%ld")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_71); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_71); + __gen_e_acsl_literal_string_286 = "%lc\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_286, + sizeof("%lc\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_286); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_286); + __gen_e_acsl_literal_string_93 = "%lc"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_93,sizeof("%lc")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_93); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_93); + __gen_e_acsl_literal_string_199 = "%lX\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_199, + sizeof("%lX\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_199); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_199); + __gen_e_acsl_literal_string_69 = "%lX"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_69,sizeof("%lX")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_69); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_69); + __gen_e_acsl_literal_string_218 = "%jx\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_218, + sizeof("%jx\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_218); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_218); + __gen_e_acsl_literal_string_113 = "%jx"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_113,sizeof("%jx")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_113); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_113); + __gen_e_acsl_literal_string_215 = "%ju\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_215, + sizeof("%ju\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_215); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_215); + __gen_e_acsl_literal_string_110 = "%ju"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_110,sizeof("%ju")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_110); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_110); + __gen_e_acsl_literal_string_217 = "%jo\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_217, + sizeof("%jo\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_217); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_217); + __gen_e_acsl_literal_string_112 = "%jo"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_112,sizeof("%jo")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_112); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_112); + __gen_e_acsl_literal_string_115 = "%jn"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_115,sizeof("%jn")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_115); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_115); + __gen_e_acsl_literal_string_179 = "%ji\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_179, + sizeof("%ji\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_179); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_179); + __gen_e_acsl_literal_string_109 = "%ji"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_109,sizeof("%ji")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_109); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_109); + __gen_e_acsl_literal_string_181 = "%jd\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_181, + sizeof("%jd\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_181); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_181); + __gen_e_acsl_literal_string_107 = "%jd"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_107,sizeof("%jd")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_107); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_107); + __gen_e_acsl_literal_string_219 = "%jX\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_219, + sizeof("%jX\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_219); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_219); + __gen_e_acsl_literal_string_105 = "%jX"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_105,sizeof("%jX")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_105); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_105); + __gen_e_acsl_literal_string_160 = "%i\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_160, + sizeof("%i\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_160); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_160); + __gen_e_acsl_literal_string_208 = "%hx\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_208, + sizeof("%hx\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_208); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_208); + __gen_e_acsl_literal_string_65 = "%hx"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_65,sizeof("%hx")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_65); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_65); + __gen_e_acsl_literal_string_205 = "%hu\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_205, + sizeof("%hu\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_205); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_205); + __gen_e_acsl_literal_string_62 = "%hu"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_62,sizeof("%hu")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_62); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_62); + __gen_e_acsl_literal_string_207 = "%ho\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_207, + sizeof("%ho\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_207); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_207); + __gen_e_acsl_literal_string_64 = "%ho"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_64,sizeof("%ho")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_64); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_64); + __gen_e_acsl_literal_string_67 = "%hn"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_67,sizeof("%hn")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_67); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_67); + __gen_e_acsl_literal_string_173 = "%hi\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_173, + sizeof("%hi\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_173); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_173); + __gen_e_acsl_literal_string_61 = "%hi"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_61,sizeof("%hi")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_61); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_61); + __gen_e_acsl_literal_string_213 = "%hhx\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_213, + sizeof("%hhx\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_213); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_213); + __gen_e_acsl_literal_string_54 = "%hhx"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_54,sizeof("%hhx")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_54); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_54); + __gen_e_acsl_literal_string_210 = "%hhu\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_210, + sizeof("%hhu\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_210); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_210); + __gen_e_acsl_literal_string_51 = "%hhu"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_51,sizeof("%hhu")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_51); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_51); + __gen_e_acsl_literal_string_212 = "%hho\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_212, + sizeof("%hho\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_212); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_212); + __gen_e_acsl_literal_string_53 = "%hho"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_53,sizeof("%hho")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_53); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_53); + __gen_e_acsl_literal_string_56 = "%hhn"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_56,sizeof("%hhn")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_56); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_56); + __gen_e_acsl_literal_string_176 = "%hhi\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_176, + sizeof("%hhi\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_176); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_176); + __gen_e_acsl_literal_string_50 = "%hhi"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_50,sizeof("%hhi")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_50); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_50); + __gen_e_acsl_literal_string_178 = "%hhd\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_178, + sizeof("%hhd\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_178); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_178); + __gen_e_acsl_literal_string_48 = "%hhd"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_48,sizeof("%hhd")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_48); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_48); + __gen_e_acsl_literal_string_214 = "%hhX\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_214, + sizeof("%hhX\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_214); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_214); + __gen_e_acsl_literal_string_46 = "%hhX"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_46,sizeof("%hhX")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_46); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_46); + __gen_e_acsl_literal_string_175 = "%hd\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_175, + sizeof("%hd\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_175); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_175); + __gen_e_acsl_literal_string_59 = "%hd"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_59,sizeof("%hd")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_59); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_59); + __gen_e_acsl_literal_string_209 = "%hX\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_209, + sizeof("%hX\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_209); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_209); + __gen_e_acsl_literal_string_57 = "%hX"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_57,sizeof("%hX")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_57); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_57); + __gen_e_acsl_literal_string_248 = "%g\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_248, + sizeof("%g\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_248); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_248); + __gen_e_acsl_literal_string_88 = "%g"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_88,sizeof("%g")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_88); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_88); + __gen_e_acsl_literal_string_230 = "%f\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_230, + sizeof("%f\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_230); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_230); + __gen_e_acsl_literal_string_79 = "%f"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_79,sizeof("%f")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_79); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_79); + __gen_e_acsl_literal_string_242 = "%e\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_242, + sizeof("%e\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_242); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_242); + __gen_e_acsl_literal_string_82 = "%e"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_82,sizeof("%e")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_82); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_82); + __gen_e_acsl_literal_string_336 = "%d - %\'% - %u times \n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_336, + sizeof("%d - %\'% - %u times \n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_336); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_336); + __gen_e_acsl_literal_string_162 = "%d\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_162, + sizeof("%d\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_162); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_162); + __gen_e_acsl_literal_string_278 = "%c\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_278, + sizeof("%c\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_278); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_278); + __gen_e_acsl_literal_string_236 = "%a\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_236, + sizeof("%a\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_236); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_236); + __gen_e_acsl_literal_string_85 = "%a"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_85,sizeof("%a")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_85); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_85); + __gen_e_acsl_literal_string_189 = "%X\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_189, + sizeof("%X\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_189); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_189); + __gen_e_acsl_literal_string_156 = "%S\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_156, + sizeof("%S\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_156); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_156); + __gen_e_acsl_literal_string_272 = "%Lg\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_272, + sizeof("%Lg\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_272); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_272); + __gen_e_acsl_literal_string_151 = "%Lg"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_151,sizeof("%Lg")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_151); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_151); + __gen_e_acsl_literal_string_254 = "%Lf\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_254, + sizeof("%Lf\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_254); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_254); + __gen_e_acsl_literal_string_142 = "%Lf"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_142,sizeof("%Lf")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_142); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_142); + __gen_e_acsl_literal_string_266 = "%Le\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_266, + sizeof("%Le\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_266); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_266); + __gen_e_acsl_literal_string_145 = "%Le"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_145,sizeof("%Le")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_145); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_145); + __gen_e_acsl_literal_string_260 = "%La\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_260, + sizeof("%La\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_260); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_260); + __gen_e_acsl_literal_string_148 = "%La"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_148,sizeof("%La")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_148); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_148); + __gen_e_acsl_literal_string_140 = "%LX"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_140,sizeof("%LX")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_140); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_140); + __gen_e_acsl_literal_string_274 = "%LG\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_274, + sizeof("%LG\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_274); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_274); + __gen_e_acsl_literal_string_153 = "%LG"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_153,sizeof("%LG")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_153); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_153); + __gen_e_acsl_literal_string_256 = "%LF\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_256, + sizeof("%LF\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_256); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_256); + __gen_e_acsl_literal_string_144 = "%LF"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_144,sizeof("%LF")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_144); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_144); + __gen_e_acsl_literal_string_268 = "%LE\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_268, + sizeof("%LE\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_268); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_268); + __gen_e_acsl_literal_string_147 = "%LE"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_147,sizeof("%LE")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_147); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_147); + __gen_e_acsl_literal_string_262 = "%LA\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_262, + sizeof("%LA\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_262); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_262); + __gen_e_acsl_literal_string_150 = "%LA"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_150,sizeof("%LA")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_150); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_150); + __gen_e_acsl_literal_string_250 = "%G\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_250, + sizeof("%G\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_250); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_250); + __gen_e_acsl_literal_string_90 = "%G"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_90,sizeof("%G")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_90); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_90); + __gen_e_acsl_literal_string_232 = "%F\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_232, + sizeof("%F\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_232); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_232); + __gen_e_acsl_literal_string_81 = "%F"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_81,sizeof("%F")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_81); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_81); + __gen_e_acsl_literal_string_244 = "%E\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_244, + sizeof("%E\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_244); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_244); + __gen_e_acsl_literal_string_84 = "%E"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_84,sizeof("%E")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_84); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_84); + __gen_e_acsl_literal_string_154 = "%C\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_154, + sizeof("%C\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_154); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_154); + __gen_e_acsl_literal_string_238 = "%A\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_238, + sizeof("%A\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_238); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_238); + __gen_e_acsl_literal_string_87 = "%A"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_87,sizeof("%A")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_87); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_87); + __gen_e_acsl_literal_string_22 = "%4$s Say it %2$d or %1$u times \n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_22, + sizeof("%4$s Say it %2$d or %1$u times \n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_22); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_22); + __gen_e_acsl_literal_string_20 = "%3$s Say it %2$d or %1$u times \n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_20, + sizeof("%3$s Say it %2$d or %1$u times \n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_20); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_20); + __gen_e_acsl_literal_string_334 = "%10n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_334, + sizeof("%10n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_334); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_334); + __gen_e_acsl_literal_string_28 = "%1$d - %% - %2$u times \n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_28, + sizeof("%1$d - %% - %2$u times \n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_28); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_28); + __gen_e_acsl_literal_string_319 = "%0n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_319,sizeof("%0n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_319); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_319); + __gen_e_acsl_literal_string_37 = "%0X"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_37,sizeof("%0X")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_37); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_37); + __gen_e_acsl_literal_string_24 = "%0$s Say it %2$d or %1$u times \n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_24, + sizeof("%0$s Say it %2$d or %1$u times \n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_24); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_24); + __gen_e_acsl_literal_string_298 = "%.s\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_298, + sizeof("%.s\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_298); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_298); + __gen_e_acsl_literal_string_329 = "%.n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_329,sizeof("%.n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_329); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_329); + __gen_e_acsl_literal_string_306 = "%.5s\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_306, + sizeof("%.5s\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_306); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_306); + __gen_e_acsl_literal_string_304 = "%.4s\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_304, + sizeof("%.4s\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_304); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_304); + __gen_e_acsl_literal_string_302 = "%.3s\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_302, + sizeof("%.3s\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_302); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_302); + __gen_e_acsl_literal_string_31 = "%.3X"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_31,sizeof("%.3X")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_31); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_31); + __gen_e_acsl_literal_string_331 = "%.2n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_331, + sizeof("%.2n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_331); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_331); + __gen_e_acsl_literal_string_300 = "%.0s\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_300, + sizeof("%.0s\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_300); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_300); + __gen_e_acsl_literal_string_327 = "%-n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_327,sizeof("%-n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_327); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_327); + __gen_e_acsl_literal_string_325 = "%+n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_325,sizeof("%+n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_325); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_325); + __gen_e_acsl_literal_string_317 = "%\'n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_317, + sizeof("%\'n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_317); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_317); + __gen_e_acsl_literal_string_321 = "%#n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_321,sizeof("%#n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_321); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_321); + __gen_e_acsl_literal_string_34 = "%#X"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_34,sizeof("%#X")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_34); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_34); + __gen_e_acsl_literal_string_323 = "% n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_323,sizeof("% n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_323); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_323); + __e_acsl_store_block((void *)(& __gen_e_acsl_strcpy),(size_t)1); + __e_acsl_full_init((void *)(& __gen_e_acsl_strcpy)); + __e_acsl_store_block((void *)(& __gen_e_acsl_strchr),(size_t)1); + __e_acsl_full_init((void *)(& __gen_e_acsl_strchr)); + __e_acsl_store_block((void *)(& __gen_e_acsl_strlen),(size_t)1); + __e_acsl_full_init((void *)(& __gen_e_acsl_strlen)); + __e_acsl_store_block((void *)(& __gen_e_acsl_exit),(size_t)1); + __e_acsl_full_init((void *)(& __gen_e_acsl_exit)); + __e_acsl_store_block((void *)(& __gen_e_acsl_abort),(size_t)1); + __e_acsl_full_init((void *)(& __gen_e_acsl_abort)); + __e_acsl_store_block((void *)(& test_specifier_application),(size_t)1); + __e_acsl_full_init((void *)(& test_specifier_application)); + __e_acsl_store_block((void *)(& apply_specifier),(size_t)1); + __e_acsl_full_init((void *)(& apply_specifier)); + __e_acsl_store_block((void *)(& valid_specifiers),(size_t)8); + __e_acsl_full_init((void *)(& valid_specifiers)); + __e_acsl_store_block((void *)(& signal_eval),(size_t)1); + __e_acsl_full_init((void *)(& signal_eval)); + __e_acsl_store_block((void *)(& testno),(size_t)4); + __e_acsl_full_init((void *)(& testno)); + __e_acsl_store_block((void *)(& __fc_p_time_tm),(size_t)8); + __e_acsl_full_init((void *)(& __fc_p_time_tm)); + __e_acsl_store_block((void *)(& __fc_time_tm),(size_t)36); + __e_acsl_full_init((void *)(& __fc_time_tm)); + __e_acsl_store_block((void *)(__fc_fds),(size_t)4096); + __e_acsl_full_init((void *)(& __fc_fds)); + __e_acsl_store_block((void *)(& __fc_fds_state),(size_t)4); + __e_acsl_full_init((void *)(& __fc_fds_state)); + __e_acsl_store_block((void *)(& __fc_time),(size_t)4); + __e_acsl_full_init((void *)(& __fc_time)); + __e_acsl_store_block((void *)(& __fc_p_strerror),(size_t)8); + __e_acsl_full_init((void *)(& __fc_p_strerror)); + __e_acsl_store_block((void *)(strerror),(size_t)64); + __e_acsl_full_init((void *)(& strerror)); + __e_acsl_store_block((void *)(& __fc_strtok_ptr),(size_t)8); + __e_acsl_full_init((void *)(& __fc_strtok_ptr)); + __e_acsl_store_block((void *)(& __fc_p_fopen),(size_t)8); + __e_acsl_full_init((void *)(& __fc_p_fopen)); + __e_acsl_store_block((void *)(__fc_fopen),(size_t)128); + __e_acsl_full_init((void *)(& __fc_fopen)); + __e_acsl_store_block((void *)(& __fc_rand_max),(size_t)8); + __e_acsl_full_init((void *)(& __fc_rand_max)); + return; +} + +int main(int argc, char const **argv) +{ + int __retres; + char *s2; + __e_acsl_memory_init(& argc,(char ***)(& argv),(size_t)8); + __e_acsl_globals_init(); + __e_acsl_store_block((void *)(& s2),(size_t)8); + __e_acsl_store_block((void *)(& __retres),(size_t)4); + char *pstr = (char *)__gen_e_acsl_literal_string_10; + __e_acsl_store_block((void *)(& pstr),(size_t)8); + __e_acsl_full_init((void *)(& pstr)); + char astr[13] = + {(char)'H', + (char)'e', + (char)'l', + (char)'l', + (char)'o', + (char)' ', + (char)'w', + (char)'o', + (char)'r', + (char)'l', + (char)'d', + (char)'!', + (char)'\000'}; + __e_acsl_store_block((void *)(astr),(size_t)13); + __e_acsl_full_init((void *)(& astr)); + signed char *sastr = (signed char *)(astr); + __e_acsl_store_block((void *)(& sastr),(size_t)8); + __e_acsl_full_init((void *)(& sastr)); + void *vptr = (void *)(& argc); + __e_acsl_store_block((void *)(& vptr),(size_t)8); + __e_acsl_full_init((void *)(& vptr)); + char chr = (char)'T'; + __e_acsl_store_block((void *)(& chr),(size_t)1); + __e_acsl_full_init((void *)(& chr)); + unsigned char uchr = (unsigned char)'U'; + __e_acsl_store_block((void *)(& uchr),(size_t)1); + __e_acsl_full_init((void *)(& uchr)); + short shrt = (short)4569; + __e_acsl_store_block((void *)(& shrt),(size_t)2); + __e_acsl_full_init((void *)(& shrt)); + unsigned short ushrt = (unsigned short)4567; + __e_acsl_store_block((void *)(& ushrt),(size_t)2); + __e_acsl_full_init((void *)(& ushrt)); + int i = 268; + __e_acsl_store_block((void *)(& i),(size_t)4); + __e_acsl_full_init((void *)(& i)); + unsigned int ui = (unsigned int)516; + __e_acsl_store_block((void *)(& ui),(size_t)4); + __e_acsl_full_init((void *)(& ui)); + wint_t wi = (unsigned int)123; + __e_acsl_store_block((void *)(& wi),(size_t)4); + __e_acsl_full_init((void *)(& wi)); + long li = (long)3134; + __e_acsl_store_block((void *)(& li),(size_t)8); + __e_acsl_full_init((void *)(& li)); + unsigned long lu = (unsigned long)7845216; + __e_acsl_store_block((void *)(& lu),(size_t)8); + __e_acsl_full_init((void *)(& lu)); + long long lli = 123LL; + __e_acsl_store_block((void *)(& lli),(size_t)8); + __e_acsl_full_init((void *)(& lli)); + unsigned long long llu = (unsigned long long)123LL; + __e_acsl_store_block((void *)(& llu),(size_t)8); + __e_acsl_full_init((void *)(& llu)); + float flt = (float)0.2; + __e_acsl_store_block((void *)(& flt),(size_t)4); + __e_acsl_full_init((void *)(& flt)); + double dbl = 0.3; + __e_acsl_store_block((void *)(& dbl),(size_t)8); + __e_acsl_full_init((void *)(& dbl)); + long double ldbl = (long double)0.3; + __e_acsl_store_block((void *)(& ldbl),(size_t)16); + __e_acsl_full_init((void *)(& ldbl)); + intmax_t imax = (long long)10; + __e_acsl_store_block((void *)(& imax),(size_t)8); + __e_acsl_full_init((void *)(& imax)); + uintmax_t uimax = (unsigned long long)10; + __e_acsl_store_block((void *)(& uimax),(size_t)8); + __e_acsl_full_init((void *)(& uimax)); + size_t szt = (unsigned long)10; + __e_acsl_store_block((void *)(& szt),(size_t)8); + __e_acsl_full_init((void *)(& szt)); + ptrdiff_t ptrdf = (long)147; + __e_acsl_store_block((void *)(& ptrdf),(size_t)8); + __e_acsl_full_init((void *)(& ptrdf)); + { + pid_t pid = fork(); + __e_acsl_store_block((void *)(& pid),(size_t)4); + __e_acsl_full_init((void *)(& pid)); + if (! pid) { + __e_acsl_builtin_printf("",__gen_e_acsl_literal_string_11); + __gen_e_acsl_exit(0); + } + else { + int process_status; + __e_acsl_store_block((void *)(& process_status),(size_t)4); + waitpid(pid,& process_status,0); + /*@ assert Value: initialization: \initialized(&process_status); */ + signal_eval(process_status,0,__gen_e_acsl_literal_string_12); + __e_acsl_delete_block((void *)(& process_status)); + } + __e_acsl_delete_block((void *)(& pid)); + } + { + pid_t pid_0 = fork(); + __e_acsl_store_block((void *)(& pid_0),(size_t)4); + __e_acsl_full_init((void *)(& pid_0)); + if (! pid_0) { + __e_acsl_builtin_printf("ssdD",__gen_e_acsl_literal_string_13,astr, + pstr,i,ui); + __gen_e_acsl_exit(0); + } + else { + int process_status_0; + __e_acsl_store_block((void *)(& process_status_0),(size_t)4); + waitpid(pid_0,& process_status_0,0); + /*@ assert Value: initialization: \initialized(&process_status_0); */ + signal_eval(process_status_0,0,__gen_e_acsl_literal_string_14); + __e_acsl_delete_block((void *)(& process_status_0)); + } + __e_acsl_delete_block((void *)(& pid_0)); + } + { + pid_t pid_1 = fork(); + __e_acsl_store_block((void *)(& pid_1),(size_t)4); + __e_acsl_full_init((void *)(& pid_1)); + if (! pid_1) { + __e_acsl_builtin_printf("ssd",__gen_e_acsl_literal_string_15,astr,pstr, + i); + __gen_e_acsl_exit(0); + } + else { + int process_status_1; + __e_acsl_store_block((void *)(& process_status_1),(size_t)4); + waitpid(pid_1,& process_status_1,0); + /*@ assert Value: initialization: \initialized(&process_status_1); */ + signal_eval(process_status_1,1,__gen_e_acsl_literal_string_16); + __e_acsl_delete_block((void *)(& process_status_1)); + } + __e_acsl_delete_block((void *)(& pid_1)); + } + { + pid_t pid_2 = fork(); + __e_acsl_store_block((void *)(& pid_2),(size_t)4); + __e_acsl_full_init((void *)(& pid_2)); + if (! pid_2) { + __e_acsl_builtin_printf("ssdDD",__gen_e_acsl_literal_string_17,astr, + pstr,i,ui,ui); + __gen_e_acsl_exit(0); + } + else { + int process_status_2; + __e_acsl_store_block((void *)(& process_status_2),(size_t)4); + waitpid(pid_2,& process_status_2,0); + /*@ assert Value: initialization: \initialized(&process_status_2); */ + signal_eval(process_status_2,0,__gen_e_acsl_literal_string_18); + __e_acsl_delete_block((void *)(& process_status_2)); + } + __e_acsl_delete_block((void *)(& pid_2)); + } + char fmt[7] = + {(char)'f', + (char)'m', + (char)'t', + (char)':', + (char)'%', + (char)'s', + (char)'\000'}; + __e_acsl_store_block((void *)(fmt),(size_t)7); + __e_acsl_full_init((void *)(& fmt)); + __e_acsl_initialize((void *)(& fmt[6]),sizeof(char)); + fmt[6] = (char)'a'; + { + pid_t pid_3 = fork(); + __e_acsl_store_block((void *)(& pid_3),(size_t)4); + __e_acsl_full_init((void *)(& pid_3)); + if (! pid_3) { + __e_acsl_builtin_printf("s",(char const *)(fmt),pstr); + __gen_e_acsl_exit(0); + } + else { + int process_status_3; + __e_acsl_store_block((void *)(& process_status_3),(size_t)4); + waitpid(pid_3,& process_status_3,0); + /*@ assert Value: initialization: \initialized(&process_status_3); */ + signal_eval(process_status_3,1,__gen_e_acsl_literal_string_19); + __e_acsl_delete_block((void *)(& process_status_3)); + } + __e_acsl_delete_block((void *)(& pid_3)); + } + { + pid_t pid_4 = fork(); + __e_acsl_store_block((void *)(& pid_4),(size_t)4); + __e_acsl_full_init((void *)(& pid_4)); + if (! pid_4) { + __e_acsl_builtin_printf("Dds",__gen_e_acsl_literal_string_20,ui,i,astr); + __gen_e_acsl_exit(0); + } + else { + int process_status_4; + __e_acsl_store_block((void *)(& process_status_4),(size_t)4); + waitpid(pid_4,& process_status_4,0); + /*@ assert Value: initialization: \initialized(&process_status_4); */ + signal_eval(process_status_4,0,__gen_e_acsl_literal_string_21); + __e_acsl_delete_block((void *)(& process_status_4)); + } + __e_acsl_delete_block((void *)(& pid_4)); + } + { + pid_t pid_5 = fork(); + __e_acsl_store_block((void *)(& pid_5),(size_t)4); + __e_acsl_full_init((void *)(& pid_5)); + if (! pid_5) { + __e_acsl_builtin_printf("Dds",__gen_e_acsl_literal_string_22,ui,i,astr); + __gen_e_acsl_exit(0); + } + else { + int process_status_5; + __e_acsl_store_block((void *)(& process_status_5),(size_t)4); + waitpid(pid_5,& process_status_5,0); + /*@ assert Value: initialization: \initialized(&process_status_5); */ + signal_eval(process_status_5,1,__gen_e_acsl_literal_string_23); + __e_acsl_delete_block((void *)(& process_status_5)); + } + __e_acsl_delete_block((void *)(& pid_5)); + } + { + pid_t pid_6 = fork(); + __e_acsl_store_block((void *)(& pid_6),(size_t)4); + __e_acsl_full_init((void *)(& pid_6)); + if (! pid_6) { + __e_acsl_builtin_printf("Dds",__gen_e_acsl_literal_string_24,ui,i,astr); + __gen_e_acsl_exit(0); + } + else { + int process_status_6; + __e_acsl_store_block((void *)(& process_status_6),(size_t)4); + waitpid(pid_6,& process_status_6,0); + /*@ assert Value: initialization: \initialized(&process_status_6); */ + signal_eval(process_status_6,1,__gen_e_acsl_literal_string_25); + __e_acsl_delete_block((void *)(& process_status_6)); + } + __e_acsl_delete_block((void *)(& pid_6)); + } + { + pid_t pid_7 = fork(); + __e_acsl_store_block((void *)(& pid_7),(size_t)4); + __e_acsl_full_init((void *)(& pid_7)); + if (! pid_7) { + __e_acsl_builtin_printf("sdD",__gen_e_acsl_literal_string_26,astr,i,ui); + __gen_e_acsl_exit(0); + } + else { + int process_status_7; + __e_acsl_store_block((void *)(& process_status_7),(size_t)4); + waitpid(pid_7,& process_status_7,0); + /*@ assert Value: initialization: \initialized(&process_status_7); */ + signal_eval(process_status_7,1,__gen_e_acsl_literal_string_27); + __e_acsl_delete_block((void *)(& process_status_7)); + } + __e_acsl_delete_block((void *)(& pid_7)); + } + { + pid_t pid_8 = fork(); + __e_acsl_store_block((void *)(& pid_8),(size_t)4); + __e_acsl_full_init((void *)(& pid_8)); + if (! pid_8) { + __e_acsl_builtin_printf("dD",__gen_e_acsl_literal_string_28,i,ui); + __gen_e_acsl_exit(0); + } + else { + int process_status_8; + __e_acsl_store_block((void *)(& process_status_8),(size_t)4); + waitpid(pid_8,& process_status_8,0); + /*@ assert Value: initialization: \initialized(&process_status_8); */ + signal_eval(process_status_8,0,__gen_e_acsl_literal_string_29); + __e_acsl_delete_block((void *)(& process_status_8)); + } + __e_acsl_delete_block((void *)(& pid_8)); + } + test_specifier_application(__gen_e_acsl_literal_string_30, + __gen_e_acsl_literal_string_31,0, + (char *)__gen_e_acsl_literal_string_32); + test_specifier_application(__gen_e_acsl_literal_string_33, + __gen_e_acsl_literal_string_34,0, + (char *)__gen_e_acsl_literal_string_35); + test_specifier_application(__gen_e_acsl_literal_string_36, + __gen_e_acsl_literal_string_37,0, + (char *)__gen_e_acsl_literal_string_38); + { + pid_t pid_9 = fork(); + __e_acsl_store_block((void *)(& pid_9),(size_t)4); + __e_acsl_full_init((void *)(& pid_9)); + if (! pid_9) { + __e_acsl_builtin_printf("l",__gen_e_acsl_literal_string_39,1L); + __gen_e_acsl_exit(0); + } + else { + int process_status_9; + __e_acsl_store_block((void *)(& process_status_9),(size_t)4); + waitpid(pid_9,& process_status_9,0); + signal_eval(process_status_9,0,__gen_e_acsl_literal_string_40); + __e_acsl_delete_block((void *)(& process_status_9)); + } + __e_acsl_delete_block((void *)(& pid_9)); + } + { + pid_t pid_10 = fork(); + __e_acsl_store_block((void *)(& pid_10),(size_t)4); + __e_acsl_full_init((void *)(& pid_10)); + if (! pid_10) { + __e_acsl_builtin_printf("r",__gen_e_acsl_literal_string_41,1LL); + __gen_e_acsl_exit(0); + } + else { + int process_status_10; + __e_acsl_store_block((void *)(& process_status_10),(size_t)4); + waitpid(pid_10,& process_status_10,0); + signal_eval(process_status_10,0,__gen_e_acsl_literal_string_42); + __e_acsl_delete_block((void *)(& process_status_10)); + } + __e_acsl_delete_block((void *)(& pid_10)); + } + { + pid_t pid_11 = fork(); + __e_acsl_store_block((void *)(& pid_11),(size_t)4); + __e_acsl_full_init((void *)(& pid_11)); + if (! pid_11) { + __e_acsl_builtin_printf("r",__gen_e_acsl_literal_string_43,1LL); + __gen_e_acsl_exit(0); + } + else { + int process_status_11; + __e_acsl_store_block((void *)(& process_status_11),(size_t)4); + waitpid(pid_11,& process_status_11,0); + signal_eval(process_status_11,1,__gen_e_acsl_literal_string_44); + __e_acsl_delete_block((void *)(& process_status_11)); + } + __e_acsl_delete_block((void *)(& pid_11)); + } + test_specifier_application(__gen_e_acsl_literal_string_45, + __gen_e_acsl_literal_string_46,1, + (char *)__gen_e_acsl_literal_string_47); + { + pid_t pid_12 = fork(); + __e_acsl_store_block((void *)(& pid_12),(size_t)4); + __e_acsl_full_init((void *)(& pid_12)); + if (! pid_12) { + __e_acsl_builtin_printf("d",__gen_e_acsl_literal_string_48,1); + __gen_e_acsl_exit(0); + } + else { + int process_status_12; + __e_acsl_store_block((void *)(& process_status_12),(size_t)4); + waitpid(pid_12,& process_status_12,0); + signal_eval(process_status_12,0,__gen_e_acsl_literal_string_49); + __e_acsl_delete_block((void *)(& process_status_12)); + } + __e_acsl_delete_block((void *)(& pid_12)); + } + { + pid_t pid_13 = fork(); + __e_acsl_store_block((void *)(& pid_13),(size_t)4); + __e_acsl_full_init((void *)(& pid_13)); + if (! pid_13) { + __e_acsl_builtin_printf("d",__gen_e_acsl_literal_string_50,1); + __gen_e_acsl_exit(0); + } + else { + int process_status_13; + __e_acsl_store_block((void *)(& process_status_13),(size_t)4); + waitpid(pid_13,& process_status_13,0); + signal_eval(process_status_13,0,__gen_e_acsl_literal_string_49); + __e_acsl_delete_block((void *)(& process_status_13)); + } + __e_acsl_delete_block((void *)(& pid_13)); + } + { + pid_t pid_14 = fork(); + __e_acsl_store_block((void *)(& pid_14),(size_t)4); + __e_acsl_full_init((void *)(& pid_14)); + if (! pid_14) { + __e_acsl_builtin_printf("d",__gen_e_acsl_literal_string_51,1); + __gen_e_acsl_exit(0); + } + else { + int process_status_14; + __e_acsl_store_block((void *)(& process_status_14),(size_t)4); + waitpid(pid_14,& process_status_14,0); + signal_eval(process_status_14,0,__gen_e_acsl_literal_string_52); + __e_acsl_delete_block((void *)(& process_status_14)); + } + __e_acsl_delete_block((void *)(& pid_14)); + } + { + pid_t pid_15 = fork(); + __e_acsl_store_block((void *)(& pid_15),(size_t)4); + __e_acsl_full_init((void *)(& pid_15)); + if (! pid_15) { + __e_acsl_builtin_printf("d",__gen_e_acsl_literal_string_53,1); + __gen_e_acsl_exit(0); + } + else { + int process_status_15; + __e_acsl_store_block((void *)(& process_status_15),(size_t)4); + waitpid(pid_15,& process_status_15,0); + signal_eval(process_status_15,0,__gen_e_acsl_literal_string_52); + __e_acsl_delete_block((void *)(& process_status_15)); + } + __e_acsl_delete_block((void *)(& pid_15)); + } + { + pid_t pid_16 = fork(); + __e_acsl_store_block((void *)(& pid_16),(size_t)4); + __e_acsl_full_init((void *)(& pid_16)); + if (! pid_16) { + __e_acsl_builtin_printf("d",__gen_e_acsl_literal_string_54,1); + __gen_e_acsl_exit(0); + } + else { + int process_status_16; + __e_acsl_store_block((void *)(& process_status_16),(size_t)4); + waitpid(pid_16,& process_status_16,0); + signal_eval(process_status_16,0,__gen_e_acsl_literal_string_55); + __e_acsl_delete_block((void *)(& process_status_16)); + } + __e_acsl_delete_block((void *)(& pid_16)); + } + { + pid_t pid_17 = fork(); + __e_acsl_store_block((void *)(& pid_17),(size_t)4); + __e_acsl_full_init((void *)(& pid_17)); + if (! pid_17) { + __e_acsl_builtin_printf("d",__gen_e_acsl_literal_string_46,1); + __gen_e_acsl_exit(0); + } + else { + int process_status_17; + __e_acsl_store_block((void *)(& process_status_17),(size_t)4); + waitpid(pid_17,& process_status_17,0); + signal_eval(process_status_17,0,__gen_e_acsl_literal_string_55); + __e_acsl_delete_block((void *)(& process_status_17)); + } + __e_acsl_delete_block((void *)(& pid_17)); + } + { + pid_t pid_18 = fork(); + __e_acsl_store_block((void *)(& pid_18),(size_t)4); + __e_acsl_full_init((void *)(& pid_18)); + if (! pid_18) { + __e_acsl_builtin_printf("s",__gen_e_acsl_literal_string_56,& chr); + __gen_e_acsl_exit(0); + } + else { + int process_status_18; + __e_acsl_store_block((void *)(& process_status_18),(size_t)4); + waitpid(pid_18,& process_status_18,0); + signal_eval(process_status_18,0,__gen_e_acsl_literal_string_55); + __e_acsl_delete_block((void *)(& process_status_18)); + } + __e_acsl_delete_block((void *)(& pid_18)); + } + test_specifier_application(__gen_e_acsl_literal_string_45, + __gen_e_acsl_literal_string_57,1, + (char *)__gen_e_acsl_literal_string_58); + { + pid_t pid_19 = fork(); + __e_acsl_store_block((void *)(& pid_19),(size_t)4); + __e_acsl_full_init((void *)(& pid_19)); + if (! pid_19) { + __e_acsl_builtin_printf("d",__gen_e_acsl_literal_string_59,1); + __gen_e_acsl_exit(0); + } + else { + int process_status_19; + __e_acsl_store_block((void *)(& process_status_19),(size_t)4); + waitpid(pid_19,& process_status_19,0); + signal_eval(process_status_19,0,__gen_e_acsl_literal_string_60); + __e_acsl_delete_block((void *)(& process_status_19)); + } + __e_acsl_delete_block((void *)(& pid_19)); + } + { + pid_t pid_20 = fork(); + __e_acsl_store_block((void *)(& pid_20),(size_t)4); + __e_acsl_full_init((void *)(& pid_20)); + if (! pid_20) { + __e_acsl_builtin_printf("d",__gen_e_acsl_literal_string_61,1); + __gen_e_acsl_exit(0); + } + else { + int process_status_20; + __e_acsl_store_block((void *)(& process_status_20),(size_t)4); + waitpid(pid_20,& process_status_20,0); + signal_eval(process_status_20,0,__gen_e_acsl_literal_string_60); + __e_acsl_delete_block((void *)(& process_status_20)); + } + __e_acsl_delete_block((void *)(& pid_20)); + } + { + pid_t pid_21 = fork(); + __e_acsl_store_block((void *)(& pid_21),(size_t)4); + __e_acsl_full_init((void *)(& pid_21)); + if (! pid_21) { + __e_acsl_builtin_printf("d",__gen_e_acsl_literal_string_62,1); + __gen_e_acsl_exit(0); + } + else { + int process_status_21; + __e_acsl_store_block((void *)(& process_status_21),(size_t)4); + waitpid(pid_21,& process_status_21,0); + signal_eval(process_status_21,0,__gen_e_acsl_literal_string_63); + __e_acsl_delete_block((void *)(& process_status_21)); + } + __e_acsl_delete_block((void *)(& pid_21)); + } + { + pid_t pid_22 = fork(); + __e_acsl_store_block((void *)(& pid_22),(size_t)4); + __e_acsl_full_init((void *)(& pid_22)); + if (! pid_22) { + __e_acsl_builtin_printf("d",__gen_e_acsl_literal_string_64,1); + __gen_e_acsl_exit(0); + } + else { + int process_status_22; + __e_acsl_store_block((void *)(& process_status_22),(size_t)4); + waitpid(pid_22,& process_status_22,0); + signal_eval(process_status_22,0,__gen_e_acsl_literal_string_63); + __e_acsl_delete_block((void *)(& process_status_22)); + } + __e_acsl_delete_block((void *)(& pid_22)); + } + { + pid_t pid_23 = fork(); + __e_acsl_store_block((void *)(& pid_23),(size_t)4); + __e_acsl_full_init((void *)(& pid_23)); + if (! pid_23) { + __e_acsl_builtin_printf("d",__gen_e_acsl_literal_string_65,1); + __gen_e_acsl_exit(0); + } + else { + int process_status_23; + __e_acsl_store_block((void *)(& process_status_23),(size_t)4); + waitpid(pid_23,& process_status_23,0); + signal_eval(process_status_23,0,__gen_e_acsl_literal_string_66); + __e_acsl_delete_block((void *)(& process_status_23)); + } + __e_acsl_delete_block((void *)(& pid_23)); + } + { + pid_t pid_24 = fork(); + __e_acsl_store_block((void *)(& pid_24),(size_t)4); + __e_acsl_full_init((void *)(& pid_24)); + if (! pid_24) { + __e_acsl_builtin_printf("d",__gen_e_acsl_literal_string_57,1); + __gen_e_acsl_exit(0); + } + else { + int process_status_24; + __e_acsl_store_block((void *)(& process_status_24),(size_t)4); + waitpid(pid_24,& process_status_24,0); + signal_eval(process_status_24,0,__gen_e_acsl_literal_string_66); + __e_acsl_delete_block((void *)(& process_status_24)); + } + __e_acsl_delete_block((void *)(& pid_24)); + } + { + pid_t pid_25 = fork(); + __e_acsl_store_block((void *)(& pid_25),(size_t)4); + __e_acsl_full_init((void *)(& pid_25)); + if (! pid_25) { + __e_acsl_builtin_printf("q",__gen_e_acsl_literal_string_67,& shrt); + __gen_e_acsl_exit(0); + } + else { + int process_status_25; + __e_acsl_store_block((void *)(& process_status_25),(size_t)4); + waitpid(pid_25,& process_status_25,0); + signal_eval(process_status_25,0,__gen_e_acsl_literal_string_66); + __e_acsl_delete_block((void *)(& process_status_25)); + } + __e_acsl_delete_block((void *)(& pid_25)); + } + test_specifier_application(__gen_e_acsl_literal_string_68, + __gen_e_acsl_literal_string_69,1, + (char *)__gen_e_acsl_literal_string_70); + { + pid_t pid_26 = fork(); + __e_acsl_store_block((void *)(& pid_26),(size_t)4); + __e_acsl_full_init((void *)(& pid_26)); + if (! pid_26) { + __e_acsl_builtin_printf("l",__gen_e_acsl_literal_string_71,1L); + __gen_e_acsl_exit(0); + } + else { + int process_status_26; + __e_acsl_store_block((void *)(& process_status_26),(size_t)4); + waitpid(pid_26,& process_status_26,0); + signal_eval(process_status_26,0,__gen_e_acsl_literal_string_72); + __e_acsl_delete_block((void *)(& process_status_26)); + } + __e_acsl_delete_block((void *)(& pid_26)); + } + { + pid_t pid_27 = fork(); + __e_acsl_store_block((void *)(& pid_27),(size_t)4); + __e_acsl_full_init((void *)(& pid_27)); + if (! pid_27) { + __e_acsl_builtin_printf("l",__gen_e_acsl_literal_string_73,1L); + __gen_e_acsl_exit(0); + } + else { + int process_status_27; + __e_acsl_store_block((void *)(& process_status_27),(size_t)4); + waitpid(pid_27,& process_status_27,0); + signal_eval(process_status_27,0,__gen_e_acsl_literal_string_72); + __e_acsl_delete_block((void *)(& process_status_27)); + } + __e_acsl_delete_block((void *)(& pid_27)); + } + { + pid_t pid_28 = fork(); + __e_acsl_store_block((void *)(& pid_28),(size_t)4); + __e_acsl_full_init((void *)(& pid_28)); + if (! pid_28) { + __e_acsl_builtin_printf("L",__gen_e_acsl_literal_string_74,1UL); + __gen_e_acsl_exit(0); + } + else { + int process_status_28; + __e_acsl_store_block((void *)(& process_status_28),(size_t)4); + waitpid(pid_28,& process_status_28,0); + signal_eval(process_status_28,0,__gen_e_acsl_literal_string_75); + __e_acsl_delete_block((void *)(& process_status_28)); + } + __e_acsl_delete_block((void *)(& pid_28)); + } + { + pid_t pid_29 = fork(); + __e_acsl_store_block((void *)(& pid_29),(size_t)4); + __e_acsl_full_init((void *)(& pid_29)); + if (! pid_29) { + __e_acsl_builtin_printf("L",__gen_e_acsl_literal_string_76,1UL); + __gen_e_acsl_exit(0); + } + else { + int process_status_29; + __e_acsl_store_block((void *)(& process_status_29),(size_t)4); + waitpid(pid_29,& process_status_29,0); + signal_eval(process_status_29,0,__gen_e_acsl_literal_string_75); + __e_acsl_delete_block((void *)(& process_status_29)); + } + __e_acsl_delete_block((void *)(& pid_29)); + } + { + pid_t pid_30 = fork(); + __e_acsl_store_block((void *)(& pid_30),(size_t)4); + __e_acsl_full_init((void *)(& pid_30)); + if (! pid_30) { + __e_acsl_builtin_printf("L",__gen_e_acsl_literal_string_77,1UL); + __gen_e_acsl_exit(0); + } + else { + int process_status_30; + __e_acsl_store_block((void *)(& process_status_30),(size_t)4); + waitpid(pid_30,& process_status_30,0); + signal_eval(process_status_30,0,__gen_e_acsl_literal_string_78); + __e_acsl_delete_block((void *)(& process_status_30)); + } + __e_acsl_delete_block((void *)(& pid_30)); + } + { + pid_t pid_31 = fork(); + __e_acsl_store_block((void *)(& pid_31),(size_t)4); + __e_acsl_full_init((void *)(& pid_31)); + if (! pid_31) { + __e_acsl_builtin_printf("L",__gen_e_acsl_literal_string_69,1UL); + __gen_e_acsl_exit(0); + } + else { + int process_status_31; + __e_acsl_store_block((void *)(& process_status_31),(size_t)4); + waitpid(pid_31,& process_status_31,0); + signal_eval(process_status_31,0,__gen_e_acsl_literal_string_78); + __e_acsl_delete_block((void *)(& process_status_31)); + } + __e_acsl_delete_block((void *)(& pid_31)); + } + { + pid_t pid_32 = fork(); + __e_acsl_store_block((void *)(& pid_32),(size_t)4); + __e_acsl_full_init((void *)(& pid_32)); + if (! pid_32) { + __e_acsl_builtin_printf("e",__gen_e_acsl_literal_string_79,dbl); + __gen_e_acsl_exit(0); + } + else { + int process_status_32; + __e_acsl_store_block((void *)(& process_status_32),(size_t)4); + waitpid(pid_32,& process_status_32,0); + signal_eval(process_status_32,0,__gen_e_acsl_literal_string_80); + __e_acsl_delete_block((void *)(& process_status_32)); + } + __e_acsl_delete_block((void *)(& pid_32)); + } + { + pid_t pid_33 = fork(); + __e_acsl_store_block((void *)(& pid_33),(size_t)4); + __e_acsl_full_init((void *)(& pid_33)); + if (! pid_33) { + __e_acsl_builtin_printf("e",__gen_e_acsl_literal_string_81,dbl); + __gen_e_acsl_exit(0); + } + else { + int process_status_33; + __e_acsl_store_block((void *)(& process_status_33),(size_t)4); + waitpid(pid_33,& process_status_33,0); + signal_eval(process_status_33,0,__gen_e_acsl_literal_string_80); + __e_acsl_delete_block((void *)(& process_status_33)); + } + __e_acsl_delete_block((void *)(& pid_33)); + } + { + pid_t pid_34 = fork(); + __e_acsl_store_block((void *)(& pid_34),(size_t)4); + __e_acsl_full_init((void *)(& pid_34)); + if (! pid_34) { + __e_acsl_builtin_printf("e",__gen_e_acsl_literal_string_82,dbl); + __gen_e_acsl_exit(0); + } + else { + int process_status_34; + __e_acsl_store_block((void *)(& process_status_34),(size_t)4); + waitpid(pid_34,& process_status_34,0); + signal_eval(process_status_34,0,__gen_e_acsl_literal_string_83); + __e_acsl_delete_block((void *)(& process_status_34)); + } + __e_acsl_delete_block((void *)(& pid_34)); + } + { + pid_t pid_35 = fork(); + __e_acsl_store_block((void *)(& pid_35),(size_t)4); + __e_acsl_full_init((void *)(& pid_35)); + if (! pid_35) { + __e_acsl_builtin_printf("e",__gen_e_acsl_literal_string_84,dbl); + __gen_e_acsl_exit(0); + } + else { + int process_status_35; + __e_acsl_store_block((void *)(& process_status_35),(size_t)4); + waitpid(pid_35,& process_status_35,0); + signal_eval(process_status_35,0,__gen_e_acsl_literal_string_83); + __e_acsl_delete_block((void *)(& process_status_35)); + } + __e_acsl_delete_block((void *)(& pid_35)); + } + { + pid_t pid_36 = fork(); + __e_acsl_store_block((void *)(& pid_36),(size_t)4); + __e_acsl_full_init((void *)(& pid_36)); + if (! pid_36) { + __e_acsl_builtin_printf("e",__gen_e_acsl_literal_string_85,dbl); + __gen_e_acsl_exit(0); + } + else { + int process_status_36; + __e_acsl_store_block((void *)(& process_status_36),(size_t)4); + waitpid(pid_36,& process_status_36,0); + signal_eval(process_status_36,0,__gen_e_acsl_literal_string_86); + __e_acsl_delete_block((void *)(& process_status_36)); + } + __e_acsl_delete_block((void *)(& pid_36)); + } + { + pid_t pid_37 = fork(); + __e_acsl_store_block((void *)(& pid_37),(size_t)4); + __e_acsl_full_init((void *)(& pid_37)); + if (! pid_37) { + __e_acsl_builtin_printf("e",__gen_e_acsl_literal_string_87,dbl); + __gen_e_acsl_exit(0); + } + else { + int process_status_37; + __e_acsl_store_block((void *)(& process_status_37),(size_t)4); + waitpid(pid_37,& process_status_37,0); + signal_eval(process_status_37,0,__gen_e_acsl_literal_string_86); + __e_acsl_delete_block((void *)(& process_status_37)); + } + __e_acsl_delete_block((void *)(& pid_37)); + } + { + pid_t pid_38 = fork(); + __e_acsl_store_block((void *)(& pid_38),(size_t)4); + __e_acsl_full_init((void *)(& pid_38)); + if (! pid_38) { + __e_acsl_builtin_printf("e",__gen_e_acsl_literal_string_88,dbl); + __gen_e_acsl_exit(0); + } + else { + int process_status_38; + __e_acsl_store_block((void *)(& process_status_38),(size_t)4); + waitpid(pid_38,& process_status_38,0); + signal_eval(process_status_38,0,__gen_e_acsl_literal_string_89); + __e_acsl_delete_block((void *)(& process_status_38)); + } + __e_acsl_delete_block((void *)(& pid_38)); + } + { + pid_t pid_39 = fork(); + __e_acsl_store_block((void *)(& pid_39),(size_t)4); + __e_acsl_full_init((void *)(& pid_39)); + if (! pid_39) { + __e_acsl_builtin_printf("e",__gen_e_acsl_literal_string_90,dbl); + __gen_e_acsl_exit(0); + } + else { + int process_status_39; + __e_acsl_store_block((void *)(& process_status_39),(size_t)4); + waitpid(pid_39,& process_status_39,0); + signal_eval(process_status_39,0,__gen_e_acsl_literal_string_89); + __e_acsl_delete_block((void *)(& process_status_39)); + } + __e_acsl_delete_block((void *)(& pid_39)); + } + { + pid_t pid_40 = fork(); + __e_acsl_store_block((void *)(& pid_40),(size_t)4); + __e_acsl_full_init((void *)(& pid_40)); + if (! pid_40) { + __e_acsl_builtin_printf("z",__gen_e_acsl_literal_string_91,& li); + __gen_e_acsl_exit(0); + } + else { + int process_status_40; + __e_acsl_store_block((void *)(& process_status_40),(size_t)4); + waitpid(pid_40,& process_status_40,0); + signal_eval(process_status_40,0,__gen_e_acsl_literal_string_92); + __e_acsl_delete_block((void *)(& process_status_40)); + } + __e_acsl_delete_block((void *)(& pid_40)); + } + { + pid_t pid_41 = fork(); + __e_acsl_store_block((void *)(& pid_41),(size_t)4); + __e_acsl_full_init((void *)(& pid_41)); + if (! pid_41) { + __e_acsl_builtin_printf("D",__gen_e_acsl_literal_string_93,wi); + __gen_e_acsl_exit(0); + } + else { + int process_status_41; + __e_acsl_store_block((void *)(& process_status_41),(size_t)4); + waitpid(pid_41,& process_status_41,0); + signal_eval(process_status_41,0,__gen_e_acsl_literal_string_94); + __e_acsl_delete_block((void *)(& process_status_41)); + } + __e_acsl_delete_block((void *)(& pid_41)); + } + { + pid_t pid_42 = fork(); + __e_acsl_store_block((void *)(& pid_42),(size_t)4); + __e_acsl_full_init((void *)(& pid_42)); + if (! pid_42) { + __e_acsl_builtin_printf("r",__gen_e_acsl_literal_string_95,1LL); + __gen_e_acsl_exit(0); + } + else { + int process_status_42; + __e_acsl_store_block((void *)(& process_status_42),(size_t)4); + waitpid(pid_42,& process_status_42,0); + signal_eval(process_status_42,0,__gen_e_acsl_literal_string_96); + __e_acsl_delete_block((void *)(& process_status_42)); + } + __e_acsl_delete_block((void *)(& pid_42)); + } + { + pid_t pid_43 = fork(); + __e_acsl_store_block((void *)(& pid_43),(size_t)4); + __e_acsl_full_init((void *)(& pid_43)); + if (! pid_43) { + __e_acsl_builtin_printf("r",__gen_e_acsl_literal_string_97,1LL); + __gen_e_acsl_exit(0); + } + else { + int process_status_43; + __e_acsl_store_block((void *)(& process_status_43),(size_t)4); + waitpid(pid_43,& process_status_43,0); + signal_eval(process_status_43,0,__gen_e_acsl_literal_string_96); + __e_acsl_delete_block((void *)(& process_status_43)); + } + __e_acsl_delete_block((void *)(& pid_43)); + } + { + pid_t pid_44 = fork(); + __e_acsl_store_block((void *)(& pid_44),(size_t)4); + __e_acsl_full_init((void *)(& pid_44)); + if (! pid_44) { + __e_acsl_builtin_printf("R",__gen_e_acsl_literal_string_98,1ULL); + __gen_e_acsl_exit(0); + } + else { + int process_status_44; + __e_acsl_store_block((void *)(& process_status_44),(size_t)4); + waitpid(pid_44,& process_status_44,0); + signal_eval(process_status_44,0,__gen_e_acsl_literal_string_99); + __e_acsl_delete_block((void *)(& process_status_44)); + } + __e_acsl_delete_block((void *)(& pid_44)); + } + { + pid_t pid_45 = fork(); + __e_acsl_store_block((void *)(& pid_45),(size_t)4); + __e_acsl_full_init((void *)(& pid_45)); + if (! pid_45) { + __e_acsl_builtin_printf("R",__gen_e_acsl_literal_string_100,1ULL); + __gen_e_acsl_exit(0); + } + else { + int process_status_45; + __e_acsl_store_block((void *)(& process_status_45),(size_t)4); + waitpid(pid_45,& process_status_45,0); + signal_eval(process_status_45,0,__gen_e_acsl_literal_string_99); + __e_acsl_delete_block((void *)(& process_status_45)); + } + __e_acsl_delete_block((void *)(& pid_45)); + } + { + pid_t pid_46 = fork(); + __e_acsl_store_block((void *)(& pid_46),(size_t)4); + __e_acsl_full_init((void *)(& pid_46)); + if (! pid_46) { + __e_acsl_builtin_printf("R",__gen_e_acsl_literal_string_101,1ULL); + __gen_e_acsl_exit(0); + } + else { + int process_status_46; + __e_acsl_store_block((void *)(& process_status_46),(size_t)4); + waitpid(pid_46,& process_status_46,0); + signal_eval(process_status_46,0,__gen_e_acsl_literal_string_102); + __e_acsl_delete_block((void *)(& process_status_46)); + } + __e_acsl_delete_block((void *)(& pid_46)); + } + { + pid_t pid_47 = fork(); + __e_acsl_store_block((void *)(& pid_47),(size_t)4); + __e_acsl_full_init((void *)(& pid_47)); + if (! pid_47) { + __e_acsl_builtin_printf("R",__gen_e_acsl_literal_string_103,1ULL); + __gen_e_acsl_exit(0); + } + else { + int process_status_47; + __e_acsl_store_block((void *)(& process_status_47),(size_t)4); + waitpid(pid_47,& process_status_47,0); + signal_eval(process_status_47,0,__gen_e_acsl_literal_string_102); + __e_acsl_delete_block((void *)(& process_status_47)); + } + __e_acsl_delete_block((void *)(& pid_47)); + } + { + pid_t pid_48 = fork(); + __e_acsl_store_block((void *)(& pid_48),(size_t)4); + __e_acsl_full_init((void *)(& pid_48)); + if (! pid_48) { + __e_acsl_builtin_printf("w",__gen_e_acsl_literal_string_104,& lli); + __gen_e_acsl_exit(0); + } + else { + int process_status_48; + __e_acsl_store_block((void *)(& process_status_48),(size_t)4); + waitpid(pid_48,& process_status_48,0); + signal_eval(process_status_48,0,__gen_e_acsl_literal_string_102); + __e_acsl_delete_block((void *)(& process_status_48)); + } + __e_acsl_delete_block((void *)(& pid_48)); + } + test_specifier_application(__gen_e_acsl_literal_string_45, + __gen_e_acsl_literal_string_105,1, + (char *)__gen_e_acsl_literal_string_106); + { + pid_t pid_49 = fork(); + __e_acsl_store_block((void *)(& pid_49),(size_t)4); + __e_acsl_full_init((void *)(& pid_49)); + if (! pid_49) { + __e_acsl_builtin_printf("r",__gen_e_acsl_literal_string_107,imax); + __gen_e_acsl_exit(0); + } + else { + int process_status_49; + __e_acsl_store_block((void *)(& process_status_49),(size_t)4); + waitpid(pid_49,& process_status_49,0); + signal_eval(process_status_49,0,__gen_e_acsl_literal_string_108); + __e_acsl_delete_block((void *)(& process_status_49)); + } + __e_acsl_delete_block((void *)(& pid_49)); + } + { + pid_t pid_50 = fork(); + __e_acsl_store_block((void *)(& pid_50),(size_t)4); + __e_acsl_full_init((void *)(& pid_50)); + if (! pid_50) { + __e_acsl_builtin_printf("r",__gen_e_acsl_literal_string_109,imax); + __gen_e_acsl_exit(0); + } + else { + int process_status_50; + __e_acsl_store_block((void *)(& process_status_50),(size_t)4); + waitpid(pid_50,& process_status_50,0); + signal_eval(process_status_50,0,__gen_e_acsl_literal_string_108); + __e_acsl_delete_block((void *)(& process_status_50)); + } + __e_acsl_delete_block((void *)(& pid_50)); + } + { + pid_t pid_51 = fork(); + __e_acsl_store_block((void *)(& pid_51),(size_t)4); + __e_acsl_full_init((void *)(& pid_51)); + if (! pid_51) { + __e_acsl_builtin_printf("R",__gen_e_acsl_literal_string_110,uimax); + __gen_e_acsl_exit(0); + } + else { + int process_status_51; + __e_acsl_store_block((void *)(& process_status_51),(size_t)4); + waitpid(pid_51,& process_status_51,0); + signal_eval(process_status_51,0,__gen_e_acsl_literal_string_111); + __e_acsl_delete_block((void *)(& process_status_51)); + } + __e_acsl_delete_block((void *)(& pid_51)); + } + { + pid_t pid_52 = fork(); + __e_acsl_store_block((void *)(& pid_52),(size_t)4); + __e_acsl_full_init((void *)(& pid_52)); + if (! pid_52) { + __e_acsl_builtin_printf("R",__gen_e_acsl_literal_string_112,uimax); + __gen_e_acsl_exit(0); + } + else { + int process_status_52; + __e_acsl_store_block((void *)(& process_status_52),(size_t)4); + waitpid(pid_52,& process_status_52,0); + signal_eval(process_status_52,0,__gen_e_acsl_literal_string_111); + __e_acsl_delete_block((void *)(& process_status_52)); + } + __e_acsl_delete_block((void *)(& pid_52)); + } + { + pid_t pid_53 = fork(); + __e_acsl_store_block((void *)(& pid_53),(size_t)4); + __e_acsl_full_init((void *)(& pid_53)); + if (! pid_53) { + __e_acsl_builtin_printf("R",__gen_e_acsl_literal_string_113,uimax); + __gen_e_acsl_exit(0); + } + else { + int process_status_53; + __e_acsl_store_block((void *)(& process_status_53),(size_t)4); + waitpid(pid_53,& process_status_53,0); + signal_eval(process_status_53,0,__gen_e_acsl_literal_string_114); + __e_acsl_delete_block((void *)(& process_status_53)); + } + __e_acsl_delete_block((void *)(& pid_53)); + } + { + pid_t pid_54 = fork(); + __e_acsl_store_block((void *)(& pid_54),(size_t)4); + __e_acsl_full_init((void *)(& pid_54)); + if (! pid_54) { + __e_acsl_builtin_printf("R",__gen_e_acsl_literal_string_105,uimax); + __gen_e_acsl_exit(0); + } + else { + int process_status_54; + __e_acsl_store_block((void *)(& process_status_54),(size_t)4); + waitpid(pid_54,& process_status_54,0); + signal_eval(process_status_54,0,__gen_e_acsl_literal_string_114); + __e_acsl_delete_block((void *)(& process_status_54)); + } + __e_acsl_delete_block((void *)(& pid_54)); + } + { + pid_t pid_55 = fork(); + __e_acsl_store_block((void *)(& pid_55),(size_t)4); + __e_acsl_full_init((void *)(& pid_55)); + if (! pid_55) { + __e_acsl_builtin_printf("w",__gen_e_acsl_literal_string_115,& imax); + __gen_e_acsl_exit(0); + } + else { + int process_status_55; + __e_acsl_store_block((void *)(& process_status_55),(size_t)4); + waitpid(pid_55,& process_status_55,0); + signal_eval(process_status_55,0,__gen_e_acsl_literal_string_114); + __e_acsl_delete_block((void *)(& process_status_55)); + } + __e_acsl_delete_block((void *)(& pid_55)); + } + test_specifier_application(__gen_e_acsl_literal_string_45, + __gen_e_acsl_literal_string_116,1, + (char *)__gen_e_acsl_literal_string_117); + { + pid_t pid_56 = fork(); + __e_acsl_store_block((void *)(& pid_56),(size_t)4); + __e_acsl_full_init((void *)(& pid_56)); + if (! pid_56) { + __e_acsl_builtin_printf("l",__gen_e_acsl_literal_string_118,li); + __gen_e_acsl_exit(0); + } + else { + int process_status_56; + __e_acsl_store_block((void *)(& process_status_56),(size_t)4); + waitpid(pid_56,& process_status_56,0); + signal_eval(process_status_56,0,__gen_e_acsl_literal_string_119); + __e_acsl_delete_block((void *)(& process_status_56)); + } + __e_acsl_delete_block((void *)(& pid_56)); + } + { + pid_t pid_57 = fork(); + __e_acsl_store_block((void *)(& pid_57),(size_t)4); + __e_acsl_full_init((void *)(& pid_57)); + if (! pid_57) { + __e_acsl_builtin_printf("l",__gen_e_acsl_literal_string_120,li); + __gen_e_acsl_exit(0); + } + else { + int process_status_57; + __e_acsl_store_block((void *)(& process_status_57),(size_t)4); + waitpid(pid_57,& process_status_57,0); + signal_eval(process_status_57,0,__gen_e_acsl_literal_string_119); + __e_acsl_delete_block((void *)(& process_status_57)); + } + __e_acsl_delete_block((void *)(& pid_57)); + } + { + pid_t pid_58 = fork(); + __e_acsl_store_block((void *)(& pid_58),(size_t)4); + __e_acsl_full_init((void *)(& pid_58)); + if (! pid_58) { + __e_acsl_builtin_printf("L",__gen_e_acsl_literal_string_121,szt); + __gen_e_acsl_exit(0); + } + else { + int process_status_58; + __e_acsl_store_block((void *)(& process_status_58),(size_t)4); + waitpid(pid_58,& process_status_58,0); + signal_eval(process_status_58,0,__gen_e_acsl_literal_string_122); + __e_acsl_delete_block((void *)(& process_status_58)); + } + __e_acsl_delete_block((void *)(& pid_58)); + } + { + pid_t pid_59 = fork(); + __e_acsl_store_block((void *)(& pid_59),(size_t)4); + __e_acsl_full_init((void *)(& pid_59)); + if (! pid_59) { + __e_acsl_builtin_printf("L",__gen_e_acsl_literal_string_123,szt); + __gen_e_acsl_exit(0); + } + else { + int process_status_59; + __e_acsl_store_block((void *)(& process_status_59),(size_t)4); + waitpid(pid_59,& process_status_59,0); + signal_eval(process_status_59,0,__gen_e_acsl_literal_string_122); + __e_acsl_delete_block((void *)(& process_status_59)); + } + __e_acsl_delete_block((void *)(& pid_59)); + } + { + pid_t pid_60 = fork(); + __e_acsl_store_block((void *)(& pid_60),(size_t)4); + __e_acsl_full_init((void *)(& pid_60)); + if (! pid_60) { + __e_acsl_builtin_printf("L",__gen_e_acsl_literal_string_124,szt); + __gen_e_acsl_exit(0); + } + else { + int process_status_60; + __e_acsl_store_block((void *)(& process_status_60),(size_t)4); + waitpid(pid_60,& process_status_60,0); + signal_eval(process_status_60,0,__gen_e_acsl_literal_string_125); + __e_acsl_delete_block((void *)(& process_status_60)); + } + __e_acsl_delete_block((void *)(& pid_60)); + } + { + pid_t pid_61 = fork(); + __e_acsl_store_block((void *)(& pid_61),(size_t)4); + __e_acsl_full_init((void *)(& pid_61)); + if (! pid_61) { + __e_acsl_builtin_printf("L",__gen_e_acsl_literal_string_116,szt); + __gen_e_acsl_exit(0); + } + else { + int process_status_61; + __e_acsl_store_block((void *)(& process_status_61),(size_t)4); + waitpid(pid_61,& process_status_61,0); + signal_eval(process_status_61,0,__gen_e_acsl_literal_string_125); + __e_acsl_delete_block((void *)(& process_status_61)); + } + __e_acsl_delete_block((void *)(& pid_61)); + } + { + pid_t pid_62 = fork(); + __e_acsl_store_block((void *)(& pid_62),(size_t)4); + __e_acsl_full_init((void *)(& pid_62)); + if (! pid_62) { + __e_acsl_builtin_printf("Z",__gen_e_acsl_literal_string_126,& szt); + __gen_e_acsl_exit(0); + } + else { + int process_status_62; + __e_acsl_store_block((void *)(& process_status_62),(size_t)4); + waitpid(pid_62,& process_status_62,0); + signal_eval(process_status_62,0,__gen_e_acsl_literal_string_125); + __e_acsl_delete_block((void *)(& process_status_62)); + } + __e_acsl_delete_block((void *)(& pid_62)); + } + test_specifier_application(__gen_e_acsl_literal_string_45, + __gen_e_acsl_literal_string_127,1, + (char *)__gen_e_acsl_literal_string_128); + { + pid_t pid_63 = fork(); + __e_acsl_store_block((void *)(& pid_63),(size_t)4); + __e_acsl_full_init((void *)(& pid_63)); + if (! pid_63) { + __e_acsl_builtin_printf("L",__gen_e_acsl_literal_string_129,lu); + __gen_e_acsl_exit(0); + } + else { + int process_status_63; + __e_acsl_store_block((void *)(& process_status_63),(size_t)4); + waitpid(pid_63,& process_status_63,0); + signal_eval(process_status_63,0,__gen_e_acsl_literal_string_130); + __e_acsl_delete_block((void *)(& process_status_63)); + } + __e_acsl_delete_block((void *)(& pid_63)); + } + { + pid_t pid_64 = fork(); + __e_acsl_store_block((void *)(& pid_64),(size_t)4); + __e_acsl_full_init((void *)(& pid_64)); + if (! pid_64) { + __e_acsl_builtin_printf("L",__gen_e_acsl_literal_string_131,lu); + __gen_e_acsl_exit(0); + } + else { + int process_status_64; + __e_acsl_store_block((void *)(& process_status_64),(size_t)4); + waitpid(pid_64,& process_status_64,0); + signal_eval(process_status_64,0,__gen_e_acsl_literal_string_130); + __e_acsl_delete_block((void *)(& process_status_64)); + } + __e_acsl_delete_block((void *)(& pid_64)); + } + { + pid_t pid_65 = fork(); + __e_acsl_store_block((void *)(& pid_65),(size_t)4); + __e_acsl_full_init((void *)(& pid_65)); + if (! pid_65) { + __e_acsl_builtin_printf("L",__gen_e_acsl_literal_string_132,lu); + __gen_e_acsl_exit(0); + } + else { + int process_status_65; + __e_acsl_store_block((void *)(& process_status_65),(size_t)4); + waitpid(pid_65,& process_status_65,0); + signal_eval(process_status_65,0,__gen_e_acsl_literal_string_133); + __e_acsl_delete_block((void *)(& process_status_65)); + } + __e_acsl_delete_block((void *)(& pid_65)); + } + { + pid_t pid_66 = fork(); + __e_acsl_store_block((void *)(& pid_66),(size_t)4); + __e_acsl_full_init((void *)(& pid_66)); + if (! pid_66) { + __e_acsl_builtin_printf("L",__gen_e_acsl_literal_string_127,lu); + __gen_e_acsl_exit(0); + } + else { + int process_status_66; + __e_acsl_store_block((void *)(& process_status_66),(size_t)4); + waitpid(pid_66,& process_status_66,0); + signal_eval(process_status_66,0,__gen_e_acsl_literal_string_133); + __e_acsl_delete_block((void *)(& process_status_66)); + } + __e_acsl_delete_block((void *)(& pid_66)); + } + { + pid_t pid_67 = fork(); + __e_acsl_store_block((void *)(& pid_67),(size_t)4); + __e_acsl_full_init((void *)(& pid_67)); + if (! pid_67) { + __e_acsl_builtin_printf("l",__gen_e_acsl_literal_string_134,ptrdf); + __gen_e_acsl_exit(0); + } + else { + int process_status_67; + __e_acsl_store_block((void *)(& process_status_67),(size_t)4); + waitpid(pid_67,& process_status_67,0); + signal_eval(process_status_67,0,__gen_e_acsl_literal_string_135); + __e_acsl_delete_block((void *)(& process_status_67)); + } + __e_acsl_delete_block((void *)(& pid_67)); + } + { + pid_t pid_68 = fork(); + __e_acsl_store_block((void *)(& pid_68),(size_t)4); + __e_acsl_full_init((void *)(& pid_68)); + if (! pid_68) { + __e_acsl_builtin_printf("l",__gen_e_acsl_literal_string_136,ptrdf); + __gen_e_acsl_exit(0); + } + else { + int process_status_68; + __e_acsl_store_block((void *)(& process_status_68),(size_t)4); + waitpid(pid_68,& process_status_68,0); + signal_eval(process_status_68,0,__gen_e_acsl_literal_string_135); + __e_acsl_delete_block((void *)(& process_status_68)); + } + __e_acsl_delete_block((void *)(& pid_68)); + } + { + pid_t pid_69 = fork(); + __e_acsl_store_block((void *)(& pid_69),(size_t)4); + __e_acsl_full_init((void *)(& pid_69)); + if (! pid_69) { + __e_acsl_builtin_printf("z",__gen_e_acsl_literal_string_137,& ptrdf); + __gen_e_acsl_exit(0); + } + else { + int process_status_69; + __e_acsl_store_block((void *)(& process_status_69),(size_t)4); + waitpid(pid_69,& process_status_69,0); + signal_eval(process_status_69,0,__gen_e_acsl_literal_string_138); + __e_acsl_delete_block((void *)(& process_status_69)); + } + __e_acsl_delete_block((void *)(& pid_69)); + } + test_specifier_application(__gen_e_acsl_literal_string_139, + __gen_e_acsl_literal_string_140,1, + (char *)__gen_e_acsl_literal_string_141); + { + pid_t pid_70 = fork(); + __e_acsl_store_block((void *)(& pid_70),(size_t)4); + __e_acsl_full_init((void *)(& pid_70)); + if (! pid_70) { + __e_acsl_builtin_printf("E",__gen_e_acsl_literal_string_142,ldbl); + __gen_e_acsl_exit(0); + } + else { + int process_status_70; + __e_acsl_store_block((void *)(& process_status_70),(size_t)4); + waitpid(pid_70,& process_status_70,0); + signal_eval(process_status_70,0,__gen_e_acsl_literal_string_143); + __e_acsl_delete_block((void *)(& process_status_70)); + } + __e_acsl_delete_block((void *)(& pid_70)); + } + { + pid_t pid_71 = fork(); + __e_acsl_store_block((void *)(& pid_71),(size_t)4); + __e_acsl_full_init((void *)(& pid_71)); + if (! pid_71) { + __e_acsl_builtin_printf("E",__gen_e_acsl_literal_string_144,ldbl); + __gen_e_acsl_exit(0); + } + else { + int process_status_71; + __e_acsl_store_block((void *)(& process_status_71),(size_t)4); + waitpid(pid_71,& process_status_71,0); + signal_eval(process_status_71,0,__gen_e_acsl_literal_string_143); + __e_acsl_delete_block((void *)(& process_status_71)); + } + __e_acsl_delete_block((void *)(& pid_71)); + } + { + pid_t pid_72 = fork(); + __e_acsl_store_block((void *)(& pid_72),(size_t)4); + __e_acsl_full_init((void *)(& pid_72)); + if (! pid_72) { + __e_acsl_builtin_printf("E",__gen_e_acsl_literal_string_145,ldbl); + __gen_e_acsl_exit(0); + } + else { + int process_status_72; + __e_acsl_store_block((void *)(& process_status_72),(size_t)4); + waitpid(pid_72,& process_status_72,0); + signal_eval(process_status_72,0,__gen_e_acsl_literal_string_146); + __e_acsl_delete_block((void *)(& process_status_72)); + } + __e_acsl_delete_block((void *)(& pid_72)); + } + { + pid_t pid_73 = fork(); + __e_acsl_store_block((void *)(& pid_73),(size_t)4); + __e_acsl_full_init((void *)(& pid_73)); + if (! pid_73) { + __e_acsl_builtin_printf("E",__gen_e_acsl_literal_string_147,ldbl); + __gen_e_acsl_exit(0); + } + else { + int process_status_73; + __e_acsl_store_block((void *)(& process_status_73),(size_t)4); + waitpid(pid_73,& process_status_73,0); + signal_eval(process_status_73,0,__gen_e_acsl_literal_string_146); + __e_acsl_delete_block((void *)(& process_status_73)); + } + __e_acsl_delete_block((void *)(& pid_73)); + } + { + pid_t pid_74 = fork(); + __e_acsl_store_block((void *)(& pid_74),(size_t)4); + __e_acsl_full_init((void *)(& pid_74)); + if (! pid_74) { + __e_acsl_builtin_printf("E",__gen_e_acsl_literal_string_148,ldbl); + __gen_e_acsl_exit(0); + } + else { + int process_status_74; + __e_acsl_store_block((void *)(& process_status_74),(size_t)4); + waitpid(pid_74,& process_status_74,0); + signal_eval(process_status_74,0,__gen_e_acsl_literal_string_149); + __e_acsl_delete_block((void *)(& process_status_74)); + } + __e_acsl_delete_block((void *)(& pid_74)); + } + { + pid_t pid_75 = fork(); + __e_acsl_store_block((void *)(& pid_75),(size_t)4); + __e_acsl_full_init((void *)(& pid_75)); + if (! pid_75) { + __e_acsl_builtin_printf("E",__gen_e_acsl_literal_string_150,ldbl); + __gen_e_acsl_exit(0); + } + else { + int process_status_75; + __e_acsl_store_block((void *)(& process_status_75),(size_t)4); + waitpid(pid_75,& process_status_75,0); + signal_eval(process_status_75,0,__gen_e_acsl_literal_string_149); + __e_acsl_delete_block((void *)(& process_status_75)); + } + __e_acsl_delete_block((void *)(& pid_75)); + } + { + pid_t pid_76 = fork(); + __e_acsl_store_block((void *)(& pid_76),(size_t)4); + __e_acsl_full_init((void *)(& pid_76)); + if (! pid_76) { + __e_acsl_builtin_printf("E",__gen_e_acsl_literal_string_151,ldbl); + __gen_e_acsl_exit(0); + } + else { + int process_status_76; + __e_acsl_store_block((void *)(& process_status_76),(size_t)4); + waitpid(pid_76,& process_status_76,0); + signal_eval(process_status_76,0,__gen_e_acsl_literal_string_152); + __e_acsl_delete_block((void *)(& process_status_76)); + } + __e_acsl_delete_block((void *)(& pid_76)); + } + { + pid_t pid_77 = fork(); + __e_acsl_store_block((void *)(& pid_77),(size_t)4); + __e_acsl_full_init((void *)(& pid_77)); + if (! pid_77) { + __e_acsl_builtin_printf("E",__gen_e_acsl_literal_string_153,ldbl); + __gen_e_acsl_exit(0); + } + else { + int process_status_77; + __e_acsl_store_block((void *)(& process_status_77),(size_t)4); + waitpid(pid_77,& process_status_77,0); + signal_eval(process_status_77,0,__gen_e_acsl_literal_string_152); + __e_acsl_delete_block((void *)(& process_status_77)); + } + __e_acsl_delete_block((void *)(& pid_77)); + } + { + pid_t pid_78 = fork(); + __e_acsl_store_block((void *)(& pid_78),(size_t)4); + __e_acsl_full_init((void *)(& pid_78)); + if (! pid_78) { + __e_acsl_builtin_printf("d",__gen_e_acsl_literal_string_154,1); + __gen_e_acsl_exit(0); + } + else { + int process_status_78; + __e_acsl_store_block((void *)(& process_status_78),(size_t)4); + waitpid(pid_78,& process_status_78,0); + signal_eval(process_status_78,1,__gen_e_acsl_literal_string_155); + __e_acsl_delete_block((void *)(& process_status_78)); + } + __e_acsl_delete_block((void *)(& pid_78)); + } + { + pid_t pid_79 = fork(); + __e_acsl_store_block((void *)(& pid_79),(size_t)4); + __e_acsl_full_init((void *)(& pid_79)); + if (! pid_79) { + __e_acsl_builtin_printf("d",__gen_e_acsl_literal_string_156,1); + __gen_e_acsl_exit(0); + } + else { + int process_status_79; + __e_acsl_store_block((void *)(& process_status_79),(size_t)4); + waitpid(pid_79,& process_status_79,0); + signal_eval(process_status_79,1,__gen_e_acsl_literal_string_157); + __e_acsl_delete_block((void *)(& process_status_79)); + } + __e_acsl_delete_block((void *)(& pid_79)); + } + { + pid_t pid_80 = fork(); + __e_acsl_store_block((void *)(& pid_80),(size_t)4); + __e_acsl_full_init((void *)(& pid_80)); + if (! pid_80) { + __e_acsl_builtin_printf("d",__gen_e_acsl_literal_string_158,1); + __gen_e_acsl_exit(0); + } + else { + int process_status_80; + __e_acsl_store_block((void *)(& process_status_80),(size_t)4); + waitpid(pid_80,& process_status_80,0); + signal_eval(process_status_80,1,__gen_e_acsl_literal_string_159); + __e_acsl_delete_block((void *)(& process_status_80)); + } + __e_acsl_delete_block((void *)(& pid_80)); + } + { + pid_t pid_81 = fork(); + __e_acsl_store_block((void *)(& pid_81),(size_t)4); + __e_acsl_full_init((void *)(& pid_81)); + if (! pid_81) { + __e_acsl_builtin_printf("d",__gen_e_acsl_literal_string_160,i); + __gen_e_acsl_exit(0); + } + else { + int process_status_81; + __e_acsl_store_block((void *)(& process_status_81),(size_t)4); + waitpid(pid_81,& process_status_81,0); + signal_eval(process_status_81,0,__gen_e_acsl_literal_string_161); + __e_acsl_delete_block((void *)(& process_status_81)); + } + __e_acsl_delete_block((void *)(& pid_81)); + } + { + pid_t pid_82 = fork(); + __e_acsl_store_block((void *)(& pid_82),(size_t)4); + __e_acsl_full_init((void *)(& pid_82)); + if (! pid_82) { + __e_acsl_builtin_printf("d",__gen_e_acsl_literal_string_162,i); + __gen_e_acsl_exit(0); + } + else { + int process_status_82; + __e_acsl_store_block((void *)(& process_status_82),(size_t)4); + waitpid(pid_82,& process_status_82,0); + signal_eval(process_status_82,0,__gen_e_acsl_literal_string_161); + __e_acsl_delete_block((void *)(& process_status_82)); + } + __e_acsl_delete_block((void *)(& pid_82)); + } + { + pid_t pid_83 = fork(); + __e_acsl_store_block((void *)(& pid_83),(size_t)4); + __e_acsl_full_init((void *)(& pid_83)); + if (! pid_83) { + __e_acsl_builtin_printf("d",__gen_e_acsl_literal_string_160,(int)chr); + __gen_e_acsl_exit(0); + } + else { + int process_status_83; + __e_acsl_store_block((void *)(& process_status_83),(size_t)4); + waitpid(pid_83,& process_status_83,0); + signal_eval(process_status_83,0,__gen_e_acsl_literal_string_163); + __e_acsl_delete_block((void *)(& process_status_83)); + } + __e_acsl_delete_block((void *)(& pid_83)); + } + { + pid_t pid_84 = fork(); + __e_acsl_store_block((void *)(& pid_84),(size_t)4); + __e_acsl_full_init((void *)(& pid_84)); + if (! pid_84) { + __e_acsl_builtin_printf("d",__gen_e_acsl_literal_string_162,(int)chr); + __gen_e_acsl_exit(0); + } + else { + int process_status_84; + __e_acsl_store_block((void *)(& process_status_84),(size_t)4); + waitpid(pid_84,& process_status_84,0); + signal_eval(process_status_84,0,__gen_e_acsl_literal_string_163); + __e_acsl_delete_block((void *)(& process_status_84)); + } + __e_acsl_delete_block((void *)(& pid_84)); + } + { + pid_t pid_85 = fork(); + __e_acsl_store_block((void *)(& pid_85),(size_t)4); + __e_acsl_full_init((void *)(& pid_85)); + if (! pid_85) { + __e_acsl_builtin_printf("d",__gen_e_acsl_literal_string_160,(int)shrt); + __gen_e_acsl_exit(0); + } + else { + int process_status_85; + __e_acsl_store_block((void *)(& process_status_85),(size_t)4); + waitpid(pid_85,& process_status_85,0); + signal_eval(process_status_85,0,__gen_e_acsl_literal_string_164); + __e_acsl_delete_block((void *)(& process_status_85)); + } + __e_acsl_delete_block((void *)(& pid_85)); + } + { + pid_t pid_86 = fork(); + __e_acsl_store_block((void *)(& pid_86),(size_t)4); + __e_acsl_full_init((void *)(& pid_86)); + if (! pid_86) { + __e_acsl_builtin_printf("d",__gen_e_acsl_literal_string_162,(int)shrt); + __gen_e_acsl_exit(0); + } + else { + int process_status_86; + __e_acsl_store_block((void *)(& process_status_86),(size_t)4); + waitpid(pid_86,& process_status_86,0); + signal_eval(process_status_86,0,__gen_e_acsl_literal_string_164); + __e_acsl_delete_block((void *)(& process_status_86)); + } + __e_acsl_delete_block((void *)(& pid_86)); + } + { + pid_t pid_87 = fork(); + __e_acsl_store_block((void *)(& pid_87),(size_t)4); + __e_acsl_full_init((void *)(& pid_87)); + if (! pid_87) { + __e_acsl_builtin_printf("l",__gen_e_acsl_literal_string_160,li); + __gen_e_acsl_exit(0); + } + else { + int process_status_87; + __e_acsl_store_block((void *)(& process_status_87),(size_t)4); + waitpid(pid_87,& process_status_87,0); + signal_eval(process_status_87,1,__gen_e_acsl_literal_string_165); + __e_acsl_delete_block((void *)(& process_status_87)); + } + __e_acsl_delete_block((void *)(& pid_87)); + } + { + pid_t pid_88 = fork(); + __e_acsl_store_block((void *)(& pid_88),(size_t)4); + __e_acsl_full_init((void *)(& pid_88)); + if (! pid_88) { + __e_acsl_builtin_printf("l",__gen_e_acsl_literal_string_162,li); + __gen_e_acsl_exit(0); + } + else { + int process_status_88; + __e_acsl_store_block((void *)(& process_status_88),(size_t)4); + waitpid(pid_88,& process_status_88,0); + signal_eval(process_status_88,1,__gen_e_acsl_literal_string_165); + __e_acsl_delete_block((void *)(& process_status_88)); + } + __e_acsl_delete_block((void *)(& pid_88)); + } + { + pid_t pid_89 = fork(); + __e_acsl_store_block((void *)(& pid_89),(size_t)4); + __e_acsl_full_init((void *)(& pid_89)); + if (! pid_89) { + __e_acsl_builtin_printf("D",__gen_e_acsl_literal_string_160,ui); + __gen_e_acsl_exit(0); + } + else { + int process_status_89; + __e_acsl_store_block((void *)(& process_status_89),(size_t)4); + waitpid(pid_89,& process_status_89,0); + signal_eval(process_status_89,1,__gen_e_acsl_literal_string_166); + __e_acsl_delete_block((void *)(& process_status_89)); + } + __e_acsl_delete_block((void *)(& pid_89)); + } + { + pid_t pid_90 = fork(); + __e_acsl_store_block((void *)(& pid_90),(size_t)4); + __e_acsl_full_init((void *)(& pid_90)); + if (! pid_90) { + __e_acsl_builtin_printf("D",__gen_e_acsl_literal_string_162,ui); + __gen_e_acsl_exit(0); + } + else { + int process_status_90; + __e_acsl_store_block((void *)(& process_status_90),(size_t)4); + waitpid(pid_90,& process_status_90,0); + signal_eval(process_status_90,1,__gen_e_acsl_literal_string_166); + __e_acsl_delete_block((void *)(& process_status_90)); + } + __e_acsl_delete_block((void *)(& pid_90)); + } + { + pid_t pid_91 = fork(); + __e_acsl_store_block((void *)(& pid_91),(size_t)4); + __e_acsl_full_init((void *)(& pid_91)); + if (! pid_91) { + __e_acsl_builtin_printf("p",__gen_e_acsl_literal_string_160,vptr); + __gen_e_acsl_exit(0); + } + else { + int process_status_91; + __e_acsl_store_block((void *)(& process_status_91),(size_t)4); + waitpid(pid_91,& process_status_91,0); + signal_eval(process_status_91,1,__gen_e_acsl_literal_string_167); + __e_acsl_delete_block((void *)(& process_status_91)); + } + __e_acsl_delete_block((void *)(& pid_91)); + } + { + pid_t pid_92 = fork(); + __e_acsl_store_block((void *)(& pid_92),(size_t)4); + __e_acsl_full_init((void *)(& pid_92)); + if (! pid_92) { + __e_acsl_builtin_printf("p",__gen_e_acsl_literal_string_162,vptr); + __gen_e_acsl_exit(0); + } + else { + int process_status_92; + __e_acsl_store_block((void *)(& process_status_92),(size_t)4); + waitpid(pid_92,& process_status_92,0); + signal_eval(process_status_92,1,__gen_e_acsl_literal_string_167); + __e_acsl_delete_block((void *)(& process_status_92)); + } + __e_acsl_delete_block((void *)(& pid_92)); + } + { + pid_t pid_93 = fork(); + __e_acsl_store_block((void *)(& pid_93),(size_t)4); + __e_acsl_full_init((void *)(& pid_93)); + if (! pid_93) { + __e_acsl_builtin_printf("e",__gen_e_acsl_literal_string_160, + (double)flt); + __gen_e_acsl_exit(0); + } + else { + int process_status_93; + __e_acsl_store_block((void *)(& process_status_93),(size_t)4); + waitpid(pid_93,& process_status_93,0); + signal_eval(process_status_93,1,__gen_e_acsl_literal_string_168); + __e_acsl_delete_block((void *)(& process_status_93)); + } + __e_acsl_delete_block((void *)(& pid_93)); + } + { + pid_t pid_94 = fork(); + __e_acsl_store_block((void *)(& pid_94),(size_t)4); + __e_acsl_full_init((void *)(& pid_94)); + if (! pid_94) { + __e_acsl_builtin_printf("e",__gen_e_acsl_literal_string_162, + (double)flt); + __gen_e_acsl_exit(0); + } + else { + int process_status_94; + __e_acsl_store_block((void *)(& process_status_94),(size_t)4); + waitpid(pid_94,& process_status_94,0); + signal_eval(process_status_94,1,__gen_e_acsl_literal_string_168); + __e_acsl_delete_block((void *)(& process_status_94)); + } + __e_acsl_delete_block((void *)(& pid_94)); + } + { + pid_t pid_95 = fork(); + __e_acsl_store_block((void *)(& pid_95),(size_t)4); + __e_acsl_full_init((void *)(& pid_95)); + if (! pid_95) { + __e_acsl_builtin_printf("l",__gen_e_acsl_literal_string_169,li); + __gen_e_acsl_exit(0); + } + else { + int process_status_95; + __e_acsl_store_block((void *)(& process_status_95),(size_t)4); + waitpid(pid_95,& process_status_95,0); + signal_eval(process_status_95,0,__gen_e_acsl_literal_string_170); + __e_acsl_delete_block((void *)(& process_status_95)); + } + __e_acsl_delete_block((void *)(& pid_95)); + } + { + pid_t pid_96 = fork(); + __e_acsl_store_block((void *)(& pid_96),(size_t)4); + __e_acsl_full_init((void *)(& pid_96)); + if (! pid_96) { + __e_acsl_builtin_printf("l",__gen_e_acsl_literal_string_39,li); + __gen_e_acsl_exit(0); + } + else { + int process_status_96; + __e_acsl_store_block((void *)(& process_status_96),(size_t)4); + waitpid(pid_96,& process_status_96,0); + signal_eval(process_status_96,0,__gen_e_acsl_literal_string_170); + __e_acsl_delete_block((void *)(& process_status_96)); + } + __e_acsl_delete_block((void *)(& pid_96)); + } + { + pid_t pid_97 = fork(); + __e_acsl_store_block((void *)(& pid_97),(size_t)4); + __e_acsl_full_init((void *)(& pid_97)); + if (! pid_97) { + __e_acsl_builtin_printf("r",__gen_e_acsl_literal_string_171,lli); + __gen_e_acsl_exit(0); + } + else { + int process_status_97; + __e_acsl_store_block((void *)(& process_status_97),(size_t)4); + waitpid(pid_97,& process_status_97,0); + signal_eval(process_status_97,0,__gen_e_acsl_literal_string_172); + __e_acsl_delete_block((void *)(& process_status_97)); + } + __e_acsl_delete_block((void *)(& pid_97)); + } + { + pid_t pid_98 = fork(); + __e_acsl_store_block((void *)(& pid_98),(size_t)4); + __e_acsl_full_init((void *)(& pid_98)); + if (! pid_98) { + __e_acsl_builtin_printf("r",__gen_e_acsl_literal_string_41,lli); + __gen_e_acsl_exit(0); + } + else { + int process_status_98; + __e_acsl_store_block((void *)(& process_status_98),(size_t)4); + waitpid(pid_98,& process_status_98,0); + signal_eval(process_status_98,0,__gen_e_acsl_literal_string_172); + __e_acsl_delete_block((void *)(& process_status_98)); + } + __e_acsl_delete_block((void *)(& pid_98)); + } + { + pid_t pid_99 = fork(); + __e_acsl_store_block((void *)(& pid_99),(size_t)4); + __e_acsl_full_init((void *)(& pid_99)); + if (! pid_99) { + __e_acsl_builtin_printf("d",__gen_e_acsl_literal_string_173,(int)shrt); + __gen_e_acsl_exit(0); + } + else { + int process_status_99; + __e_acsl_store_block((void *)(& process_status_99),(size_t)4); + waitpid(pid_99,& process_status_99,0); + signal_eval(process_status_99,0,__gen_e_acsl_literal_string_174); + __e_acsl_delete_block((void *)(& process_status_99)); + } + __e_acsl_delete_block((void *)(& pid_99)); + } + { + pid_t pid_100 = fork(); + __e_acsl_store_block((void *)(& pid_100),(size_t)4); + __e_acsl_full_init((void *)(& pid_100)); + if (! pid_100) { + __e_acsl_builtin_printf("d",__gen_e_acsl_literal_string_175,(int)shrt); + __gen_e_acsl_exit(0); + } + else { + int process_status_100; + __e_acsl_store_block((void *)(& process_status_100),(size_t)4); + waitpid(pid_100,& process_status_100,0); + signal_eval(process_status_100,0,__gen_e_acsl_literal_string_174); + __e_acsl_delete_block((void *)(& process_status_100)); + } + __e_acsl_delete_block((void *)(& pid_100)); + } + { + pid_t pid_101 = fork(); + __e_acsl_store_block((void *)(& pid_101),(size_t)4); + __e_acsl_full_init((void *)(& pid_101)); + if (! pid_101) { + __e_acsl_builtin_printf("d",__gen_e_acsl_literal_string_176,(int)chr); + __gen_e_acsl_exit(0); + } + else { + int process_status_101; + __e_acsl_store_block((void *)(& process_status_101),(size_t)4); + waitpid(pid_101,& process_status_101,0); + signal_eval(process_status_101,0,__gen_e_acsl_literal_string_177); + __e_acsl_delete_block((void *)(& process_status_101)); + } + __e_acsl_delete_block((void *)(& pid_101)); + } + { + pid_t pid_102 = fork(); + __e_acsl_store_block((void *)(& pid_102),(size_t)4); + __e_acsl_full_init((void *)(& pid_102)); + if (! pid_102) { + __e_acsl_builtin_printf("d",__gen_e_acsl_literal_string_178,(int)chr); + __gen_e_acsl_exit(0); + } + else { + int process_status_102; + __e_acsl_store_block((void *)(& process_status_102),(size_t)4); + waitpid(pid_102,& process_status_102,0); + signal_eval(process_status_102,0,__gen_e_acsl_literal_string_177); + __e_acsl_delete_block((void *)(& process_status_102)); + } + __e_acsl_delete_block((void *)(& pid_102)); + } + { + pid_t pid_103 = fork(); + __e_acsl_store_block((void *)(& pid_103),(size_t)4); + __e_acsl_full_init((void *)(& pid_103)); + if (! pid_103) { + __e_acsl_builtin_printf("l",__gen_e_acsl_literal_string_179,li); + __gen_e_acsl_exit(0); + } + else { + int process_status_103; + __e_acsl_store_block((void *)(& process_status_103),(size_t)4); + waitpid(pid_103,& process_status_103,0); + signal_eval(process_status_103,0,__gen_e_acsl_literal_string_180); + __e_acsl_delete_block((void *)(& process_status_103)); + } + __e_acsl_delete_block((void *)(& pid_103)); + } + { + pid_t pid_104 = fork(); + __e_acsl_store_block((void *)(& pid_104),(size_t)4); + __e_acsl_full_init((void *)(& pid_104)); + if (! pid_104) { + __e_acsl_builtin_printf("l",__gen_e_acsl_literal_string_181,li); + __gen_e_acsl_exit(0); + } + else { + int process_status_104; + __e_acsl_store_block((void *)(& process_status_104),(size_t)4); + waitpid(pid_104,& process_status_104,0); + signal_eval(process_status_104,0,__gen_e_acsl_literal_string_180); + __e_acsl_delete_block((void *)(& process_status_104)); + } + __e_acsl_delete_block((void *)(& pid_104)); + } + { + pid_t pid_105 = fork(); + __e_acsl_store_block((void *)(& pid_105),(size_t)4); + __e_acsl_full_init((void *)(& pid_105)); + if (! pid_105) { + __e_acsl_builtin_printf("l",__gen_e_acsl_literal_string_182,ptrdf); + __gen_e_acsl_exit(0); + } + else { + int process_status_105; + __e_acsl_store_block((void *)(& process_status_105),(size_t)4); + waitpid(pid_105,& process_status_105,0); + signal_eval(process_status_105,0,__gen_e_acsl_literal_string_183); + __e_acsl_delete_block((void *)(& process_status_105)); + } + __e_acsl_delete_block((void *)(& pid_105)); + } + { + pid_t pid_106 = fork(); + __e_acsl_store_block((void *)(& pid_106),(size_t)4); + __e_acsl_full_init((void *)(& pid_106)); + if (! pid_106) { + __e_acsl_builtin_printf("l",__gen_e_acsl_literal_string_184,ptrdf); + __gen_e_acsl_exit(0); + } + else { + int process_status_106; + __e_acsl_store_block((void *)(& process_status_106),(size_t)4); + waitpid(pid_106,& process_status_106,0); + signal_eval(process_status_106,0,__gen_e_acsl_literal_string_183); + __e_acsl_delete_block((void *)(& process_status_106)); + } + __e_acsl_delete_block((void *)(& pid_106)); + } + { + pid_t pid_107 = fork(); + __e_acsl_store_block((void *)(& pid_107),(size_t)4); + __e_acsl_full_init((void *)(& pid_107)); + if (! pid_107) { + __e_acsl_builtin_printf("D",__gen_e_acsl_literal_string_185,ui); + __gen_e_acsl_exit(0); + } + else { + int process_status_107; + __e_acsl_store_block((void *)(& process_status_107),(size_t)4); + waitpid(pid_107,& process_status_107,0); + signal_eval(process_status_107,0,__gen_e_acsl_literal_string_186); + __e_acsl_delete_block((void *)(& process_status_107)); + } + __e_acsl_delete_block((void *)(& pid_107)); + } + { + pid_t pid_108 = fork(); + __e_acsl_store_block((void *)(& pid_108),(size_t)4); + __e_acsl_full_init((void *)(& pid_108)); + if (! pid_108) { + __e_acsl_builtin_printf("D",__gen_e_acsl_literal_string_187,ui); + __gen_e_acsl_exit(0); + } + else { + int process_status_108; + __e_acsl_store_block((void *)(& process_status_108),(size_t)4); + waitpid(pid_108,& process_status_108,0); + signal_eval(process_status_108,0,__gen_e_acsl_literal_string_186); + __e_acsl_delete_block((void *)(& process_status_108)); + } + __e_acsl_delete_block((void *)(& pid_108)); + } + { + pid_t pid_109 = fork(); + __e_acsl_store_block((void *)(& pid_109),(size_t)4); + __e_acsl_full_init((void *)(& pid_109)); + if (! pid_109) { + __e_acsl_builtin_printf("D",__gen_e_acsl_literal_string_188,ui); + __gen_e_acsl_exit(0); + } + else { + int process_status_109; + __e_acsl_store_block((void *)(& process_status_109),(size_t)4); + waitpid(pid_109,& process_status_109,0); + signal_eval(process_status_109,0,__gen_e_acsl_literal_string_186); + __e_acsl_delete_block((void *)(& process_status_109)); + } + __e_acsl_delete_block((void *)(& pid_109)); + } + { + pid_t pid_110 = fork(); + __e_acsl_store_block((void *)(& pid_110),(size_t)4); + __e_acsl_full_init((void *)(& pid_110)); + if (! pid_110) { + __e_acsl_builtin_printf("D",__gen_e_acsl_literal_string_189,ui); + __gen_e_acsl_exit(0); + } + else { + int process_status_110; + __e_acsl_store_block((void *)(& process_status_110),(size_t)4); + waitpid(pid_110,& process_status_110,0); + signal_eval(process_status_110,0,__gen_e_acsl_literal_string_186); + __e_acsl_delete_block((void *)(& process_status_110)); + } + __e_acsl_delete_block((void *)(& pid_110)); + } + { + pid_t pid_111 = fork(); + __e_acsl_store_block((void *)(& pid_111),(size_t)4); + __e_acsl_full_init((void *)(& pid_111)); + if (! pid_111) { + __e_acsl_builtin_printf("l",__gen_e_acsl_literal_string_185,li); + __gen_e_acsl_exit(0); + } + else { + int process_status_111; + __e_acsl_store_block((void *)(& process_status_111),(size_t)4); + waitpid(pid_111,& process_status_111,0); + signal_eval(process_status_111,1,__gen_e_acsl_literal_string_190); + __e_acsl_delete_block((void *)(& process_status_111)); + } + __e_acsl_delete_block((void *)(& pid_111)); + } + { + pid_t pid_112 = fork(); + __e_acsl_store_block((void *)(& pid_112),(size_t)4); + __e_acsl_full_init((void *)(& pid_112)); + if (! pid_112) { + __e_acsl_builtin_printf("l",__gen_e_acsl_literal_string_187,li); + __gen_e_acsl_exit(0); + } + else { + int process_status_112; + __e_acsl_store_block((void *)(& process_status_112),(size_t)4); + waitpid(pid_112,& process_status_112,0); + signal_eval(process_status_112,1,__gen_e_acsl_literal_string_190); + __e_acsl_delete_block((void *)(& process_status_112)); + } + __e_acsl_delete_block((void *)(& pid_112)); + } + { + pid_t pid_113 = fork(); + __e_acsl_store_block((void *)(& pid_113),(size_t)4); + __e_acsl_full_init((void *)(& pid_113)); + if (! pid_113) { + __e_acsl_builtin_printf("l",__gen_e_acsl_literal_string_188,li); + __gen_e_acsl_exit(0); + } + else { + int process_status_113; + __e_acsl_store_block((void *)(& process_status_113),(size_t)4); + waitpid(pid_113,& process_status_113,0); + signal_eval(process_status_113,1,__gen_e_acsl_literal_string_190); + __e_acsl_delete_block((void *)(& process_status_113)); + } + __e_acsl_delete_block((void *)(& pid_113)); + } + { + pid_t pid_114 = fork(); + __e_acsl_store_block((void *)(& pid_114),(size_t)4); + __e_acsl_full_init((void *)(& pid_114)); + if (! pid_114) { + __e_acsl_builtin_printf("l",__gen_e_acsl_literal_string_189,li); + __gen_e_acsl_exit(0); + } + else { + int process_status_114; + __e_acsl_store_block((void *)(& process_status_114),(size_t)4); + waitpid(pid_114,& process_status_114,0); + signal_eval(process_status_114,1,__gen_e_acsl_literal_string_190); + __e_acsl_delete_block((void *)(& process_status_114)); + } + __e_acsl_delete_block((void *)(& pid_114)); + } + { + pid_t pid_115 = fork(); + __e_acsl_store_block((void *)(& pid_115),(size_t)4); + __e_acsl_full_init((void *)(& pid_115)); + if (! pid_115) { + __e_acsl_builtin_printf("L",__gen_e_acsl_literal_string_185,lu); + __gen_e_acsl_exit(0); + } + else { + int process_status_115; + __e_acsl_store_block((void *)(& process_status_115),(size_t)4); + waitpid(pid_115,& process_status_115,0); + signal_eval(process_status_115,1,__gen_e_acsl_literal_string_191); + __e_acsl_delete_block((void *)(& process_status_115)); + } + __e_acsl_delete_block((void *)(& pid_115)); + } + { + pid_t pid_116 = fork(); + __e_acsl_store_block((void *)(& pid_116),(size_t)4); + __e_acsl_full_init((void *)(& pid_116)); + if (! pid_116) { + __e_acsl_builtin_printf("L",__gen_e_acsl_literal_string_187,lu); + __gen_e_acsl_exit(0); + } + else { + int process_status_116; + __e_acsl_store_block((void *)(& process_status_116),(size_t)4); + waitpid(pid_116,& process_status_116,0); + signal_eval(process_status_116,1,__gen_e_acsl_literal_string_191); + __e_acsl_delete_block((void *)(& process_status_116)); + } + __e_acsl_delete_block((void *)(& pid_116)); + } + { + pid_t pid_117 = fork(); + __e_acsl_store_block((void *)(& pid_117),(size_t)4); + __e_acsl_full_init((void *)(& pid_117)); + if (! pid_117) { + __e_acsl_builtin_printf("L",__gen_e_acsl_literal_string_188,lu); + __gen_e_acsl_exit(0); + } + else { + int process_status_117; + __e_acsl_store_block((void *)(& process_status_117),(size_t)4); + waitpid(pid_117,& process_status_117,0); + signal_eval(process_status_117,1,__gen_e_acsl_literal_string_191); + __e_acsl_delete_block((void *)(& process_status_117)); + } + __e_acsl_delete_block((void *)(& pid_117)); + } + { + pid_t pid_118 = fork(); + __e_acsl_store_block((void *)(& pid_118),(size_t)4); + __e_acsl_full_init((void *)(& pid_118)); + if (! pid_118) { + __e_acsl_builtin_printf("L",__gen_e_acsl_literal_string_189,lu); + __gen_e_acsl_exit(0); + } + else { + int process_status_118; + __e_acsl_store_block((void *)(& process_status_118),(size_t)4); + waitpid(pid_118,& process_status_118,0); + signal_eval(process_status_118,1,__gen_e_acsl_literal_string_191); + __e_acsl_delete_block((void *)(& process_status_118)); + } + __e_acsl_delete_block((void *)(& pid_118)); + } + { + pid_t pid_119 = fork(); + __e_acsl_store_block((void *)(& pid_119),(size_t)4); + __e_acsl_full_init((void *)(& pid_119)); + if (! pid_119) { + __e_acsl_builtin_printf("e",__gen_e_acsl_literal_string_185, + (double)flt); + __gen_e_acsl_exit(0); + } + else { + int process_status_119; + __e_acsl_store_block((void *)(& process_status_119),(size_t)4); + waitpid(pid_119,& process_status_119,0); + signal_eval(process_status_119,1,__gen_e_acsl_literal_string_192); + __e_acsl_delete_block((void *)(& process_status_119)); + } + __e_acsl_delete_block((void *)(& pid_119)); + } + { + pid_t pid_120 = fork(); + __e_acsl_store_block((void *)(& pid_120),(size_t)4); + __e_acsl_full_init((void *)(& pid_120)); + if (! pid_120) { + __e_acsl_builtin_printf("e",__gen_e_acsl_literal_string_187, + (double)flt); + __gen_e_acsl_exit(0); + } + else { + int process_status_120; + __e_acsl_store_block((void *)(& process_status_120),(size_t)4); + waitpid(pid_120,& process_status_120,0); + signal_eval(process_status_120,1,__gen_e_acsl_literal_string_192); + __e_acsl_delete_block((void *)(& process_status_120)); + } + __e_acsl_delete_block((void *)(& pid_120)); + } + { + pid_t pid_121 = fork(); + __e_acsl_store_block((void *)(& pid_121),(size_t)4); + __e_acsl_full_init((void *)(& pid_121)); + if (! pid_121) { + __e_acsl_builtin_printf("e",__gen_e_acsl_literal_string_188, + (double)flt); + __gen_e_acsl_exit(0); + } + else { + int process_status_121; + __e_acsl_store_block((void *)(& process_status_121),(size_t)4); + waitpid(pid_121,& process_status_121,0); + signal_eval(process_status_121,1,__gen_e_acsl_literal_string_192); + __e_acsl_delete_block((void *)(& process_status_121)); + } + __e_acsl_delete_block((void *)(& pid_121)); + } + { + pid_t pid_122 = fork(); + __e_acsl_store_block((void *)(& pid_122),(size_t)4); + __e_acsl_full_init((void *)(& pid_122)); + if (! pid_122) { + __e_acsl_builtin_printf("e",__gen_e_acsl_literal_string_189, + (double)flt); + __gen_e_acsl_exit(0); + } + else { + int process_status_122; + __e_acsl_store_block((void *)(& process_status_122),(size_t)4); + waitpid(pid_122,& process_status_122,0); + signal_eval(process_status_122,1,__gen_e_acsl_literal_string_192); + __e_acsl_delete_block((void *)(& process_status_122)); + } + __e_acsl_delete_block((void *)(& pid_122)); + } + { + pid_t pid_123 = fork(); + __e_acsl_store_block((void *)(& pid_123),(size_t)4); + __e_acsl_full_init((void *)(& pid_123)); + if (! pid_123) { + __e_acsl_builtin_printf("p",__gen_e_acsl_literal_string_185,vptr); + __gen_e_acsl_exit(0); + } + else { + int process_status_123; + __e_acsl_store_block((void *)(& process_status_123),(size_t)4); + waitpid(pid_123,& process_status_123,0); + signal_eval(process_status_123,1,__gen_e_acsl_literal_string_193); + __e_acsl_delete_block((void *)(& process_status_123)); + } + __e_acsl_delete_block((void *)(& pid_123)); + } + { + pid_t pid_124 = fork(); + __e_acsl_store_block((void *)(& pid_124),(size_t)4); + __e_acsl_full_init((void *)(& pid_124)); + if (! pid_124) { + __e_acsl_builtin_printf("p",__gen_e_acsl_literal_string_187,vptr); + __gen_e_acsl_exit(0); + } + else { + int process_status_124; + __e_acsl_store_block((void *)(& process_status_124),(size_t)4); + waitpid(pid_124,& process_status_124,0); + signal_eval(process_status_124,1,__gen_e_acsl_literal_string_193); + __e_acsl_delete_block((void *)(& process_status_124)); + } + __e_acsl_delete_block((void *)(& pid_124)); + } + { + pid_t pid_125 = fork(); + __e_acsl_store_block((void *)(& pid_125),(size_t)4); + __e_acsl_full_init((void *)(& pid_125)); + if (! pid_125) { + __e_acsl_builtin_printf("p",__gen_e_acsl_literal_string_188,vptr); + __gen_e_acsl_exit(0); + } + else { + int process_status_125; + __e_acsl_store_block((void *)(& process_status_125),(size_t)4); + waitpid(pid_125,& process_status_125,0); + signal_eval(process_status_125,1,__gen_e_acsl_literal_string_193); + __e_acsl_delete_block((void *)(& process_status_125)); + } + __e_acsl_delete_block((void *)(& pid_125)); + } + { + pid_t pid_126 = fork(); + __e_acsl_store_block((void *)(& pid_126),(size_t)4); + __e_acsl_full_init((void *)(& pid_126)); + if (! pid_126) { + __e_acsl_builtin_printf("p",__gen_e_acsl_literal_string_189,vptr); + __gen_e_acsl_exit(0); + } + else { + int process_status_126; + __e_acsl_store_block((void *)(& process_status_126),(size_t)4); + waitpid(pid_126,& process_status_126,0); + signal_eval(process_status_126,1,__gen_e_acsl_literal_string_193); + __e_acsl_delete_block((void *)(& process_status_126)); + } + __e_acsl_delete_block((void *)(& pid_126)); + } + { + pid_t pid_127 = fork(); + __e_acsl_store_block((void *)(& pid_127),(size_t)4); + __e_acsl_full_init((void *)(& pid_127)); + if (! pid_127) { + __e_acsl_builtin_printf("s",__gen_e_acsl_literal_string_185,astr); + __gen_e_acsl_exit(0); + } + else { + int process_status_127; + __e_acsl_store_block((void *)(& process_status_127),(size_t)4); + waitpid(pid_127,& process_status_127,0); + signal_eval(process_status_127,1,__gen_e_acsl_literal_string_194); + __e_acsl_delete_block((void *)(& process_status_127)); + } + __e_acsl_delete_block((void *)(& pid_127)); + } + { + pid_t pid_128 = fork(); + __e_acsl_store_block((void *)(& pid_128),(size_t)4); + __e_acsl_full_init((void *)(& pid_128)); + if (! pid_128) { + __e_acsl_builtin_printf("s",__gen_e_acsl_literal_string_187,astr); + __gen_e_acsl_exit(0); + } + else { + int process_status_128; + __e_acsl_store_block((void *)(& process_status_128),(size_t)4); + waitpid(pid_128,& process_status_128,0); + signal_eval(process_status_128,1,__gen_e_acsl_literal_string_194); + __e_acsl_delete_block((void *)(& process_status_128)); + } + __e_acsl_delete_block((void *)(& pid_128)); + } + { + pid_t pid_129 = fork(); + __e_acsl_store_block((void *)(& pid_129),(size_t)4); + __e_acsl_full_init((void *)(& pid_129)); + if (! pid_129) { + __e_acsl_builtin_printf("s",__gen_e_acsl_literal_string_188,astr); + __gen_e_acsl_exit(0); + } + else { + int process_status_129; + __e_acsl_store_block((void *)(& process_status_129),(size_t)4); + waitpid(pid_129,& process_status_129,0); + signal_eval(process_status_129,1,__gen_e_acsl_literal_string_194); + __e_acsl_delete_block((void *)(& process_status_129)); + } + __e_acsl_delete_block((void *)(& pid_129)); + } + { + pid_t pid_130 = fork(); + __e_acsl_store_block((void *)(& pid_130),(size_t)4); + __e_acsl_full_init((void *)(& pid_130)); + if (! pid_130) { + __e_acsl_builtin_printf("s",__gen_e_acsl_literal_string_189,astr); + __gen_e_acsl_exit(0); + } + else { + int process_status_130; + __e_acsl_store_block((void *)(& process_status_130),(size_t)4); + waitpid(pid_130,& process_status_130,0); + signal_eval(process_status_130,1,__gen_e_acsl_literal_string_194); + __e_acsl_delete_block((void *)(& process_status_130)); + } + __e_acsl_delete_block((void *)(& pid_130)); + } + { + pid_t pid_131 = fork(); + __e_acsl_store_block((void *)(& pid_131),(size_t)4); + __e_acsl_full_init((void *)(& pid_131)); + if (! pid_131) { + __e_acsl_builtin_printf("L",__gen_e_acsl_literal_string_195,lu); + __gen_e_acsl_exit(0); + } + else { + int process_status_131; + __e_acsl_store_block((void *)(& process_status_131),(size_t)4); + waitpid(pid_131,& process_status_131,0); + signal_eval(process_status_131,0,__gen_e_acsl_literal_string_196); + __e_acsl_delete_block((void *)(& process_status_131)); + } + __e_acsl_delete_block((void *)(& pid_131)); + } + { + pid_t pid_132 = fork(); + __e_acsl_store_block((void *)(& pid_132),(size_t)4); + __e_acsl_full_init((void *)(& pid_132)); + if (! pid_132) { + __e_acsl_builtin_printf("L",__gen_e_acsl_literal_string_197,lu); + __gen_e_acsl_exit(0); + } + else { + int process_status_132; + __e_acsl_store_block((void *)(& process_status_132),(size_t)4); + waitpid(pid_132,& process_status_132,0); + signal_eval(process_status_132,0,__gen_e_acsl_literal_string_196); + __e_acsl_delete_block((void *)(& process_status_132)); + } + __e_acsl_delete_block((void *)(& pid_132)); + } + { + pid_t pid_133 = fork(); + __e_acsl_store_block((void *)(& pid_133),(size_t)4); + __e_acsl_full_init((void *)(& pid_133)); + if (! pid_133) { + __e_acsl_builtin_printf("L",__gen_e_acsl_literal_string_198,lu); + __gen_e_acsl_exit(0); + } + else { + int process_status_133; + __e_acsl_store_block((void *)(& process_status_133),(size_t)4); + waitpid(pid_133,& process_status_133,0); + signal_eval(process_status_133,0,__gen_e_acsl_literal_string_196); + __e_acsl_delete_block((void *)(& process_status_133)); + } + __e_acsl_delete_block((void *)(& pid_133)); + } + { + pid_t pid_134 = fork(); + __e_acsl_store_block((void *)(& pid_134),(size_t)4); + __e_acsl_full_init((void *)(& pid_134)); + if (! pid_134) { + __e_acsl_builtin_printf("L",__gen_e_acsl_literal_string_199,lu); + __gen_e_acsl_exit(0); + } + else { + int process_status_134; + __e_acsl_store_block((void *)(& process_status_134),(size_t)4); + waitpid(pid_134,& process_status_134,0); + signal_eval(process_status_134,0,__gen_e_acsl_literal_string_196); + __e_acsl_delete_block((void *)(& process_status_134)); + } + __e_acsl_delete_block((void *)(& pid_134)); + } + { + pid_t pid_135 = fork(); + __e_acsl_store_block((void *)(& pid_135),(size_t)4); + __e_acsl_full_init((void *)(& pid_135)); + if (! pid_135) { + __e_acsl_builtin_printf("R",__gen_e_acsl_literal_string_200,llu); + __gen_e_acsl_exit(0); + } + else { + int process_status_135; + __e_acsl_store_block((void *)(& process_status_135),(size_t)4); + waitpid(pid_135,& process_status_135,0); + signal_eval(process_status_135,0,__gen_e_acsl_literal_string_201); + __e_acsl_delete_block((void *)(& process_status_135)); + } + __e_acsl_delete_block((void *)(& pid_135)); + } + { + pid_t pid_136 = fork(); + __e_acsl_store_block((void *)(& pid_136),(size_t)4); + __e_acsl_full_init((void *)(& pid_136)); + if (! pid_136) { + __e_acsl_builtin_printf("R",__gen_e_acsl_literal_string_202,llu); + __gen_e_acsl_exit(0); + } + else { + int process_status_136; + __e_acsl_store_block((void *)(& process_status_136),(size_t)4); + waitpid(pid_136,& process_status_136,0); + signal_eval(process_status_136,0,__gen_e_acsl_literal_string_201); + __e_acsl_delete_block((void *)(& process_status_136)); + } + __e_acsl_delete_block((void *)(& pid_136)); + } + { + pid_t pid_137 = fork(); + __e_acsl_store_block((void *)(& pid_137),(size_t)4); + __e_acsl_full_init((void *)(& pid_137)); + if (! pid_137) { + __e_acsl_builtin_printf("R",__gen_e_acsl_literal_string_203,llu); + __gen_e_acsl_exit(0); + } + else { + int process_status_137; + __e_acsl_store_block((void *)(& process_status_137),(size_t)4); + waitpid(pid_137,& process_status_137,0); + signal_eval(process_status_137,0,__gen_e_acsl_literal_string_201); + __e_acsl_delete_block((void *)(& process_status_137)); + } + __e_acsl_delete_block((void *)(& pid_137)); + } + { + pid_t pid_138 = fork(); + __e_acsl_store_block((void *)(& pid_138),(size_t)4); + __e_acsl_full_init((void *)(& pid_138)); + if (! pid_138) { + __e_acsl_builtin_printf("R",__gen_e_acsl_literal_string_204,llu); + __gen_e_acsl_exit(0); + } + else { + int process_status_138; + __e_acsl_store_block((void *)(& process_status_138),(size_t)4); + waitpid(pid_138,& process_status_138,0); + signal_eval(process_status_138,0,__gen_e_acsl_literal_string_201); + __e_acsl_delete_block((void *)(& process_status_138)); + } + __e_acsl_delete_block((void *)(& pid_138)); + } + { + pid_t pid_139 = fork(); + __e_acsl_store_block((void *)(& pid_139),(size_t)4); + __e_acsl_full_init((void *)(& pid_139)); + if (! pid_139) { + __e_acsl_builtin_printf("d",__gen_e_acsl_literal_string_205,i); + __gen_e_acsl_exit(0); + } + else { + int process_status_139; + __e_acsl_store_block((void *)(& process_status_139),(size_t)4); + waitpid(pid_139,& process_status_139,0); + signal_eval(process_status_139,0,__gen_e_acsl_literal_string_206); + __e_acsl_delete_block((void *)(& process_status_139)); + } + __e_acsl_delete_block((void *)(& pid_139)); + } + { + pid_t pid_140 = fork(); + __e_acsl_store_block((void *)(& pid_140),(size_t)4); + __e_acsl_full_init((void *)(& pid_140)); + if (! pid_140) { + __e_acsl_builtin_printf("d",__gen_e_acsl_literal_string_207,i); + __gen_e_acsl_exit(0); + } + else { + int process_status_140; + __e_acsl_store_block((void *)(& process_status_140),(size_t)4); + waitpid(pid_140,& process_status_140,0); + signal_eval(process_status_140,0,__gen_e_acsl_literal_string_206); + __e_acsl_delete_block((void *)(& process_status_140)); + } + __e_acsl_delete_block((void *)(& pid_140)); + } + { + pid_t pid_141 = fork(); + __e_acsl_store_block((void *)(& pid_141),(size_t)4); + __e_acsl_full_init((void *)(& pid_141)); + if (! pid_141) { + __e_acsl_builtin_printf("d",__gen_e_acsl_literal_string_208,i); + __gen_e_acsl_exit(0); + } + else { + int process_status_141; + __e_acsl_store_block((void *)(& process_status_141),(size_t)4); + waitpid(pid_141,& process_status_141,0); + signal_eval(process_status_141,0,__gen_e_acsl_literal_string_206); + __e_acsl_delete_block((void *)(& process_status_141)); + } + __e_acsl_delete_block((void *)(& pid_141)); + } + { + pid_t pid_142 = fork(); + __e_acsl_store_block((void *)(& pid_142),(size_t)4); + __e_acsl_full_init((void *)(& pid_142)); + if (! pid_142) { + __e_acsl_builtin_printf("d",__gen_e_acsl_literal_string_209,i); + __gen_e_acsl_exit(0); + } + else { + int process_status_142; + __e_acsl_store_block((void *)(& process_status_142),(size_t)4); + waitpid(pid_142,& process_status_142,0); + signal_eval(process_status_142,0,__gen_e_acsl_literal_string_206); + __e_acsl_delete_block((void *)(& process_status_142)); + } + __e_acsl_delete_block((void *)(& pid_142)); + } + { + pid_t pid_143 = fork(); + __e_acsl_store_block((void *)(& pid_143),(size_t)4); + __e_acsl_full_init((void *)(& pid_143)); + if (! pid_143) { + __e_acsl_builtin_printf("d",__gen_e_acsl_literal_string_210,i); + __gen_e_acsl_exit(0); + } + else { + int process_status_143; + __e_acsl_store_block((void *)(& process_status_143),(size_t)4); + waitpid(pid_143,& process_status_143,0); + signal_eval(process_status_143,0,__gen_e_acsl_literal_string_211); + __e_acsl_delete_block((void *)(& process_status_143)); + } + __e_acsl_delete_block((void *)(& pid_143)); + } + { + pid_t pid_144 = fork(); + __e_acsl_store_block((void *)(& pid_144),(size_t)4); + __e_acsl_full_init((void *)(& pid_144)); + if (! pid_144) { + __e_acsl_builtin_printf("d",__gen_e_acsl_literal_string_212,i); + __gen_e_acsl_exit(0); + } + else { + int process_status_144; + __e_acsl_store_block((void *)(& process_status_144),(size_t)4); + waitpid(pid_144,& process_status_144,0); + signal_eval(process_status_144,0,__gen_e_acsl_literal_string_211); + __e_acsl_delete_block((void *)(& process_status_144)); + } + __e_acsl_delete_block((void *)(& pid_144)); + } + { + pid_t pid_145 = fork(); + __e_acsl_store_block((void *)(& pid_145),(size_t)4); + __e_acsl_full_init((void *)(& pid_145)); + if (! pid_145) { + __e_acsl_builtin_printf("d",__gen_e_acsl_literal_string_213,i); + __gen_e_acsl_exit(0); + } + else { + int process_status_145; + __e_acsl_store_block((void *)(& process_status_145),(size_t)4); + waitpid(pid_145,& process_status_145,0); + signal_eval(process_status_145,0,__gen_e_acsl_literal_string_211); + __e_acsl_delete_block((void *)(& process_status_145)); + } + __e_acsl_delete_block((void *)(& pid_145)); + } + { + pid_t pid_146 = fork(); + __e_acsl_store_block((void *)(& pid_146),(size_t)4); + __e_acsl_full_init((void *)(& pid_146)); + if (! pid_146) { + __e_acsl_builtin_printf("d",__gen_e_acsl_literal_string_214,i); + __gen_e_acsl_exit(0); + } + else { + int process_status_146; + __e_acsl_store_block((void *)(& process_status_146),(size_t)4); + waitpid(pid_146,& process_status_146,0); + signal_eval(process_status_146,0,__gen_e_acsl_literal_string_211); + __e_acsl_delete_block((void *)(& process_status_146)); + } + __e_acsl_delete_block((void *)(& pid_146)); + } + { + pid_t pid_147 = fork(); + __e_acsl_store_block((void *)(& pid_147),(size_t)4); + __e_acsl_full_init((void *)(& pid_147)); + if (! pid_147) { + __e_acsl_builtin_printf("R",__gen_e_acsl_literal_string_215,uimax); + __gen_e_acsl_exit(0); + } + else { + int process_status_147; + __e_acsl_store_block((void *)(& process_status_147),(size_t)4); + waitpid(pid_147,& process_status_147,0); + signal_eval(process_status_147,0,__gen_e_acsl_literal_string_216); + __e_acsl_delete_block((void *)(& process_status_147)); + } + __e_acsl_delete_block((void *)(& pid_147)); + } + { + pid_t pid_148 = fork(); + __e_acsl_store_block((void *)(& pid_148),(size_t)4); + __e_acsl_full_init((void *)(& pid_148)); + if (! pid_148) { + __e_acsl_builtin_printf("R",__gen_e_acsl_literal_string_217,uimax); + __gen_e_acsl_exit(0); + } + else { + int process_status_148; + __e_acsl_store_block((void *)(& process_status_148),(size_t)4); + waitpid(pid_148,& process_status_148,0); + signal_eval(process_status_148,0,__gen_e_acsl_literal_string_216); + __e_acsl_delete_block((void *)(& process_status_148)); + } + __e_acsl_delete_block((void *)(& pid_148)); + } + { + pid_t pid_149 = fork(); + __e_acsl_store_block((void *)(& pid_149),(size_t)4); + __e_acsl_full_init((void *)(& pid_149)); + if (! pid_149) { + __e_acsl_builtin_printf("R",__gen_e_acsl_literal_string_218,uimax); + __gen_e_acsl_exit(0); + } + else { + int process_status_149; + __e_acsl_store_block((void *)(& process_status_149),(size_t)4); + waitpid(pid_149,& process_status_149,0); + signal_eval(process_status_149,0,__gen_e_acsl_literal_string_216); + __e_acsl_delete_block((void *)(& process_status_149)); + } + __e_acsl_delete_block((void *)(& pid_149)); + } + { + pid_t pid_150 = fork(); + __e_acsl_store_block((void *)(& pid_150),(size_t)4); + __e_acsl_full_init((void *)(& pid_150)); + if (! pid_150) { + __e_acsl_builtin_printf("R",__gen_e_acsl_literal_string_219,uimax); + __gen_e_acsl_exit(0); + } + else { + int process_status_150; + __e_acsl_store_block((void *)(& process_status_150),(size_t)4); + waitpid(pid_150,& process_status_150,0); + signal_eval(process_status_150,0,__gen_e_acsl_literal_string_216); + __e_acsl_delete_block((void *)(& process_status_150)); + } + __e_acsl_delete_block((void *)(& pid_150)); + } + { + pid_t pid_151 = fork(); + __e_acsl_store_block((void *)(& pid_151),(size_t)4); + __e_acsl_full_init((void *)(& pid_151)); + if (! pid_151) { + __e_acsl_builtin_printf("L",__gen_e_acsl_literal_string_220,szt); + __gen_e_acsl_exit(0); + } + else { + int process_status_151; + __e_acsl_store_block((void *)(& process_status_151),(size_t)4); + waitpid(pid_151,& process_status_151,0); + signal_eval(process_status_151,0,__gen_e_acsl_literal_string_221); + __e_acsl_delete_block((void *)(& process_status_151)); + } + __e_acsl_delete_block((void *)(& pid_151)); + } + { + pid_t pid_152 = fork(); + __e_acsl_store_block((void *)(& pid_152),(size_t)4); + __e_acsl_full_init((void *)(& pid_152)); + if (! pid_152) { + __e_acsl_builtin_printf("L",__gen_e_acsl_literal_string_222,szt); + __gen_e_acsl_exit(0); + } + else { + int process_status_152; + __e_acsl_store_block((void *)(& process_status_152),(size_t)4); + waitpid(pid_152,& process_status_152,0); + signal_eval(process_status_152,0,__gen_e_acsl_literal_string_221); + __e_acsl_delete_block((void *)(& process_status_152)); + } + __e_acsl_delete_block((void *)(& pid_152)); + } + { + pid_t pid_153 = fork(); + __e_acsl_store_block((void *)(& pid_153),(size_t)4); + __e_acsl_full_init((void *)(& pid_153)); + if (! pid_153) { + __e_acsl_builtin_printf("L",__gen_e_acsl_literal_string_223,szt); + __gen_e_acsl_exit(0); + } + else { + int process_status_153; + __e_acsl_store_block((void *)(& process_status_153),(size_t)4); + waitpid(pid_153,& process_status_153,0); + signal_eval(process_status_153,0,__gen_e_acsl_literal_string_221); + __e_acsl_delete_block((void *)(& process_status_153)); + } + __e_acsl_delete_block((void *)(& pid_153)); + } + { + pid_t pid_154 = fork(); + __e_acsl_store_block((void *)(& pid_154),(size_t)4); + __e_acsl_full_init((void *)(& pid_154)); + if (! pid_154) { + __e_acsl_builtin_printf("L",__gen_e_acsl_literal_string_224,szt); + __gen_e_acsl_exit(0); + } + else { + int process_status_154; + __e_acsl_store_block((void *)(& process_status_154),(size_t)4); + waitpid(pid_154,& process_status_154,0); + signal_eval(process_status_154,0,__gen_e_acsl_literal_string_221); + __e_acsl_delete_block((void *)(& process_status_154)); + } + __e_acsl_delete_block((void *)(& pid_154)); + } + { + pid_t pid_155 = fork(); + __e_acsl_store_block((void *)(& pid_155),(size_t)4); + __e_acsl_full_init((void *)(& pid_155)); + if (! pid_155) { + __e_acsl_builtin_printf("L",__gen_e_acsl_literal_string_225,lu); + __gen_e_acsl_exit(0); + } + else { + int process_status_155; + __e_acsl_store_block((void *)(& process_status_155),(size_t)4); + waitpid(pid_155,& process_status_155,0); + signal_eval(process_status_155,0,__gen_e_acsl_literal_string_226); + __e_acsl_delete_block((void *)(& process_status_155)); + } + __e_acsl_delete_block((void *)(& pid_155)); + } + { + pid_t pid_156 = fork(); + __e_acsl_store_block((void *)(& pid_156),(size_t)4); + __e_acsl_full_init((void *)(& pid_156)); + if (! pid_156) { + __e_acsl_builtin_printf("L",__gen_e_acsl_literal_string_227,lu); + __gen_e_acsl_exit(0); + } + else { + int process_status_156; + __e_acsl_store_block((void *)(& process_status_156),(size_t)4); + waitpid(pid_156,& process_status_156,0); + signal_eval(process_status_156,0,__gen_e_acsl_literal_string_226); + __e_acsl_delete_block((void *)(& process_status_156)); + } + __e_acsl_delete_block((void *)(& pid_156)); + } + { + pid_t pid_157 = fork(); + __e_acsl_store_block((void *)(& pid_157),(size_t)4); + __e_acsl_full_init((void *)(& pid_157)); + if (! pid_157) { + __e_acsl_builtin_printf("L",__gen_e_acsl_literal_string_228,lu); + __gen_e_acsl_exit(0); + } + else { + int process_status_157; + __e_acsl_store_block((void *)(& process_status_157),(size_t)4); + waitpid(pid_157,& process_status_157,0); + signal_eval(process_status_157,0,__gen_e_acsl_literal_string_226); + __e_acsl_delete_block((void *)(& process_status_157)); + } + __e_acsl_delete_block((void *)(& pid_157)); + } + { + pid_t pid_158 = fork(); + __e_acsl_store_block((void *)(& pid_158),(size_t)4); + __e_acsl_full_init((void *)(& pid_158)); + if (! pid_158) { + __e_acsl_builtin_printf("L",__gen_e_acsl_literal_string_229,lu); + __gen_e_acsl_exit(0); + } + else { + int process_status_158; + __e_acsl_store_block((void *)(& process_status_158),(size_t)4); + waitpid(pid_158,& process_status_158,0); + signal_eval(process_status_158,0,__gen_e_acsl_literal_string_226); + __e_acsl_delete_block((void *)(& process_status_158)); + } + __e_acsl_delete_block((void *)(& pid_158)); + } + { + pid_t pid_159 = fork(); + __e_acsl_store_block((void *)(& pid_159),(size_t)4); + __e_acsl_full_init((void *)(& pid_159)); + if (! pid_159) { + __e_acsl_builtin_printf("e",__gen_e_acsl_literal_string_230,dbl); + __gen_e_acsl_exit(0); + } + else { + int process_status_159; + __e_acsl_store_block((void *)(& process_status_159),(size_t)4); + waitpid(pid_159,& process_status_159,0); + signal_eval(process_status_159,0,__gen_e_acsl_literal_string_231); + __e_acsl_delete_block((void *)(& process_status_159)); + } + __e_acsl_delete_block((void *)(& pid_159)); + } + { + pid_t pid_160 = fork(); + __e_acsl_store_block((void *)(& pid_160),(size_t)4); + __e_acsl_full_init((void *)(& pid_160)); + if (! pid_160) { + __e_acsl_builtin_printf("e",__gen_e_acsl_literal_string_232,dbl); + __gen_e_acsl_exit(0); + } + else { + int process_status_160; + __e_acsl_store_block((void *)(& process_status_160),(size_t)4); + waitpid(pid_160,& process_status_160,0); + signal_eval(process_status_160,0,__gen_e_acsl_literal_string_231); + __e_acsl_delete_block((void *)(& process_status_160)); + } + __e_acsl_delete_block((void *)(& pid_160)); + } + { + pid_t pid_161 = fork(); + __e_acsl_store_block((void *)(& pid_161),(size_t)4); + __e_acsl_full_init((void *)(& pid_161)); + if (! pid_161) { + __e_acsl_builtin_printf("E",__gen_e_acsl_literal_string_230,ldbl); + __gen_e_acsl_exit(0); + } + else { + int process_status_161; + __e_acsl_store_block((void *)(& process_status_161),(size_t)4); + waitpid(pid_161,& process_status_161,0); + signal_eval(process_status_161,1,__gen_e_acsl_literal_string_233); + __e_acsl_delete_block((void *)(& process_status_161)); + } + __e_acsl_delete_block((void *)(& pid_161)); + } + { + pid_t pid_162 = fork(); + __e_acsl_store_block((void *)(& pid_162),(size_t)4); + __e_acsl_full_init((void *)(& pid_162)); + if (! pid_162) { + __e_acsl_builtin_printf("E",__gen_e_acsl_literal_string_232,ldbl); + __gen_e_acsl_exit(0); + } + else { + int process_status_162; + __e_acsl_store_block((void *)(& process_status_162),(size_t)4); + waitpid(pid_162,& process_status_162,0); + signal_eval(process_status_162,1,__gen_e_acsl_literal_string_233); + __e_acsl_delete_block((void *)(& process_status_162)); + } + __e_acsl_delete_block((void *)(& pid_162)); + } + { + pid_t pid_163 = fork(); + __e_acsl_store_block((void *)(& pid_163),(size_t)4); + __e_acsl_full_init((void *)(& pid_163)); + if (! pid_163) { + __e_acsl_builtin_printf("d",__gen_e_acsl_literal_string_230,i); + __gen_e_acsl_exit(0); + } + else { + int process_status_163; + __e_acsl_store_block((void *)(& process_status_163),(size_t)4); + waitpid(pid_163,& process_status_163,0); + signal_eval(process_status_163,1,__gen_e_acsl_literal_string_234); + __e_acsl_delete_block((void *)(& process_status_163)); + } + __e_acsl_delete_block((void *)(& pid_163)); + } + { + pid_t pid_164 = fork(); + __e_acsl_store_block((void *)(& pid_164),(size_t)4); + __e_acsl_full_init((void *)(& pid_164)); + if (! pid_164) { + __e_acsl_builtin_printf("d",__gen_e_acsl_literal_string_232,i); + __gen_e_acsl_exit(0); + } + else { + int process_status_164; + __e_acsl_store_block((void *)(& process_status_164),(size_t)4); + waitpid(pid_164,& process_status_164,0); + signal_eval(process_status_164,1,__gen_e_acsl_literal_string_234); + __e_acsl_delete_block((void *)(& process_status_164)); + } + __e_acsl_delete_block((void *)(& pid_164)); + } + { + pid_t pid_165 = fork(); + __e_acsl_store_block((void *)(& pid_165),(size_t)4); + __e_acsl_full_init((void *)(& pid_165)); + if (! pid_165) { + __e_acsl_builtin_printf("L",__gen_e_acsl_literal_string_230,lu); + __gen_e_acsl_exit(0); + } + else { + int process_status_165; + __e_acsl_store_block((void *)(& process_status_165),(size_t)4); + waitpid(pid_165,& process_status_165,0); + signal_eval(process_status_165,1,__gen_e_acsl_literal_string_235); + __e_acsl_delete_block((void *)(& process_status_165)); + } + __e_acsl_delete_block((void *)(& pid_165)); + } + { + pid_t pid_166 = fork(); + __e_acsl_store_block((void *)(& pid_166),(size_t)4); + __e_acsl_full_init((void *)(& pid_166)); + if (! pid_166) { + __e_acsl_builtin_printf("L",__gen_e_acsl_literal_string_232,lu); + __gen_e_acsl_exit(0); + } + else { + int process_status_166; + __e_acsl_store_block((void *)(& process_status_166),(size_t)4); + waitpid(pid_166,& process_status_166,0); + signal_eval(process_status_166,1,__gen_e_acsl_literal_string_235); + __e_acsl_delete_block((void *)(& process_status_166)); + } + __e_acsl_delete_block((void *)(& pid_166)); + } + { + pid_t pid_167 = fork(); + __e_acsl_store_block((void *)(& pid_167),(size_t)4); + __e_acsl_full_init((void *)(& pid_167)); + if (! pid_167) { + __e_acsl_builtin_printf("e",__gen_e_acsl_literal_string_236,dbl); + __gen_e_acsl_exit(0); + } + else { + int process_status_167; + __e_acsl_store_block((void *)(& process_status_167),(size_t)4); + waitpid(pid_167,& process_status_167,0); + signal_eval(process_status_167,0,__gen_e_acsl_literal_string_237); + __e_acsl_delete_block((void *)(& process_status_167)); + } + __e_acsl_delete_block((void *)(& pid_167)); + } + { + pid_t pid_168 = fork(); + __e_acsl_store_block((void *)(& pid_168),(size_t)4); + __e_acsl_full_init((void *)(& pid_168)); + if (! pid_168) { + __e_acsl_builtin_printf("e",__gen_e_acsl_literal_string_238,dbl); + __gen_e_acsl_exit(0); + } + else { + int process_status_168; + __e_acsl_store_block((void *)(& process_status_168),(size_t)4); + waitpid(pid_168,& process_status_168,0); + signal_eval(process_status_168,0,__gen_e_acsl_literal_string_237); + __e_acsl_delete_block((void *)(& process_status_168)); + } + __e_acsl_delete_block((void *)(& pid_168)); + } + { + pid_t pid_169 = fork(); + __e_acsl_store_block((void *)(& pid_169),(size_t)4); + __e_acsl_full_init((void *)(& pid_169)); + if (! pid_169) { + __e_acsl_builtin_printf("E",__gen_e_acsl_literal_string_236,ldbl); + __gen_e_acsl_exit(0); + } + else { + int process_status_169; + __e_acsl_store_block((void *)(& process_status_169),(size_t)4); + waitpid(pid_169,& process_status_169,0); + signal_eval(process_status_169,1,__gen_e_acsl_literal_string_239); + __e_acsl_delete_block((void *)(& process_status_169)); + } + __e_acsl_delete_block((void *)(& pid_169)); + } + { + pid_t pid_170 = fork(); + __e_acsl_store_block((void *)(& pid_170),(size_t)4); + __e_acsl_full_init((void *)(& pid_170)); + if (! pid_170) { + __e_acsl_builtin_printf("E",__gen_e_acsl_literal_string_238,ldbl); + __gen_e_acsl_exit(0); + } + else { + int process_status_170; + __e_acsl_store_block((void *)(& process_status_170),(size_t)4); + waitpid(pid_170,& process_status_170,0); + signal_eval(process_status_170,1,__gen_e_acsl_literal_string_239); + __e_acsl_delete_block((void *)(& process_status_170)); + } + __e_acsl_delete_block((void *)(& pid_170)); + } + { + pid_t pid_171 = fork(); + __e_acsl_store_block((void *)(& pid_171),(size_t)4); + __e_acsl_full_init((void *)(& pid_171)); + if (! pid_171) { + __e_acsl_builtin_printf("d",__gen_e_acsl_literal_string_236,i); + __gen_e_acsl_exit(0); + } + else { + int process_status_171; + __e_acsl_store_block((void *)(& process_status_171),(size_t)4); + waitpid(pid_171,& process_status_171,0); + signal_eval(process_status_171,1,__gen_e_acsl_literal_string_240); + __e_acsl_delete_block((void *)(& process_status_171)); + } + __e_acsl_delete_block((void *)(& pid_171)); + } + { + pid_t pid_172 = fork(); + __e_acsl_store_block((void *)(& pid_172),(size_t)4); + __e_acsl_full_init((void *)(& pid_172)); + if (! pid_172) { + __e_acsl_builtin_printf("d",__gen_e_acsl_literal_string_238,i); + __gen_e_acsl_exit(0); + } + else { + int process_status_172; + __e_acsl_store_block((void *)(& process_status_172),(size_t)4); + waitpid(pid_172,& process_status_172,0); + signal_eval(process_status_172,1,__gen_e_acsl_literal_string_240); + __e_acsl_delete_block((void *)(& process_status_172)); + } + __e_acsl_delete_block((void *)(& pid_172)); + } + { + pid_t pid_173 = fork(); + __e_acsl_store_block((void *)(& pid_173),(size_t)4); + __e_acsl_full_init((void *)(& pid_173)); + if (! pid_173) { + __e_acsl_builtin_printf("L",__gen_e_acsl_literal_string_236,lu); + __gen_e_acsl_exit(0); + } + else { + int process_status_173; + __e_acsl_store_block((void *)(& process_status_173),(size_t)4); + waitpid(pid_173,& process_status_173,0); + signal_eval(process_status_173,1,__gen_e_acsl_literal_string_241); + __e_acsl_delete_block((void *)(& process_status_173)); + } + __e_acsl_delete_block((void *)(& pid_173)); + } + { + pid_t pid_174 = fork(); + __e_acsl_store_block((void *)(& pid_174),(size_t)4); + __e_acsl_full_init((void *)(& pid_174)); + if (! pid_174) { + __e_acsl_builtin_printf("L",__gen_e_acsl_literal_string_238,lu); + __gen_e_acsl_exit(0); + } + else { + int process_status_174; + __e_acsl_store_block((void *)(& process_status_174),(size_t)4); + waitpid(pid_174,& process_status_174,0); + signal_eval(process_status_174,1,__gen_e_acsl_literal_string_241); + __e_acsl_delete_block((void *)(& process_status_174)); + } + __e_acsl_delete_block((void *)(& pid_174)); + } + { + pid_t pid_175 = fork(); + __e_acsl_store_block((void *)(& pid_175),(size_t)4); + __e_acsl_full_init((void *)(& pid_175)); + if (! pid_175) { + __e_acsl_builtin_printf("e",__gen_e_acsl_literal_string_242,dbl); + __gen_e_acsl_exit(0); + } + else { + int process_status_175; + __e_acsl_store_block((void *)(& process_status_175),(size_t)4); + waitpid(pid_175,& process_status_175,0); + signal_eval(process_status_175,0,__gen_e_acsl_literal_string_243); + __e_acsl_delete_block((void *)(& process_status_175)); + } + __e_acsl_delete_block((void *)(& pid_175)); + } + { + pid_t pid_176 = fork(); + __e_acsl_store_block((void *)(& pid_176),(size_t)4); + __e_acsl_full_init((void *)(& pid_176)); + if (! pid_176) { + __e_acsl_builtin_printf("e",__gen_e_acsl_literal_string_244,dbl); + __gen_e_acsl_exit(0); + } + else { + int process_status_176; + __e_acsl_store_block((void *)(& process_status_176),(size_t)4); + waitpid(pid_176,& process_status_176,0); + signal_eval(process_status_176,0,__gen_e_acsl_literal_string_243); + __e_acsl_delete_block((void *)(& process_status_176)); + } + __e_acsl_delete_block((void *)(& pid_176)); + } + { + pid_t pid_177 = fork(); + __e_acsl_store_block((void *)(& pid_177),(size_t)4); + __e_acsl_full_init((void *)(& pid_177)); + if (! pid_177) { + __e_acsl_builtin_printf("E",__gen_e_acsl_literal_string_242,ldbl); + __gen_e_acsl_exit(0); + } + else { + int process_status_177; + __e_acsl_store_block((void *)(& process_status_177),(size_t)4); + waitpid(pid_177,& process_status_177,0); + signal_eval(process_status_177,1,__gen_e_acsl_literal_string_245); + __e_acsl_delete_block((void *)(& process_status_177)); + } + __e_acsl_delete_block((void *)(& pid_177)); + } + { + pid_t pid_178 = fork(); + __e_acsl_store_block((void *)(& pid_178),(size_t)4); + __e_acsl_full_init((void *)(& pid_178)); + if (! pid_178) { + __e_acsl_builtin_printf("E",__gen_e_acsl_literal_string_244,ldbl); + __gen_e_acsl_exit(0); + } + else { + int process_status_178; + __e_acsl_store_block((void *)(& process_status_178),(size_t)4); + waitpid(pid_178,& process_status_178,0); + signal_eval(process_status_178,1,__gen_e_acsl_literal_string_245); + __e_acsl_delete_block((void *)(& process_status_178)); + } + __e_acsl_delete_block((void *)(& pid_178)); + } + { + pid_t pid_179 = fork(); + __e_acsl_store_block((void *)(& pid_179),(size_t)4); + __e_acsl_full_init((void *)(& pid_179)); + if (! pid_179) { + __e_acsl_builtin_printf("d",__gen_e_acsl_literal_string_242,i); + __gen_e_acsl_exit(0); + } + else { + int process_status_179; + __e_acsl_store_block((void *)(& process_status_179),(size_t)4); + waitpid(pid_179,& process_status_179,0); + signal_eval(process_status_179,1,__gen_e_acsl_literal_string_246); + __e_acsl_delete_block((void *)(& process_status_179)); + } + __e_acsl_delete_block((void *)(& pid_179)); + } + { + pid_t pid_180 = fork(); + __e_acsl_store_block((void *)(& pid_180),(size_t)4); + __e_acsl_full_init((void *)(& pid_180)); + if (! pid_180) { + __e_acsl_builtin_printf("d",__gen_e_acsl_literal_string_244,i); + __gen_e_acsl_exit(0); + } + else { + int process_status_180; + __e_acsl_store_block((void *)(& process_status_180),(size_t)4); + waitpid(pid_180,& process_status_180,0); + signal_eval(process_status_180,1,__gen_e_acsl_literal_string_246); + __e_acsl_delete_block((void *)(& process_status_180)); + } + __e_acsl_delete_block((void *)(& pid_180)); + } + { + pid_t pid_181 = fork(); + __e_acsl_store_block((void *)(& pid_181),(size_t)4); + __e_acsl_full_init((void *)(& pid_181)); + if (! pid_181) { + __e_acsl_builtin_printf("L",__gen_e_acsl_literal_string_242,lu); + __gen_e_acsl_exit(0); + } + else { + int process_status_181; + __e_acsl_store_block((void *)(& process_status_181),(size_t)4); + waitpid(pid_181,& process_status_181,0); + signal_eval(process_status_181,1,__gen_e_acsl_literal_string_247); + __e_acsl_delete_block((void *)(& process_status_181)); + } + __e_acsl_delete_block((void *)(& pid_181)); + } + { + pid_t pid_182 = fork(); + __e_acsl_store_block((void *)(& pid_182),(size_t)4); + __e_acsl_full_init((void *)(& pid_182)); + if (! pid_182) { + __e_acsl_builtin_printf("L",__gen_e_acsl_literal_string_244,lu); + __gen_e_acsl_exit(0); + } + else { + int process_status_182; + __e_acsl_store_block((void *)(& process_status_182),(size_t)4); + waitpid(pid_182,& process_status_182,0); + signal_eval(process_status_182,1,__gen_e_acsl_literal_string_247); + __e_acsl_delete_block((void *)(& process_status_182)); + } + __e_acsl_delete_block((void *)(& pid_182)); + } + { + pid_t pid_183 = fork(); + __e_acsl_store_block((void *)(& pid_183),(size_t)4); + __e_acsl_full_init((void *)(& pid_183)); + if (! pid_183) { + __e_acsl_builtin_printf("e",__gen_e_acsl_literal_string_248,dbl); + __gen_e_acsl_exit(0); + } + else { + int process_status_183; + __e_acsl_store_block((void *)(& process_status_183),(size_t)4); + waitpid(pid_183,& process_status_183,0); + signal_eval(process_status_183,0,__gen_e_acsl_literal_string_249); + __e_acsl_delete_block((void *)(& process_status_183)); + } + __e_acsl_delete_block((void *)(& pid_183)); + } + { + pid_t pid_184 = fork(); + __e_acsl_store_block((void *)(& pid_184),(size_t)4); + __e_acsl_full_init((void *)(& pid_184)); + if (! pid_184) { + __e_acsl_builtin_printf("e",__gen_e_acsl_literal_string_250,dbl); + __gen_e_acsl_exit(0); + } + else { + int process_status_184; + __e_acsl_store_block((void *)(& process_status_184),(size_t)4); + waitpid(pid_184,& process_status_184,0); + signal_eval(process_status_184,0,__gen_e_acsl_literal_string_249); + __e_acsl_delete_block((void *)(& process_status_184)); + } + __e_acsl_delete_block((void *)(& pid_184)); + } + { + pid_t pid_185 = fork(); + __e_acsl_store_block((void *)(& pid_185),(size_t)4); + __e_acsl_full_init((void *)(& pid_185)); + if (! pid_185) { + __e_acsl_builtin_printf("E",__gen_e_acsl_literal_string_248,ldbl); + __gen_e_acsl_exit(0); + } + else { + int process_status_185; + __e_acsl_store_block((void *)(& process_status_185),(size_t)4); + waitpid(pid_185,& process_status_185,0); + signal_eval(process_status_185,1,__gen_e_acsl_literal_string_251); + __e_acsl_delete_block((void *)(& process_status_185)); + } + __e_acsl_delete_block((void *)(& pid_185)); + } + { + pid_t pid_186 = fork(); + __e_acsl_store_block((void *)(& pid_186),(size_t)4); + __e_acsl_full_init((void *)(& pid_186)); + if (! pid_186) { + __e_acsl_builtin_printf("E",__gen_e_acsl_literal_string_250,ldbl); + __gen_e_acsl_exit(0); + } + else { + int process_status_186; + __e_acsl_store_block((void *)(& process_status_186),(size_t)4); + waitpid(pid_186,& process_status_186,0); + signal_eval(process_status_186,1,__gen_e_acsl_literal_string_251); + __e_acsl_delete_block((void *)(& process_status_186)); + } + __e_acsl_delete_block((void *)(& pid_186)); + } + { + pid_t pid_187 = fork(); + __e_acsl_store_block((void *)(& pid_187),(size_t)4); + __e_acsl_full_init((void *)(& pid_187)); + if (! pid_187) { + __e_acsl_builtin_printf("d",__gen_e_acsl_literal_string_248,i); + __gen_e_acsl_exit(0); + } + else { + int process_status_187; + __e_acsl_store_block((void *)(& process_status_187),(size_t)4); + waitpid(pid_187,& process_status_187,0); + signal_eval(process_status_187,1,__gen_e_acsl_literal_string_252); + __e_acsl_delete_block((void *)(& process_status_187)); + } + __e_acsl_delete_block((void *)(& pid_187)); + } + { + pid_t pid_188 = fork(); + __e_acsl_store_block((void *)(& pid_188),(size_t)4); + __e_acsl_full_init((void *)(& pid_188)); + if (! pid_188) { + __e_acsl_builtin_printf("d",__gen_e_acsl_literal_string_250,i); + __gen_e_acsl_exit(0); + } + else { + int process_status_188; + __e_acsl_store_block((void *)(& process_status_188),(size_t)4); + waitpid(pid_188,& process_status_188,0); + signal_eval(process_status_188,1,__gen_e_acsl_literal_string_252); + __e_acsl_delete_block((void *)(& process_status_188)); + } + __e_acsl_delete_block((void *)(& pid_188)); + } + { + pid_t pid_189 = fork(); + __e_acsl_store_block((void *)(& pid_189),(size_t)4); + __e_acsl_full_init((void *)(& pid_189)); + if (! pid_189) { + __e_acsl_builtin_printf("L",__gen_e_acsl_literal_string_248,lu); + __gen_e_acsl_exit(0); + } + else { + int process_status_189; + __e_acsl_store_block((void *)(& process_status_189),(size_t)4); + waitpid(pid_189,& process_status_189,0); + signal_eval(process_status_189,1,__gen_e_acsl_literal_string_253); + __e_acsl_delete_block((void *)(& process_status_189)); + } + __e_acsl_delete_block((void *)(& pid_189)); + } + { + pid_t pid_190 = fork(); + __e_acsl_store_block((void *)(& pid_190),(size_t)4); + __e_acsl_full_init((void *)(& pid_190)); + if (! pid_190) { + __e_acsl_builtin_printf("L",__gen_e_acsl_literal_string_250,lu); + __gen_e_acsl_exit(0); + } + else { + int process_status_190; + __e_acsl_store_block((void *)(& process_status_190),(size_t)4); + waitpid(pid_190,& process_status_190,0); + signal_eval(process_status_190,1,__gen_e_acsl_literal_string_253); + __e_acsl_delete_block((void *)(& process_status_190)); + } + __e_acsl_delete_block((void *)(& pid_190)); + } + { + pid_t pid_191 = fork(); + __e_acsl_store_block((void *)(& pid_191),(size_t)4); + __e_acsl_full_init((void *)(& pid_191)); + if (! pid_191) { + __e_acsl_builtin_printf("e",__gen_e_acsl_literal_string_254,dbl); + __gen_e_acsl_exit(0); + } + else { + int process_status_191; + __e_acsl_store_block((void *)(& process_status_191),(size_t)4); + waitpid(pid_191,& process_status_191,0); + signal_eval(process_status_191,1,__gen_e_acsl_literal_string_255); + __e_acsl_delete_block((void *)(& process_status_191)); + } + __e_acsl_delete_block((void *)(& pid_191)); + } + { + pid_t pid_192 = fork(); + __e_acsl_store_block((void *)(& pid_192),(size_t)4); + __e_acsl_full_init((void *)(& pid_192)); + if (! pid_192) { + __e_acsl_builtin_printf("e",__gen_e_acsl_literal_string_256,dbl); + __gen_e_acsl_exit(0); + } + else { + int process_status_192; + __e_acsl_store_block((void *)(& process_status_192),(size_t)4); + waitpid(pid_192,& process_status_192,0); + signal_eval(process_status_192,1,__gen_e_acsl_literal_string_255); + __e_acsl_delete_block((void *)(& process_status_192)); + } + __e_acsl_delete_block((void *)(& pid_192)); + } + { + pid_t pid_193 = fork(); + __e_acsl_store_block((void *)(& pid_193),(size_t)4); + __e_acsl_full_init((void *)(& pid_193)); + if (! pid_193) { + __e_acsl_builtin_printf("E",__gen_e_acsl_literal_string_254,ldbl); + __gen_e_acsl_exit(0); + } + else { + int process_status_193; + __e_acsl_store_block((void *)(& process_status_193),(size_t)4); + waitpid(pid_193,& process_status_193,0); + signal_eval(process_status_193,0,__gen_e_acsl_literal_string_257); + __e_acsl_delete_block((void *)(& process_status_193)); + } + __e_acsl_delete_block((void *)(& pid_193)); + } + { + pid_t pid_194 = fork(); + __e_acsl_store_block((void *)(& pid_194),(size_t)4); + __e_acsl_full_init((void *)(& pid_194)); + if (! pid_194) { + __e_acsl_builtin_printf("E",__gen_e_acsl_literal_string_256,ldbl); + __gen_e_acsl_exit(0); + } + else { + int process_status_194; + __e_acsl_store_block((void *)(& process_status_194),(size_t)4); + waitpid(pid_194,& process_status_194,0); + signal_eval(process_status_194,0,__gen_e_acsl_literal_string_257); + __e_acsl_delete_block((void *)(& process_status_194)); + } + __e_acsl_delete_block((void *)(& pid_194)); + } + { + pid_t pid_195 = fork(); + __e_acsl_store_block((void *)(& pid_195),(size_t)4); + __e_acsl_full_init((void *)(& pid_195)); + if (! pid_195) { + __e_acsl_builtin_printf("d",__gen_e_acsl_literal_string_254,i); + __gen_e_acsl_exit(0); + } + else { + int process_status_195; + __e_acsl_store_block((void *)(& process_status_195),(size_t)4); + waitpid(pid_195,& process_status_195,0); + signal_eval(process_status_195,1,__gen_e_acsl_literal_string_258); + __e_acsl_delete_block((void *)(& process_status_195)); + } + __e_acsl_delete_block((void *)(& pid_195)); + } + { + pid_t pid_196 = fork(); + __e_acsl_store_block((void *)(& pid_196),(size_t)4); + __e_acsl_full_init((void *)(& pid_196)); + if (! pid_196) { + __e_acsl_builtin_printf("d",__gen_e_acsl_literal_string_256,i); + __gen_e_acsl_exit(0); + } + else { + int process_status_196; + __e_acsl_store_block((void *)(& process_status_196),(size_t)4); + waitpid(pid_196,& process_status_196,0); + signal_eval(process_status_196,1,__gen_e_acsl_literal_string_258); + __e_acsl_delete_block((void *)(& process_status_196)); + } + __e_acsl_delete_block((void *)(& pid_196)); + } + { + pid_t pid_197 = fork(); + __e_acsl_store_block((void *)(& pid_197),(size_t)4); + __e_acsl_full_init((void *)(& pid_197)); + if (! pid_197) { + __e_acsl_builtin_printf("L",__gen_e_acsl_literal_string_254,lu); + __gen_e_acsl_exit(0); + } + else { + int process_status_197; + __e_acsl_store_block((void *)(& process_status_197),(size_t)4); + waitpid(pid_197,& process_status_197,0); + signal_eval(process_status_197,1,__gen_e_acsl_literal_string_259); + __e_acsl_delete_block((void *)(& process_status_197)); + } + __e_acsl_delete_block((void *)(& pid_197)); + } + { + pid_t pid_198 = fork(); + __e_acsl_store_block((void *)(& pid_198),(size_t)4); + __e_acsl_full_init((void *)(& pid_198)); + if (! pid_198) { + __e_acsl_builtin_printf("L",__gen_e_acsl_literal_string_256,lu); + __gen_e_acsl_exit(0); + } + else { + int process_status_198; + __e_acsl_store_block((void *)(& process_status_198),(size_t)4); + waitpid(pid_198,& process_status_198,0); + signal_eval(process_status_198,1,__gen_e_acsl_literal_string_259); + __e_acsl_delete_block((void *)(& process_status_198)); + } + __e_acsl_delete_block((void *)(& pid_198)); + } + { + pid_t pid_199 = fork(); + __e_acsl_store_block((void *)(& pid_199),(size_t)4); + __e_acsl_full_init((void *)(& pid_199)); + if (! pid_199) { + __e_acsl_builtin_printf("e",__gen_e_acsl_literal_string_260,dbl); + __gen_e_acsl_exit(0); + } + else { + int process_status_199; + __e_acsl_store_block((void *)(& process_status_199),(size_t)4); + waitpid(pid_199,& process_status_199,0); + signal_eval(process_status_199,1,__gen_e_acsl_literal_string_261); + __e_acsl_delete_block((void *)(& process_status_199)); + } + __e_acsl_delete_block((void *)(& pid_199)); + } + { + pid_t pid_200 = fork(); + __e_acsl_store_block((void *)(& pid_200),(size_t)4); + __e_acsl_full_init((void *)(& pid_200)); + if (! pid_200) { + __e_acsl_builtin_printf("e",__gen_e_acsl_literal_string_262,dbl); + __gen_e_acsl_exit(0); + } + else { + int process_status_200; + __e_acsl_store_block((void *)(& process_status_200),(size_t)4); + waitpid(pid_200,& process_status_200,0); + signal_eval(process_status_200,1,__gen_e_acsl_literal_string_261); + __e_acsl_delete_block((void *)(& process_status_200)); + } + __e_acsl_delete_block((void *)(& pid_200)); + } + { + pid_t pid_201 = fork(); + __e_acsl_store_block((void *)(& pid_201),(size_t)4); + __e_acsl_full_init((void *)(& pid_201)); + if (! pid_201) { + __e_acsl_builtin_printf("E",__gen_e_acsl_literal_string_260,ldbl); + __gen_e_acsl_exit(0); + } + else { + int process_status_201; + __e_acsl_store_block((void *)(& process_status_201),(size_t)4); + waitpid(pid_201,& process_status_201,0); + signal_eval(process_status_201,0,__gen_e_acsl_literal_string_263); + __e_acsl_delete_block((void *)(& process_status_201)); + } + __e_acsl_delete_block((void *)(& pid_201)); + } + { + pid_t pid_202 = fork(); + __e_acsl_store_block((void *)(& pid_202),(size_t)4); + __e_acsl_full_init((void *)(& pid_202)); + if (! pid_202) { + __e_acsl_builtin_printf("E",__gen_e_acsl_literal_string_262,ldbl); + __gen_e_acsl_exit(0); + } + else { + int process_status_202; + __e_acsl_store_block((void *)(& process_status_202),(size_t)4); + waitpid(pid_202,& process_status_202,0); + signal_eval(process_status_202,0,__gen_e_acsl_literal_string_263); + __e_acsl_delete_block((void *)(& process_status_202)); + } + __e_acsl_delete_block((void *)(& pid_202)); + } + { + pid_t pid_203 = fork(); + __e_acsl_store_block((void *)(& pid_203),(size_t)4); + __e_acsl_full_init((void *)(& pid_203)); + if (! pid_203) { + __e_acsl_builtin_printf("d",__gen_e_acsl_literal_string_260,i); + __gen_e_acsl_exit(0); + } + else { + int process_status_203; + __e_acsl_store_block((void *)(& process_status_203),(size_t)4); + waitpid(pid_203,& process_status_203,0); + signal_eval(process_status_203,1,__gen_e_acsl_literal_string_264); + __e_acsl_delete_block((void *)(& process_status_203)); + } + __e_acsl_delete_block((void *)(& pid_203)); + } + { + pid_t pid_204 = fork(); + __e_acsl_store_block((void *)(& pid_204),(size_t)4); + __e_acsl_full_init((void *)(& pid_204)); + if (! pid_204) { + __e_acsl_builtin_printf("d",__gen_e_acsl_literal_string_262,i); + __gen_e_acsl_exit(0); + } + else { + int process_status_204; + __e_acsl_store_block((void *)(& process_status_204),(size_t)4); + waitpid(pid_204,& process_status_204,0); + signal_eval(process_status_204,1,__gen_e_acsl_literal_string_264); + __e_acsl_delete_block((void *)(& process_status_204)); + } + __e_acsl_delete_block((void *)(& pid_204)); + } + { + pid_t pid_205 = fork(); + __e_acsl_store_block((void *)(& pid_205),(size_t)4); + __e_acsl_full_init((void *)(& pid_205)); + if (! pid_205) { + __e_acsl_builtin_printf("L",__gen_e_acsl_literal_string_260,lu); + __gen_e_acsl_exit(0); + } + else { + int process_status_205; + __e_acsl_store_block((void *)(& process_status_205),(size_t)4); + waitpid(pid_205,& process_status_205,0); + signal_eval(process_status_205,1,__gen_e_acsl_literal_string_265); + __e_acsl_delete_block((void *)(& process_status_205)); + } + __e_acsl_delete_block((void *)(& pid_205)); + } + { + pid_t pid_206 = fork(); + __e_acsl_store_block((void *)(& pid_206),(size_t)4); + __e_acsl_full_init((void *)(& pid_206)); + if (! pid_206) { + __e_acsl_builtin_printf("L",__gen_e_acsl_literal_string_262,lu); + __gen_e_acsl_exit(0); + } + else { + int process_status_206; + __e_acsl_store_block((void *)(& process_status_206),(size_t)4); + waitpid(pid_206,& process_status_206,0); + signal_eval(process_status_206,1,__gen_e_acsl_literal_string_265); + __e_acsl_delete_block((void *)(& process_status_206)); + } + __e_acsl_delete_block((void *)(& pid_206)); + } + { + pid_t pid_207 = fork(); + __e_acsl_store_block((void *)(& pid_207),(size_t)4); + __e_acsl_full_init((void *)(& pid_207)); + if (! pid_207) { + __e_acsl_builtin_printf("e",__gen_e_acsl_literal_string_266,dbl); + __gen_e_acsl_exit(0); + } + else { + int process_status_207; + __e_acsl_store_block((void *)(& process_status_207),(size_t)4); + waitpid(pid_207,& process_status_207,0); + signal_eval(process_status_207,1,__gen_e_acsl_literal_string_267); + __e_acsl_delete_block((void *)(& process_status_207)); + } + __e_acsl_delete_block((void *)(& pid_207)); + } + { + pid_t pid_208 = fork(); + __e_acsl_store_block((void *)(& pid_208),(size_t)4); + __e_acsl_full_init((void *)(& pid_208)); + if (! pid_208) { + __e_acsl_builtin_printf("e",__gen_e_acsl_literal_string_268,dbl); + __gen_e_acsl_exit(0); + } + else { + int process_status_208; + __e_acsl_store_block((void *)(& process_status_208),(size_t)4); + waitpid(pid_208,& process_status_208,0); + signal_eval(process_status_208,1,__gen_e_acsl_literal_string_267); + __e_acsl_delete_block((void *)(& process_status_208)); + } + __e_acsl_delete_block((void *)(& pid_208)); + } + { + pid_t pid_209 = fork(); + __e_acsl_store_block((void *)(& pid_209),(size_t)4); + __e_acsl_full_init((void *)(& pid_209)); + if (! pid_209) { + __e_acsl_builtin_printf("E",__gen_e_acsl_literal_string_266,ldbl); + __gen_e_acsl_exit(0); + } + else { + int process_status_209; + __e_acsl_store_block((void *)(& process_status_209),(size_t)4); + waitpid(pid_209,& process_status_209,0); + signal_eval(process_status_209,0,__gen_e_acsl_literal_string_269); + __e_acsl_delete_block((void *)(& process_status_209)); + } + __e_acsl_delete_block((void *)(& pid_209)); + } + { + pid_t pid_210 = fork(); + __e_acsl_store_block((void *)(& pid_210),(size_t)4); + __e_acsl_full_init((void *)(& pid_210)); + if (! pid_210) { + __e_acsl_builtin_printf("E",__gen_e_acsl_literal_string_268,ldbl); + __gen_e_acsl_exit(0); + } + else { + int process_status_210; + __e_acsl_store_block((void *)(& process_status_210),(size_t)4); + waitpid(pid_210,& process_status_210,0); + signal_eval(process_status_210,0,__gen_e_acsl_literal_string_269); + __e_acsl_delete_block((void *)(& process_status_210)); + } + __e_acsl_delete_block((void *)(& pid_210)); + } + { + pid_t pid_211 = fork(); + __e_acsl_store_block((void *)(& pid_211),(size_t)4); + __e_acsl_full_init((void *)(& pid_211)); + if (! pid_211) { + __e_acsl_builtin_printf("d",__gen_e_acsl_literal_string_266,i); + __gen_e_acsl_exit(0); + } + else { + int process_status_211; + __e_acsl_store_block((void *)(& process_status_211),(size_t)4); + waitpid(pid_211,& process_status_211,0); + signal_eval(process_status_211,1,__gen_e_acsl_literal_string_270); + __e_acsl_delete_block((void *)(& process_status_211)); + } + __e_acsl_delete_block((void *)(& pid_211)); + } + { + pid_t pid_212 = fork(); + __e_acsl_store_block((void *)(& pid_212),(size_t)4); + __e_acsl_full_init((void *)(& pid_212)); + if (! pid_212) { + __e_acsl_builtin_printf("d",__gen_e_acsl_literal_string_268,i); + __gen_e_acsl_exit(0); + } + else { + int process_status_212; + __e_acsl_store_block((void *)(& process_status_212),(size_t)4); + waitpid(pid_212,& process_status_212,0); + signal_eval(process_status_212,1,__gen_e_acsl_literal_string_270); + __e_acsl_delete_block((void *)(& process_status_212)); + } + __e_acsl_delete_block((void *)(& pid_212)); + } + { + pid_t pid_213 = fork(); + __e_acsl_store_block((void *)(& pid_213),(size_t)4); + __e_acsl_full_init((void *)(& pid_213)); + if (! pid_213) { + __e_acsl_builtin_printf("L",__gen_e_acsl_literal_string_266,lu); + __gen_e_acsl_exit(0); + } + else { + int process_status_213; + __e_acsl_store_block((void *)(& process_status_213),(size_t)4); + waitpid(pid_213,& process_status_213,0); + signal_eval(process_status_213,1,__gen_e_acsl_literal_string_271); + __e_acsl_delete_block((void *)(& process_status_213)); + } + __e_acsl_delete_block((void *)(& pid_213)); + } + { + pid_t pid_214 = fork(); + __e_acsl_store_block((void *)(& pid_214),(size_t)4); + __e_acsl_full_init((void *)(& pid_214)); + if (! pid_214) { + __e_acsl_builtin_printf("L",__gen_e_acsl_literal_string_268,lu); + __gen_e_acsl_exit(0); + } + else { + int process_status_214; + __e_acsl_store_block((void *)(& process_status_214),(size_t)4); + waitpid(pid_214,& process_status_214,0); + signal_eval(process_status_214,1,__gen_e_acsl_literal_string_271); + __e_acsl_delete_block((void *)(& process_status_214)); + } + __e_acsl_delete_block((void *)(& pid_214)); + } + { + pid_t pid_215 = fork(); + __e_acsl_store_block((void *)(& pid_215),(size_t)4); + __e_acsl_full_init((void *)(& pid_215)); + if (! pid_215) { + __e_acsl_builtin_printf("e",__gen_e_acsl_literal_string_272,dbl); + __gen_e_acsl_exit(0); + } + else { + int process_status_215; + __e_acsl_store_block((void *)(& process_status_215),(size_t)4); + waitpid(pid_215,& process_status_215,0); + signal_eval(process_status_215,1,__gen_e_acsl_literal_string_273); + __e_acsl_delete_block((void *)(& process_status_215)); + } + __e_acsl_delete_block((void *)(& pid_215)); + } + { + pid_t pid_216 = fork(); + __e_acsl_store_block((void *)(& pid_216),(size_t)4); + __e_acsl_full_init((void *)(& pid_216)); + if (! pid_216) { + __e_acsl_builtin_printf("e",__gen_e_acsl_literal_string_274,dbl); + __gen_e_acsl_exit(0); + } + else { + int process_status_216; + __e_acsl_store_block((void *)(& process_status_216),(size_t)4); + waitpid(pid_216,& process_status_216,0); + signal_eval(process_status_216,1,__gen_e_acsl_literal_string_273); + __e_acsl_delete_block((void *)(& process_status_216)); + } + __e_acsl_delete_block((void *)(& pid_216)); + } + { + pid_t pid_217 = fork(); + __e_acsl_store_block((void *)(& pid_217),(size_t)4); + __e_acsl_full_init((void *)(& pid_217)); + if (! pid_217) { + __e_acsl_builtin_printf("E",__gen_e_acsl_literal_string_272,ldbl); + __gen_e_acsl_exit(0); + } + else { + int process_status_217; + __e_acsl_store_block((void *)(& process_status_217),(size_t)4); + waitpid(pid_217,& process_status_217,0); + signal_eval(process_status_217,0,__gen_e_acsl_literal_string_275); + __e_acsl_delete_block((void *)(& process_status_217)); + } + __e_acsl_delete_block((void *)(& pid_217)); + } + { + pid_t pid_218 = fork(); + __e_acsl_store_block((void *)(& pid_218),(size_t)4); + __e_acsl_full_init((void *)(& pid_218)); + if (! pid_218) { + __e_acsl_builtin_printf("E",__gen_e_acsl_literal_string_274,ldbl); + __gen_e_acsl_exit(0); + } + else { + int process_status_218; + __e_acsl_store_block((void *)(& process_status_218),(size_t)4); + waitpid(pid_218,& process_status_218,0); + signal_eval(process_status_218,0,__gen_e_acsl_literal_string_275); + __e_acsl_delete_block((void *)(& process_status_218)); + } + __e_acsl_delete_block((void *)(& pid_218)); + } + { + pid_t pid_219 = fork(); + __e_acsl_store_block((void *)(& pid_219),(size_t)4); + __e_acsl_full_init((void *)(& pid_219)); + if (! pid_219) { + __e_acsl_builtin_printf("d",__gen_e_acsl_literal_string_272,i); + __gen_e_acsl_exit(0); + } + else { + int process_status_219; + __e_acsl_store_block((void *)(& process_status_219),(size_t)4); + waitpid(pid_219,& process_status_219,0); + signal_eval(process_status_219,1,__gen_e_acsl_literal_string_276); + __e_acsl_delete_block((void *)(& process_status_219)); + } + __e_acsl_delete_block((void *)(& pid_219)); + } + { + pid_t pid_220 = fork(); + __e_acsl_store_block((void *)(& pid_220),(size_t)4); + __e_acsl_full_init((void *)(& pid_220)); + if (! pid_220) { + __e_acsl_builtin_printf("d",__gen_e_acsl_literal_string_274,i); + __gen_e_acsl_exit(0); + } + else { + int process_status_220; + __e_acsl_store_block((void *)(& process_status_220),(size_t)4); + waitpid(pid_220,& process_status_220,0); + signal_eval(process_status_220,1,__gen_e_acsl_literal_string_276); + __e_acsl_delete_block((void *)(& process_status_220)); + } + __e_acsl_delete_block((void *)(& pid_220)); + } + { + pid_t pid_221 = fork(); + __e_acsl_store_block((void *)(& pid_221),(size_t)4); + __e_acsl_full_init((void *)(& pid_221)); + if (! pid_221) { + __e_acsl_builtin_printf("L",__gen_e_acsl_literal_string_272,lu); + __gen_e_acsl_exit(0); + } + else { + int process_status_221; + __e_acsl_store_block((void *)(& process_status_221),(size_t)4); + waitpid(pid_221,& process_status_221,0); + signal_eval(process_status_221,1,__gen_e_acsl_literal_string_277); + __e_acsl_delete_block((void *)(& process_status_221)); + } + __e_acsl_delete_block((void *)(& pid_221)); + } + { + pid_t pid_222 = fork(); + __e_acsl_store_block((void *)(& pid_222),(size_t)4); + __e_acsl_full_init((void *)(& pid_222)); + if (! pid_222) { + __e_acsl_builtin_printf("L",__gen_e_acsl_literal_string_274,lu); + __gen_e_acsl_exit(0); + } + else { + int process_status_222; + __e_acsl_store_block((void *)(& process_status_222),(size_t)4); + waitpid(pid_222,& process_status_222,0); + signal_eval(process_status_222,1,__gen_e_acsl_literal_string_277); + __e_acsl_delete_block((void *)(& process_status_222)); + } + __e_acsl_delete_block((void *)(& pid_222)); + } + { + pid_t pid_223 = fork(); + __e_acsl_store_block((void *)(& pid_223),(size_t)4); + __e_acsl_full_init((void *)(& pid_223)); + if (! pid_223) { + __e_acsl_builtin_printf("d",__gen_e_acsl_literal_string_278,i); + __gen_e_acsl_exit(0); + } + else { + int process_status_223; + __e_acsl_store_block((void *)(& process_status_223),(size_t)4); + waitpid(pid_223,& process_status_223,0); + signal_eval(process_status_223,0,__gen_e_acsl_literal_string_279); + __e_acsl_delete_block((void *)(& process_status_223)); + } + __e_acsl_delete_block((void *)(& pid_223)); + } + { + pid_t pid_224 = fork(); + __e_acsl_store_block((void *)(& pid_224),(size_t)4); + __e_acsl_full_init((void *)(& pid_224)); + if (! pid_224) { + __e_acsl_builtin_printf("d",__gen_e_acsl_literal_string_278,(int)chr); + __gen_e_acsl_exit(0); + } + else { + int process_status_224; + __e_acsl_store_block((void *)(& process_status_224),(size_t)4); + waitpid(pid_224,& process_status_224,0); + signal_eval(process_status_224,0,__gen_e_acsl_literal_string_280); + __e_acsl_delete_block((void *)(& process_status_224)); + } + __e_acsl_delete_block((void *)(& pid_224)); + } + { + pid_t pid_225 = fork(); + __e_acsl_store_block((void *)(& pid_225),(size_t)4); + __e_acsl_full_init((void *)(& pid_225)); + if (! pid_225) { + __e_acsl_builtin_printf("d",__gen_e_acsl_literal_string_278,(int)shrt); + __gen_e_acsl_exit(0); + } + else { + int process_status_225; + __e_acsl_store_block((void *)(& process_status_225),(size_t)4); + waitpid(pid_225,& process_status_225,0); + signal_eval(process_status_225,0,__gen_e_acsl_literal_string_281); + __e_acsl_delete_block((void *)(& process_status_225)); + } + __e_acsl_delete_block((void *)(& pid_225)); + } + { + pid_t pid_226 = fork(); + __e_acsl_store_block((void *)(& pid_226),(size_t)4); + __e_acsl_full_init((void *)(& pid_226)); + if (! pid_226) { + __e_acsl_builtin_printf("D",__gen_e_acsl_literal_string_278,ui); + __gen_e_acsl_exit(0); + } + else { + int process_status_226; + __e_acsl_store_block((void *)(& process_status_226),(size_t)4); + waitpid(pid_226,& process_status_226,0); + signal_eval(process_status_226,1,__gen_e_acsl_literal_string_282); + __e_acsl_delete_block((void *)(& process_status_226)); + } + __e_acsl_delete_block((void *)(& pid_226)); + } + { + pid_t pid_227 = fork(); + __e_acsl_store_block((void *)(& pid_227),(size_t)4); + __e_acsl_full_init((void *)(& pid_227)); + if (! pid_227) { + __e_acsl_builtin_printf("l",__gen_e_acsl_literal_string_278,li); + __gen_e_acsl_exit(0); + } + else { + int process_status_227; + __e_acsl_store_block((void *)(& process_status_227),(size_t)4); + waitpid(pid_227,& process_status_227,0); + signal_eval(process_status_227,1,__gen_e_acsl_literal_string_283); + __e_acsl_delete_block((void *)(& process_status_227)); + } + __e_acsl_delete_block((void *)(& pid_227)); + } + { + pid_t pid_228 = fork(); + __e_acsl_store_block((void *)(& pid_228),(size_t)4); + __e_acsl_full_init((void *)(& pid_228)); + if (! pid_228) { + __e_acsl_builtin_printf("e",__gen_e_acsl_literal_string_278, + (double)flt); + __gen_e_acsl_exit(0); + } + else { + int process_status_228; + __e_acsl_store_block((void *)(& process_status_228),(size_t)4); + waitpid(pid_228,& process_status_228,0); + signal_eval(process_status_228,1,__gen_e_acsl_literal_string_284); + __e_acsl_delete_block((void *)(& process_status_228)); + } + __e_acsl_delete_block((void *)(& pid_228)); + } + { + pid_t pid_229 = fork(); + __e_acsl_store_block((void *)(& pid_229),(size_t)4); + __e_acsl_full_init((void *)(& pid_229)); + if (! pid_229) { + __e_acsl_builtin_printf("s",__gen_e_acsl_literal_string_278,astr); + __gen_e_acsl_exit(0); + } + else { + int process_status_229; + __e_acsl_store_block((void *)(& process_status_229),(size_t)4); + waitpid(pid_229,& process_status_229,0); + signal_eval(process_status_229,1,__gen_e_acsl_literal_string_285); + __e_acsl_delete_block((void *)(& process_status_229)); + } + __e_acsl_delete_block((void *)(& pid_229)); + } + { + pid_t pid_230 = fork(); + __e_acsl_store_block((void *)(& pid_230),(size_t)4); + __e_acsl_full_init((void *)(& pid_230)); + if (! pid_230) { + __e_acsl_builtin_printf("D",__gen_e_acsl_literal_string_286,wi); + __gen_e_acsl_exit(0); + } + else { + int process_status_230; + __e_acsl_store_block((void *)(& process_status_230),(size_t)4); + waitpid(pid_230,& process_status_230,0); + signal_eval(process_status_230,0,__gen_e_acsl_literal_string_287); + __e_acsl_delete_block((void *)(& process_status_230)); + } + __e_acsl_delete_block((void *)(& pid_230)); + } + { + pid_t pid_231 = fork(); + __e_acsl_store_block((void *)(& pid_231),(size_t)4); + __e_acsl_full_init((void *)(& pid_231)); + if (! pid_231) { + __e_acsl_builtin_printf("l",__gen_e_acsl_literal_string_286,li); + __gen_e_acsl_exit(0); + } + else { + int process_status_231; + __e_acsl_store_block((void *)(& process_status_231),(size_t)4); + waitpid(pid_231,& process_status_231,0); + signal_eval(process_status_231,1,__gen_e_acsl_literal_string_288); + __e_acsl_delete_block((void *)(& process_status_231)); + } + __e_acsl_delete_block((void *)(& pid_231)); + } + { + pid_t pid_232 = fork(); + __e_acsl_store_block((void *)(& pid_232),(size_t)4); + __e_acsl_full_init((void *)(& pid_232)); + if (! pid_232) { + __e_acsl_builtin_printf("s",__gen_e_acsl_literal_string_289,astr); + __gen_e_acsl_exit(0); + } + else { + int process_status_232; + __e_acsl_store_block((void *)(& process_status_232),(size_t)4); + waitpid(pid_232,& process_status_232,0); + signal_eval(process_status_232,0,__gen_e_acsl_literal_string_290); + __e_acsl_delete_block((void *)(& process_status_232)); + } + __e_acsl_delete_block((void *)(& pid_232)); + } + { + pid_t pid_233 = fork(); + __e_acsl_store_block((void *)(& pid_233),(size_t)4); + __e_acsl_full_init((void *)(& pid_233)); + if (! pid_233) { + __e_acsl_builtin_printf("s",__gen_e_acsl_literal_string_289,pstr); + __gen_e_acsl_exit(0); + } + else { + int process_status_233; + __e_acsl_store_block((void *)(& process_status_233),(size_t)4); + waitpid(pid_233,& process_status_233,0); + signal_eval(process_status_233,0,__gen_e_acsl_literal_string_291); + __e_acsl_delete_block((void *)(& process_status_233)); + } + __e_acsl_delete_block((void *)(& pid_233)); + } + { + pid_t pid_234 = fork(); + __e_acsl_store_block((void *)(& pid_234),(size_t)4); + __e_acsl_full_init((void *)(& pid_234)); + if (! pid_234) { + __e_acsl_builtin_printf("d",__gen_e_acsl_literal_string_289,i); + __gen_e_acsl_exit(0); + } + else { + int process_status_234; + __e_acsl_store_block((void *)(& process_status_234),(size_t)4); + waitpid(pid_234,& process_status_234,0); + signal_eval(process_status_234,1,__gen_e_acsl_literal_string_292); + __e_acsl_delete_block((void *)(& process_status_234)); + } + __e_acsl_delete_block((void *)(& pid_234)); + } + { + pid_t pid_235 = fork(); + __e_acsl_store_block((void *)(& pid_235),(size_t)4); + __e_acsl_full_init((void *)(& pid_235)); + if (! pid_235) { + __e_acsl_builtin_printf("p",__gen_e_acsl_literal_string_289,vptr); + __gen_e_acsl_exit(0); + } + else { + int process_status_235; + __e_acsl_store_block((void *)(& process_status_235),(size_t)4); + waitpid(pid_235,& process_status_235,0); + signal_eval(process_status_235,1,__gen_e_acsl_literal_string_293); + __e_acsl_delete_block((void *)(& process_status_235)); + } + __e_acsl_delete_block((void *)(& pid_235)); + } + char *s1 = (char *)0; + __e_acsl_store_block((void *)(& s1),(size_t)8); + __e_acsl_full_init((void *)(& s1)); + { + pid_t pid_236 = fork(); + __e_acsl_store_block((void *)(& pid_236),(size_t)4); + __e_acsl_full_init((void *)(& pid_236)); + if (! pid_236) { + __e_acsl_builtin_printf("s",__gen_e_acsl_literal_string_289,s1); + __gen_e_acsl_exit(0); + } + else { + int process_status_236; + __e_acsl_store_block((void *)(& process_status_236),(size_t)4); + waitpid(pid_236,& process_status_236,0); + signal_eval(process_status_236,1,__gen_e_acsl_literal_string_294); + __e_acsl_delete_block((void *)(& process_status_236)); + } + __e_acsl_delete_block((void *)(& pid_236)); + } + { + pid_t pid_237 = fork(); + __e_acsl_store_block((void *)(& pid_237),(size_t)4); + __e_acsl_full_init((void *)(& pid_237)); + if (! pid_237) { + __e_acsl_builtin_printf("s",__gen_e_acsl_literal_string_289,s2); + __gen_e_acsl_exit(0); + } + else { + int process_status_237; + __e_acsl_store_block((void *)(& process_status_237),(size_t)4); + waitpid(pid_237,& process_status_237,0); + signal_eval(process_status_237,1,__gen_e_acsl_literal_string_295); + __e_acsl_delete_block((void *)(& process_status_237)); + } + __e_acsl_delete_block((void *)(& pid_237)); + } + char s4[4] = {(char)'c', (char)'a', (char)'t', (char)'\000'}; + __e_acsl_store_block((void *)(s4),(size_t)4); + __e_acsl_full_init((void *)(& s4)); + { + pid_t pid_238 = fork(); + __e_acsl_store_block((void *)(& pid_238),(size_t)4); + __e_acsl_full_init((void *)(& pid_238)); + if (! pid_238) { + __e_acsl_builtin_printf("s",__gen_e_acsl_literal_string_289,s4); + __gen_e_acsl_exit(0); + } + else { + int process_status_238; + __e_acsl_store_block((void *)(& process_status_238),(size_t)4); + waitpid(pid_238,& process_status_238,0); + signal_eval(process_status_238,0,__gen_e_acsl_literal_string_296); + __e_acsl_delete_block((void *)(& process_status_238)); + } + __e_acsl_delete_block((void *)(& pid_238)); + } + __e_acsl_initialize((void *)(& s4[3]),sizeof(char)); + s4[3] = (char)'s'; + { + pid_t pid_239 = fork(); + __e_acsl_store_block((void *)(& pid_239),(size_t)4); + __e_acsl_full_init((void *)(& pid_239)); + if (! pid_239) { + __e_acsl_builtin_printf("s",__gen_e_acsl_literal_string_289,s4); + __gen_e_acsl_exit(0); + } + else { + int process_status_239; + __e_acsl_store_block((void *)(& process_status_239),(size_t)4); + waitpid(pid_239,& process_status_239,0); + signal_eval(process_status_239,1,__gen_e_acsl_literal_string_297); + __e_acsl_delete_block((void *)(& process_status_239)); + } + __e_acsl_delete_block((void *)(& pid_239)); + } + { + pid_t pid_240 = fork(); + __e_acsl_store_block((void *)(& pid_240),(size_t)4); + __e_acsl_full_init((void *)(& pid_240)); + if (! pid_240) { + __e_acsl_builtin_printf("s",__gen_e_acsl_literal_string_298,s1); + __gen_e_acsl_exit(0); + } + else { + int process_status_240; + __e_acsl_store_block((void *)(& process_status_240),(size_t)4); + waitpid(pid_240,& process_status_240,0); + signal_eval(process_status_240,0,__gen_e_acsl_literal_string_299); + __e_acsl_delete_block((void *)(& process_status_240)); + } + __e_acsl_delete_block((void *)(& pid_240)); + } + { + pid_t pid_241 = fork(); + __e_acsl_store_block((void *)(& pid_241),(size_t)4); + __e_acsl_full_init((void *)(& pid_241)); + if (! pid_241) { + __e_acsl_builtin_printf("s",__gen_e_acsl_literal_string_300,s1); + __gen_e_acsl_exit(0); + } + else { + int process_status_241; + __e_acsl_store_block((void *)(& process_status_241),(size_t)4); + waitpid(pid_241,& process_status_241,0); + signal_eval(process_status_241,0,__gen_e_acsl_literal_string_301); + __e_acsl_delete_block((void *)(& process_status_241)); + } + __e_acsl_delete_block((void *)(& pid_241)); + } + { + pid_t pid_242 = fork(); + __e_acsl_store_block((void *)(& pid_242),(size_t)4); + __e_acsl_full_init((void *)(& pid_242)); + if (! pid_242) { + __e_acsl_builtin_printf("s",__gen_e_acsl_literal_string_302,s4); + __gen_e_acsl_exit(0); + } + else { + int process_status_242; + __e_acsl_store_block((void *)(& process_status_242),(size_t)4); + waitpid(pid_242,& process_status_242,0); + signal_eval(process_status_242,0,__gen_e_acsl_literal_string_303); + __e_acsl_delete_block((void *)(& process_status_242)); + } + __e_acsl_delete_block((void *)(& pid_242)); + } + { + pid_t pid_243 = fork(); + __e_acsl_store_block((void *)(& pid_243),(size_t)4); + __e_acsl_full_init((void *)(& pid_243)); + if (! pid_243) { + __e_acsl_builtin_printf("s",__gen_e_acsl_literal_string_304,s4); + __gen_e_acsl_exit(0); + } + else { + int process_status_243; + __e_acsl_store_block((void *)(& process_status_243),(size_t)4); + waitpid(pid_243,& process_status_243,0); + signal_eval(process_status_243,0,__gen_e_acsl_literal_string_305); + __e_acsl_delete_block((void *)(& process_status_243)); + } + __e_acsl_delete_block((void *)(& pid_243)); + } + { + pid_t pid_244 = fork(); + __e_acsl_store_block((void *)(& pid_244),(size_t)4); + __e_acsl_full_init((void *)(& pid_244)); + if (! pid_244) { + __e_acsl_builtin_printf("s",__gen_e_acsl_literal_string_306,s4); + __gen_e_acsl_exit(0); + } + else { + int process_status_244; + __e_acsl_store_block((void *)(& process_status_244),(size_t)4); + waitpid(pid_244,& process_status_244,0); + signal_eval(process_status_244,1,__gen_e_acsl_literal_string_307); + __e_acsl_delete_block((void *)(& process_status_244)); + } + __e_acsl_delete_block((void *)(& pid_244)); + } + { + pid_t pid_245 = fork(); + __e_acsl_store_block((void *)(& pid_245),(size_t)4); + __e_acsl_full_init((void *)(& pid_245)); + if (! pid_245) { + __e_acsl_builtin_printf("p",__gen_e_acsl_literal_string_308,vptr); + __gen_e_acsl_exit(0); + } + else { + int process_status_245; + __e_acsl_store_block((void *)(& process_status_245),(size_t)4); + waitpid(pid_245,& process_status_245,0); + signal_eval(process_status_245,0,__gen_e_acsl_literal_string_309); + __e_acsl_delete_block((void *)(& process_status_245)); + } + __e_acsl_delete_block((void *)(& pid_245)); + } + { + pid_t pid_246 = fork(); + __e_acsl_store_block((void *)(& pid_246),(size_t)4); + __e_acsl_full_init((void *)(& pid_246)); + if (! pid_246) { + __e_acsl_builtin_printf("s",__gen_e_acsl_literal_string_308,astr); + __gen_e_acsl_exit(0); + } + else { + int process_status_246; + __e_acsl_store_block((void *)(& process_status_246),(size_t)4); + waitpid(pid_246,& process_status_246,0); + signal_eval(process_status_246,1,__gen_e_acsl_literal_string_310); + __e_acsl_delete_block((void *)(& process_status_246)); + } + __e_acsl_delete_block((void *)(& pid_246)); + } + { + pid_t pid_247 = fork(); + __e_acsl_store_block((void *)(& pid_247),(size_t)4); + __e_acsl_full_init((void *)(& pid_247)); + if (! pid_247) { + __e_acsl_builtin_printf("p",__gen_e_acsl_literal_string_308,(void *)0); + __gen_e_acsl_exit(0); + } + else { + int process_status_247; + __e_acsl_store_block((void *)(& process_status_247),(size_t)4); + waitpid(pid_247,& process_status_247,0); + signal_eval(process_status_247,1,__gen_e_acsl_literal_string_311); + __e_acsl_delete_block((void *)(& process_status_247)); + } + __e_acsl_delete_block((void *)(& pid_247)); + } + { + pid_t pid_248 = fork(); + __e_acsl_store_block((void *)(& pid_248),(size_t)4); + __e_acsl_full_init((void *)(& pid_248)); + if (! pid_248) { + __e_acsl_builtin_printf("i",__gen_e_acsl_literal_string_312,& i); + __gen_e_acsl_exit(0); + } + else { + int process_status_248; + __e_acsl_store_block((void *)(& process_status_248),(size_t)4); + waitpid(pid_248,& process_status_248,0); + signal_eval(process_status_248,0,__gen_e_acsl_literal_string_313); + __e_acsl_delete_block((void *)(& process_status_248)); + } + __e_acsl_delete_block((void *)(& pid_248)); + } + { + pid_t pid_249 = fork(); + __e_acsl_store_block((void *)(& pid_249),(size_t)4); + __e_acsl_full_init((void *)(& pid_249)); + if (! pid_249) { + __e_acsl_builtin_printf("I",__gen_e_acsl_literal_string_312,& ui); + __gen_e_acsl_exit(0); + } + else { + int process_status_249; + __e_acsl_store_block((void *)(& process_status_249),(size_t)4); + waitpid(pid_249,& process_status_249,0); + signal_eval(process_status_249,1,__gen_e_acsl_literal_string_314); + __e_acsl_delete_block((void *)(& process_status_249)); + } + __e_acsl_delete_block((void *)(& pid_249)); + } + { + pid_t pid_250 = fork(); + __e_acsl_store_block((void *)(& pid_250),(size_t)4); + __e_acsl_full_init((void *)(& pid_250)); + if (! pid_250) { + __e_acsl_builtin_printf("p",__gen_e_acsl_literal_string_312,(void *)0); + __gen_e_acsl_exit(0); + } + else { + int process_status_250; + __e_acsl_store_block((void *)(& process_status_250),(size_t)4); + waitpid(pid_250,& process_status_250,0); + signal_eval(process_status_250,1,__gen_e_acsl_literal_string_315); + __e_acsl_delete_block((void *)(& process_status_250)); + } + __e_acsl_delete_block((void *)(& pid_250)); + } + { + pid_t pid_251 = fork(); + __e_acsl_store_block((void *)(& pid_251),(size_t)4); + __e_acsl_full_init((void *)(& pid_251)); + if (! pid_251) { + __e_acsl_builtin_printf("i",__gen_e_acsl_literal_string_312, + (int *)pstr); + __gen_e_acsl_exit(0); + } + else { + int process_status_251; + __e_acsl_store_block((void *)(& process_status_251),(size_t)4); + waitpid(pid_251,& process_status_251,0); + signal_eval(process_status_251,1,__gen_e_acsl_literal_string_316); + __e_acsl_delete_block((void *)(& process_status_251)); + } + __e_acsl_delete_block((void *)(& pid_251)); + } + { + pid_t pid_252 = fork(); + __e_acsl_store_block((void *)(& pid_252),(size_t)4); + __e_acsl_full_init((void *)(& pid_252)); + if (! pid_252) { + __e_acsl_builtin_printf("i",__gen_e_acsl_literal_string_317,& i); + __gen_e_acsl_exit(0); + } + else { + int process_status_252; + __e_acsl_store_block((void *)(& process_status_252),(size_t)4); + waitpid(pid_252,& process_status_252,0); + signal_eval(process_status_252,1,__gen_e_acsl_literal_string_318); + __e_acsl_delete_block((void *)(& process_status_252)); + } + __e_acsl_delete_block((void *)(& pid_252)); + } + { + pid_t pid_253 = fork(); + __e_acsl_store_block((void *)(& pid_253),(size_t)4); + __e_acsl_full_init((void *)(& pid_253)); + if (! pid_253) { + __e_acsl_builtin_printf("i",__gen_e_acsl_literal_string_319,& i); + __gen_e_acsl_exit(0); + } + else { + int process_status_253; + __e_acsl_store_block((void *)(& process_status_253),(size_t)4); + waitpid(pid_253,& process_status_253,0); + signal_eval(process_status_253,1,__gen_e_acsl_literal_string_320); + __e_acsl_delete_block((void *)(& process_status_253)); + } + __e_acsl_delete_block((void *)(& pid_253)); + } + { + pid_t pid_254 = fork(); + __e_acsl_store_block((void *)(& pid_254),(size_t)4); + __e_acsl_full_init((void *)(& pid_254)); + if (! pid_254) { + __e_acsl_builtin_printf("i",__gen_e_acsl_literal_string_321,& i); + __gen_e_acsl_exit(0); + } + else { + int process_status_254; + __e_acsl_store_block((void *)(& process_status_254),(size_t)4); + waitpid(pid_254,& process_status_254,0); + signal_eval(process_status_254,1,__gen_e_acsl_literal_string_322); + __e_acsl_delete_block((void *)(& process_status_254)); + } + __e_acsl_delete_block((void *)(& pid_254)); + } + { + pid_t pid_255 = fork(); + __e_acsl_store_block((void *)(& pid_255),(size_t)4); + __e_acsl_full_init((void *)(& pid_255)); + if (! pid_255) { + __e_acsl_builtin_printf("i",__gen_e_acsl_literal_string_323,& i); + __gen_e_acsl_exit(0); + } + else { + int process_status_255; + __e_acsl_store_block((void *)(& process_status_255),(size_t)4); + waitpid(pid_255,& process_status_255,0); + signal_eval(process_status_255,1,__gen_e_acsl_literal_string_324); + __e_acsl_delete_block((void *)(& process_status_255)); + } + __e_acsl_delete_block((void *)(& pid_255)); + } + { + pid_t pid_256 = fork(); + __e_acsl_store_block((void *)(& pid_256),(size_t)4); + __e_acsl_full_init((void *)(& pid_256)); + if (! pid_256) { + __e_acsl_builtin_printf("i",__gen_e_acsl_literal_string_325,& i); + __gen_e_acsl_exit(0); + } + else { + int process_status_256; + __e_acsl_store_block((void *)(& process_status_256),(size_t)4); + waitpid(pid_256,& process_status_256,0); + signal_eval(process_status_256,1,__gen_e_acsl_literal_string_326); + __e_acsl_delete_block((void *)(& process_status_256)); + } + __e_acsl_delete_block((void *)(& pid_256)); + } + { + pid_t pid_257 = fork(); + __e_acsl_store_block((void *)(& pid_257),(size_t)4); + __e_acsl_full_init((void *)(& pid_257)); + if (! pid_257) { + __e_acsl_builtin_printf("i",__gen_e_acsl_literal_string_327,& i); + __gen_e_acsl_exit(0); + } + else { + int process_status_257; + __e_acsl_store_block((void *)(& process_status_257),(size_t)4); + waitpid(pid_257,& process_status_257,0); + signal_eval(process_status_257,1,__gen_e_acsl_literal_string_328); + __e_acsl_delete_block((void *)(& process_status_257)); + } + __e_acsl_delete_block((void *)(& pid_257)); + } + { + pid_t pid_258 = fork(); + __e_acsl_store_block((void *)(& pid_258),(size_t)4); + __e_acsl_full_init((void *)(& pid_258)); + if (! pid_258) { + __e_acsl_builtin_printf("i",__gen_e_acsl_literal_string_329,& i); + __gen_e_acsl_exit(0); + } + else { + int process_status_258; + __e_acsl_store_block((void *)(& process_status_258),(size_t)4); + waitpid(pid_258,& process_status_258,0); + signal_eval(process_status_258,1,__gen_e_acsl_literal_string_330); + __e_acsl_delete_block((void *)(& process_status_258)); + } + __e_acsl_delete_block((void *)(& pid_258)); + } + { + pid_t pid_259 = fork(); + __e_acsl_store_block((void *)(& pid_259),(size_t)4); + __e_acsl_full_init((void *)(& pid_259)); + if (! pid_259) { + __e_acsl_builtin_printf("i",__gen_e_acsl_literal_string_331,& i); + __gen_e_acsl_exit(0); + } + else { + int process_status_259; + __e_acsl_store_block((void *)(& process_status_259),(size_t)4); + waitpid(pid_259,& process_status_259,0); + signal_eval(process_status_259,1,__gen_e_acsl_literal_string_332); + __e_acsl_delete_block((void *)(& process_status_259)); + } + __e_acsl_delete_block((void *)(& pid_259)); + } + { + pid_t pid_260 = fork(); + __e_acsl_store_block((void *)(& pid_260),(size_t)4); + __e_acsl_full_init((void *)(& pid_260)); + if (! pid_260) { + __e_acsl_builtin_printf("i",__gen_e_acsl_literal_string_331,& i); + __gen_e_acsl_exit(0); + } + else { + int process_status_260; + __e_acsl_store_block((void *)(& process_status_260),(size_t)4); + waitpid(pid_260,& process_status_260,0); + signal_eval(process_status_260,1,__gen_e_acsl_literal_string_333); + __e_acsl_delete_block((void *)(& process_status_260)); + } + __e_acsl_delete_block((void *)(& pid_260)); + } + { + pid_t pid_261 = fork(); + __e_acsl_store_block((void *)(& pid_261),(size_t)4); + __e_acsl_full_init((void *)(& pid_261)); + if (! pid_261) { + __e_acsl_builtin_printf("i",__gen_e_acsl_literal_string_334,& i); + __gen_e_acsl_exit(0); + } + else { + int process_status_261; + __e_acsl_store_block((void *)(& process_status_261),(size_t)4); + waitpid(pid_261,& process_status_261,0); + signal_eval(process_status_261,1,__gen_e_acsl_literal_string_335); + __e_acsl_delete_block((void *)(& process_status_261)); + } + __e_acsl_delete_block((void *)(& pid_261)); + } + { + pid_t pid_262 = fork(); + __e_acsl_store_block((void *)(& pid_262),(size_t)4); + __e_acsl_full_init((void *)(& pid_262)); + if (! pid_262) { + __e_acsl_builtin_printf("dD",__gen_e_acsl_literal_string_336,i,ui); + __gen_e_acsl_exit(0); + } + else { + int process_status_262; + __e_acsl_store_block((void *)(& process_status_262),(size_t)4); + waitpid(pid_262,& process_status_262,0); + signal_eval(process_status_262,1,__gen_e_acsl_literal_string_337); + __e_acsl_delete_block((void *)(& process_status_262)); + } + __e_acsl_delete_block((void *)(& pid_262)); + } + __e_acsl_full_init((void *)(& __retres)); + __retres = 0; + __e_acsl_delete_block((void *)(& argv)); + __e_acsl_delete_block((void *)(& argc)); + __e_acsl_delete_block((void *)(& test_specifier_application)); + __e_acsl_delete_block((void *)(& apply_specifier)); + __e_acsl_delete_block((void *)(& valid_specifiers)); + __e_acsl_delete_block((void *)(& signal_eval)); + __e_acsl_delete_block((void *)(& testno)); + __e_acsl_delete_block((void *)(& __fc_p_time_tm)); + __e_acsl_delete_block((void *)(& __fc_time_tm)); + __e_acsl_delete_block((void *)(__fc_fds)); + __e_acsl_delete_block((void *)(& __fc_fds_state)); + __e_acsl_delete_block((void *)(& __fc_time)); + __e_acsl_delete_block((void *)(& __fc_p_strerror)); + __e_acsl_delete_block((void *)(strerror)); + __e_acsl_delete_block((void *)(& __fc_strtok_ptr)); + __e_acsl_delete_block((void *)(& __fc_p_fopen)); + __e_acsl_delete_block((void *)(__fc_fopen)); + __e_acsl_delete_block((void *)(& __fc_rand_max)); + __e_acsl_delete_block((void *)(s4)); + __e_acsl_delete_block((void *)(& s2)); + __e_acsl_delete_block((void *)(& s1)); + __e_acsl_delete_block((void *)(fmt)); + __e_acsl_delete_block((void *)(& ptrdf)); + __e_acsl_delete_block((void *)(& szt)); + __e_acsl_delete_block((void *)(& uimax)); + __e_acsl_delete_block((void *)(& imax)); + __e_acsl_delete_block((void *)(& ldbl)); + __e_acsl_delete_block((void *)(& dbl)); + __e_acsl_delete_block((void *)(& flt)); + __e_acsl_delete_block((void *)(& llu)); + __e_acsl_delete_block((void *)(& lli)); + __e_acsl_delete_block((void *)(& lu)); + __e_acsl_delete_block((void *)(& li)); + __e_acsl_delete_block((void *)(& wi)); + __e_acsl_delete_block((void *)(& ui)); + __e_acsl_delete_block((void *)(& i)); + __e_acsl_delete_block((void *)(& ushrt)); + __e_acsl_delete_block((void *)(& shrt)); + __e_acsl_delete_block((void *)(& uchr)); + __e_acsl_delete_block((void *)(& chr)); + __e_acsl_delete_block((void *)(& vptr)); + __e_acsl_delete_block((void *)(& sastr)); + __e_acsl_delete_block((void *)(astr)); + __e_acsl_delete_block((void *)(& pstr)); + __e_acsl_delete_block((void *)(& __retres)); + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/format/oracle_ci/gen_printf2.c b/src/plugins/e-acsl/tests/format/oracle_ci/gen_printf2.c new file mode 100644 index 0000000000000000000000000000000000000000..6209d961c8a49396a36a19193d6ba7a3fa8e4367 --- /dev/null +++ b/src/plugins/e-acsl/tests/format/oracle_ci/gen_printf2.c @@ -0,0 +1,362 @@ +/* Generated by Frama-C */ +#include "signal.h" +#include "stdio.h" +#include "stdlib.h" +#include "string.h" +#include "sys/time.h" +#include "sys/wait.h" +#include "time.h" +#include "unistd.h" +#include "wchar.h" +char *__gen_e_acsl_literal_string_6; +char *__gen_e_acsl_literal_string_8; +char *__gen_e_acsl_literal_string_5; +char *__gen_e_acsl_literal_string_9; +char *__gen_e_acsl_literal_string_7; +char *__gen_e_acsl_literal_string; +char *__gen_e_acsl_literal_string_2; +char *__gen_e_acsl_literal_string_4; +char *__gen_e_acsl_literal_string_3; +void signal_eval(int status, int expect_signal, char const *at) +{ + __e_acsl_store_block((void *)(& at),(size_t)8); + __e_acsl_store_block((void *)(& expect_signal),(size_t)4); + __e_acsl_store_block((void *)(& status),(size_t)4); + int signalled = (int)((signed char)((status & 0x7f) + 1)) >> 1 > 0; + __e_acsl_store_block((void *)(& signalled),(size_t)4); + __e_acsl_full_init((void *)(& signalled)); + if (signalled) { + if (expect_signal) __e_acsl_builtin_printf("s", + __gen_e_acsl_literal_string, + at); + else goto _LAND_1; + } + else + _LAND_1: + if (! signalled) { + if (! expect_signal) __e_acsl_builtin_printf("s", + __gen_e_acsl_literal_string_2, + at); + else goto _LAND_0; + } + else + _LAND_0: + if (! signalled) { + if (expect_signal) { + __e_acsl_builtin_printf("s",__gen_e_acsl_literal_string_3,at); + __gen_e_acsl_exit(1); + } + else goto _LAND; + } + else { + _LAND: ; + if (signalled) + if (! expect_signal) { + __e_acsl_builtin_printf("s",__gen_e_acsl_literal_string_4,at); + __gen_e_acsl_exit(2); + } + } + __e_acsl_delete_block((void *)(& at)); + __e_acsl_delete_block((void *)(& expect_signal)); + __e_acsl_delete_block((void *)(& status)); + __e_acsl_delete_block((void *)(& signalled)); + return; +} + +char const *valid_specifiers = "diouxfFeEgGaAcspn"; +void apply_specifier(char *format, int spec) +{ + int n; + char *tmp_1; + __e_acsl_store_block((void *)(& tmp_1),(size_t)8); + __e_acsl_store_block((void *)(& n),(size_t)4); + __e_acsl_store_block((void *)(& spec),(size_t)4); + __e_acsl_store_block((void *)(& format),(size_t)8); + void *p = (void *)0; + __e_acsl_store_block((void *)(& p),(size_t)8); + __e_acsl_full_init((void *)(& p)); + __e_acsl_full_init((void *)(& tmp_1)); + tmp_1 = __gen_e_acsl_strchr(__gen_e_acsl_literal_string_5,spec); + if (tmp_1 != (char *)0) __e_acsl_builtin_printf("e",(char const *)format, + 1.0); + else { + char *tmp_0; + __e_acsl_store_block((void *)(& tmp_0),(size_t)8); + __e_acsl_full_init((void *)(& tmp_0)); + tmp_0 = __gen_e_acsl_strchr(__gen_e_acsl_literal_string_6,spec); + if (tmp_0 != (char *)0) __e_acsl_builtin_printf("D",(char const *)format, + 1U); + else { + char *tmp; + __e_acsl_store_block((void *)(& tmp),(size_t)8); + __e_acsl_full_init((void *)(& tmp)); + tmp = __gen_e_acsl_strchr(__gen_e_acsl_literal_string_7,spec); + if (tmp != (char *)0) __e_acsl_builtin_printf("d",(char const *)format, + 97); + else + if (spec == 's') __e_acsl_builtin_printf("s",(char const *)format, + __gen_e_acsl_literal_string_8); + else + if (spec == 'n') __e_acsl_builtin_printf("i",(char const *)format, + & n); + else + if (spec == 'p') __e_acsl_builtin_printf("p", + (char const *)format,p); + else __gen_e_acsl_abort(); + __e_acsl_delete_block((void *)(& tmp)); + } + __e_acsl_delete_block((void *)(& tmp_0)); + } + __e_acsl_delete_block((void *)(& spec)); + __e_acsl_delete_block((void *)(& format)); + __e_acsl_delete_block((void *)(& tmp_1)); + __e_acsl_delete_block((void *)(& p)); + __e_acsl_delete_block((void *)(& n)); + return; +} + +/*@ assigns \nothing; */ + __attribute__((__FC_BUILTIN__)) void __e_acsl_delete_block(void *); + +/* compiler builtin: + void *__builtin_alloca(unsigned long); */ +void test_specifier_application(char const *allowed, char const *fmt, + int only_negative, char *at) +{ + size_t tmp; + unsigned long __lengthof_format; + __e_acsl_store_block((void *)(& __lengthof_format),(size_t)8); + __e_acsl_store_block((void *)(& tmp),(size_t)8); + __e_acsl_store_block((void *)(& at),(size_t)8); + __e_acsl_store_block((void *)(& only_negative),(size_t)4); + __e_acsl_store_block((void *)(& fmt),(size_t)8); + __e_acsl_store_block((void *)(& allowed),(size_t)8); + __e_acsl_full_init((void *)(& tmp)); + tmp = __gen_e_acsl_strlen(fmt); + int len = (int)tmp; + __e_acsl_store_block((void *)(& len),(size_t)4); + __e_acsl_full_init((void *)(& len)); + /*@ assert + alloca_bounds: 0 < sizeof(char) * (len + 1) ≤ 18446744073709551615; + */ + { + int __gen_e_acsl_and; + if (0L < 1L * (len + 1L)) { + __e_acsl_mpz_t __gen_e_acsl_; + __e_acsl_mpz_t __gen_e_acsl__2; + int __gen_e_acsl_le; + __gmpz_init_set_si(__gen_e_acsl_,1L * (len + 1L)); + __gmpz_init_set_ui(__gen_e_acsl__2,18446744073709551615UL); + __gen_e_acsl_le = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__2)); + __gen_e_acsl_and = __gen_e_acsl_le <= 0; + __gmpz_clear(__gen_e_acsl_); + __gmpz_clear(__gen_e_acsl__2); + } + else __gen_e_acsl_and = 0; + __e_acsl_assert(__gen_e_acsl_and,(char *)"Assertion", + (char *)"test_specifier_application", + (char *)"alloca_bounds: 0 < sizeof(char) * (len + 1) <= 18446744073709551615", + 82); + } + __e_acsl_full_init((void *)(& __lengthof_format)); + __lengthof_format = (unsigned long)(len + 1); + char *format = __builtin_alloca(sizeof(char) * __lengthof_format); + __e_acsl_store_block((void *)format,sizeof(char) * __lengthof_format); + __e_acsl_store_block((void *)(& format),(size_t)8); + __e_acsl_full_init((void *)(& format)); + __gen_e_acsl_strcpy(format,fmt); + { + int i_0 = 0; + __e_acsl_store_block((void *)(& i_0),(size_t)4); + __e_acsl_full_init((void *)(& i_0)); + while (1) { + size_t tmp_3; + __e_acsl_store_block((void *)(& tmp_3),(size_t)8); + __e_acsl_full_init((void *)(& tmp_3)); + tmp_3 = __gen_e_acsl_strlen(valid_specifiers); + ; + if (! ((size_t)i_0 < tmp_3)) { + __e_acsl_delete_block((void *)(& tmp_3)); + break; + } + { + char *tmp_2; + __e_acsl_store_block((void *)(& tmp_2),(size_t)8); + int c = (int)*(valid_specifiers + i_0); + __e_acsl_store_block((void *)(& c),(size_t)4); + __e_acsl_full_init((void *)(& c)); + __e_acsl_initialize((void *)(format + (len - 1)),sizeof(char)); + *(format + (len - 1)) = (char)c; + __e_acsl_full_init((void *)(& tmp_2)); + tmp_2 = __gen_e_acsl_strchr(allowed,c); + if (tmp_2) { + if (! only_negative) { + { + pid_t pid = fork(); + __e_acsl_store_block((void *)(& pid),(size_t)4); + __e_acsl_full_init((void *)(& pid)); + if (! pid) { + apply_specifier(format,c); + __gen_e_acsl_exit(0); + } + else { + int process_status; + __e_acsl_store_block((void *)(& process_status),(size_t)4); + waitpid(pid,& process_status,0); + signal_eval(process_status,0,(char const *)at); + __e_acsl_delete_block((void *)(& process_status)); + } + __e_acsl_delete_block((void *)(& pid)); + } + } + } + else { + { + pid_t pid_0 = fork(); + __e_acsl_store_block((void *)(& pid_0),(size_t)4); + __e_acsl_full_init((void *)(& pid_0)); + if (! pid_0) { + apply_specifier(format,c); + __gen_e_acsl_exit(0); + } + else { + int process_status_0; + __e_acsl_store_block((void *)(& process_status_0),(size_t)4); + waitpid(pid_0,& process_status_0,0); + signal_eval(process_status_0,1,(char const *)at); + __e_acsl_delete_block((void *)(& process_status_0)); + } + __e_acsl_delete_block((void *)(& pid_0)); + } + } + __e_acsl_delete_block((void *)(& tmp_2)); + __e_acsl_delete_block((void *)(& c)); + } + __e_acsl_full_init((void *)(& i_0)); + i_0 ++; + __e_acsl_delete_block((void *)(& tmp_3)); + } + __e_acsl_delete_block((void *)(& i_0)); + } + __e_acsl_delete_block((void *)format); + __e_acsl_delete_block((void *)(& at)); + __e_acsl_delete_block((void *)(& only_negative)); + __e_acsl_delete_block((void *)(& fmt)); + __e_acsl_delete_block((void *)(& allowed)); + __e_acsl_delete_block((void *)(& __lengthof_format)); + __e_acsl_delete_block((void *)(& format)); + __e_acsl_delete_block((void *)(& tmp)); + __e_acsl_delete_block((void *)(& len)); + return; +} + +void __e_acsl_globals_init(void) +{ + __gen_e_acsl_literal_string_6 = "uoxX"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_6,sizeof("uoxX")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_6); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_6); + __gen_e_acsl_literal_string_8 = "foo"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_8,sizeof("foo")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_8); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_8); + __gen_e_acsl_literal_string_5 = "fFeEgGaA"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_5, + sizeof("fFeEgGaA")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_5); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_5); + __gen_e_acsl_literal_string_9 = "diouxfFeEgGaAcspn"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_9, + sizeof("diouxfFeEgGaAcspn")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_9); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_9); + __gen_e_acsl_literal_string_7 = "dic"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_7,sizeof("dic")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_7); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_7); + __gen_e_acsl_literal_string = "OK: expected signal at %s\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string, + sizeof("OK: expected signal at %s\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string); + __gen_e_acsl_literal_string_2 = "OK: Expected execution at %s\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_2, + sizeof("OK: Expected execution at %s\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_2); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_2); + __gen_e_acsl_literal_string_4 = "FAIL: Unexpected signal at %s\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_4, + sizeof("FAIL: Unexpected signal at %s\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_4); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_4); + __gen_e_acsl_literal_string_3 = "FAIL: Unexpected execution at %s\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_3, + sizeof("FAIL: Unexpected execution at %s\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_3); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_3); + __e_acsl_store_block((void *)(& __gen_e_acsl_strcpy),(size_t)1); + __e_acsl_full_init((void *)(& __gen_e_acsl_strcpy)); + __e_acsl_store_block((void *)(& __gen_e_acsl_strchr),(size_t)1); + __e_acsl_full_init((void *)(& __gen_e_acsl_strchr)); + __e_acsl_store_block((void *)(& __gen_e_acsl_strlen),(size_t)1); + __e_acsl_full_init((void *)(& __gen_e_acsl_strlen)); + __e_acsl_store_block((void *)(& __gen_e_acsl_exit),(size_t)1); + __e_acsl_full_init((void *)(& __gen_e_acsl_exit)); + __e_acsl_store_block((void *)(& __gen_e_acsl_abort),(size_t)1); + __e_acsl_full_init((void *)(& __gen_e_acsl_abort)); + __e_acsl_store_block((void *)(& test_specifier_application),(size_t)1); + __e_acsl_full_init((void *)(& test_specifier_application)); + __e_acsl_store_block((void *)(& apply_specifier),(size_t)1); + __e_acsl_full_init((void *)(& apply_specifier)); + __e_acsl_store_block((void *)(& valid_specifiers),(size_t)8); + __e_acsl_full_init((void *)(& valid_specifiers)); + __e_acsl_store_block((void *)(& signal_eval),(size_t)1); + __e_acsl_full_init((void *)(& signal_eval)); + __e_acsl_store_block((void *)(& __fc_p_time_tm),(size_t)8); + __e_acsl_full_init((void *)(& __fc_p_time_tm)); + __e_acsl_store_block((void *)(& __fc_time_tm),(size_t)36); + __e_acsl_full_init((void *)(& __fc_time_tm)); + __e_acsl_store_block((void *)(__fc_fds),(size_t)4096); + __e_acsl_full_init((void *)(& __fc_fds)); + __e_acsl_store_block((void *)(& __fc_fds_state),(size_t)4); + __e_acsl_full_init((void *)(& __fc_fds_state)); + __e_acsl_store_block((void *)(& __fc_time),(size_t)4); + __e_acsl_full_init((void *)(& __fc_time)); + __e_acsl_store_block((void *)(& __fc_p_fopen),(size_t)8); + __e_acsl_full_init((void *)(& __fc_p_fopen)); + __e_acsl_store_block((void *)(__fc_fopen),(size_t)4096); + __e_acsl_full_init((void *)(& __fc_fopen)); + __e_acsl_store_block((void *)(& __fc_rand_max),(size_t)8); + __e_acsl_full_init((void *)(& __fc_rand_max)); + return; +} + +int main(int argc, char const **argv) +{ + int __retres; + __e_acsl_memory_init(& argc,(char ***)(& argv),(size_t)8); + __e_acsl_globals_init(); + __e_acsl_store_block((void *)(& __retres),(size_t)4); + __e_acsl_full_init((void *)(& __retres)); + __retres = 0; + __e_acsl_delete_block((void *)(& argv)); + __e_acsl_delete_block((void *)(& argc)); + __e_acsl_delete_block((void *)(& test_specifier_application)); + __e_acsl_delete_block((void *)(& apply_specifier)); + __e_acsl_delete_block((void *)(& valid_specifiers)); + __e_acsl_delete_block((void *)(& signal_eval)); + __e_acsl_delete_block((void *)(& __fc_p_time_tm)); + __e_acsl_delete_block((void *)(& __fc_time_tm)); + __e_acsl_delete_block((void *)(__fc_fds)); + __e_acsl_delete_block((void *)(& __fc_fds_state)); + __e_acsl_delete_block((void *)(& __fc_time)); + __e_acsl_delete_block((void *)(& __fc_p_fopen)); + __e_acsl_delete_block((void *)(__fc_fopen)); + __e_acsl_delete_block((void *)(& __fc_rand_max)); + __e_acsl_delete_block((void *)(& __retres)); + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/format/oracle_ci/printf.0.err.oracle b/src/plugins/e-acsl/tests/format/oracle_ci/printf.0.err.oracle new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/plugins/e-acsl/tests/format/oracle_ci/printf.0.res.oracle b/src/plugins/e-acsl/tests/format/oracle_ci/printf.0.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..ebab565158d2b71aeb27fdb9077718b4788f1a36 --- /dev/null +++ b/src/plugins/e-acsl/tests/format/oracle_ci/printf.0.res.oracle @@ -0,0 +1,83 @@ +[e-acsl] beginning translation. +[e-acsl] warning: annotating undefined function `abort': + the generated program may miss memory instrumentation + if there are memory-related annotations. +[e-acsl] warning: annotating undefined function `exit': + the generated program may miss memory instrumentation + if there are memory-related annotations. +[e-acsl] warning: annotating undefined function `strlen': + the generated program may miss memory instrumentation + if there are memory-related annotations. +[e-acsl] warning: annotating undefined function `strchr': + the generated program may miss memory instrumentation + if there are memory-related annotations. +[e-acsl] warning: annotating undefined function `strcpy': + the generated program may miss memory instrumentation + if there are memory-related annotations. +FRAMAC_SHARE/libc/stdio.h:150:[kernel] warning: Neither code nor specification for function printf, generating default assigns from the prototype +FRAMAC_SHARE/libc/unistd.h:785:[kernel] warning: Neither code nor specification for function fork, generating default assigns from the prototype +FRAMAC_SHARE/libc/sys/wait.h:57:[kernel] warning: Neither code nor specification for function waitpid, generating default assigns from the prototype +:0:[kernel] warning: Neither code nor specification for function __fc_vla_free, generating default assigns from the prototype +:0:[kernel] warning: Neither code nor specification for function __fc_vla_alloc, generating default assigns from the prototype +FRAMAC_SHARE/libc/string.h:221:[e-acsl] warning: E-ACSL construct `logic function application' is not yet supported. + Ignoring annotation. +FRAMAC_SHARE/libc/string.h:222:[e-acsl] warning: E-ACSL construct `trange' is not yet supported. Ignoring annotation. +FRAMAC_SHARE/libc/string.h:224:[e-acsl] warning: E-ACSL construct `\separated' is not yet supported. Ignoring annotation. +FRAMAC_SHARE/libc/string.h:224:[e-acsl] warning: E-ACSL construct `assigns clause in behavior' is not yet supported. + Ignoring annotation. +FRAMAC_SHARE/libc/string.h:227:[e-acsl] warning: E-ACSL construct `logic function returning an integer' is not yet supported. + Ignoring annotation. +FRAMAC_SHARE/libc/string.h:227:[e-acsl] warning: E-ACSL construct `assigns clause in behavior' is not yet supported. + Ignoring annotation. +FRAMAC_SHARE/libc/string.h:124:[e-acsl] warning: E-ACSL construct `logic function application' is not yet supported. + Ignoring annotation. +FRAMAC_SHARE/libc/string.h:127:[e-acsl] warning: E-ACSL construct `user-defined logic type' is not yet supported. + Ignoring annotation. +FRAMAC_SHARE/libc/string.h:134:[e-acsl] warning: E-ACSL construct `user-defined logic type' is not yet supported. + Ignoring annotation. +FRAMAC_SHARE/libc/string.h:92:[e-acsl] warning: E-ACSL construct `logic function application' is not yet supported. + Ignoring annotation. +FRAMAC_SHARE/libc/string.h:92:[e-acsl] warning: E-ACSL construct `assigns clause in behavior' is not yet supported. + Ignoring annotation. +FRAMAC_SHARE/libc/string.h:94:[e-acsl] warning: E-ACSL construct `logic function returning an integer' is not yet supported. + Ignoring annotation. +FRAMAC_SHARE/libc/string.h:94:[e-acsl] warning: E-ACSL construct `assigns clause in behavior' is not yet supported. + Ignoring annotation. +FRAMAC_SHARE/libc/stdlib.h:396:[e-acsl] warning: E-ACSL construct `assigns clause in behavior' is not yet supported. + Ignoring annotation. +[e-acsl] translation done in project "e-acsl". +[value] Analyzing a complete application starting at main +[value] Computing initial state +[value] Initial state computed +[value:initial-state] Values of globals at initialization + __fc_rand_max ∈ {32767} + __fc_heap_status ∈ [--..--] + __e_acsl_init ∈ [--..--] + __fc_fopen[0..511] ∈ {0} + __fc_p_fopen ∈ {{ &__fc_fopen[0] }} + __e_acsl_internal_heap ∈ [--..--] + __e_acsl_heap_allocation_size ∈ [--..--] + __e_acsl_math_HUGE_VAL ∈ [-1.79769313486e+308 .. 1.79769313486e+308] + __e_acsl_math_HUGE_VALF ∈ [-3.40282346639e+38 .. 3.40282346639e+38] + __e_acsl_math_INFINITY ∈ [-1.79769313486e+308 .. 1.79769313486e+308] + __fc_time ∈ [--..--] + __fc_fds_state ∈ [--..--] + __fc_fds[0..1023] ∈ {0} + __fc_time_tm ∈ {0} + __fc_p_time_tm ∈ {{ &__fc_time_tm }} + valid_specifiers ∈ {{ "diouxfFeEgGaAcspn" }} + __gen_e_acsl_literal_string ∈ {0} + __gen_e_acsl_literal_string_2 ∈ {0} + __gen_e_acsl_literal_string_3 ∈ {0} + __gen_e_acsl_literal_string_4 ∈ {0} + __gen_e_acsl_literal_string_5 ∈ {0} + __gen_e_acsl_literal_string_6 ∈ {0} + __gen_e_acsl_literal_string_7 ∈ {0} + __gen_e_acsl_literal_string_8 ∈ {0} +[value] using specification for function __e_acsl_memory_init +[value] using specification for function __e_acsl_store_block +[value] using specification for function __e_acsl_full_init +[value] using specification for function __e_acsl_mark_readonly +[value] using specification for function __e_acsl_delete_block +[value] using specification for function __e_acsl_memory_clean +[value] done for function main diff --git a/src/plugins/e-acsl/tests/format/oracle_ci/printf.1.err.oracle b/src/plugins/e-acsl/tests/format/oracle_ci/printf.1.err.oracle new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/plugins/e-acsl/tests/format/oracle_ci/printf.1.res.oracle b/src/plugins/e-acsl/tests/format/oracle_ci/printf.1.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..c3ff63dd0ce700cb2c8f81b5d3966c411b35d835 --- /dev/null +++ b/src/plugins/e-acsl/tests/format/oracle_ci/printf.1.res.oracle @@ -0,0 +1,84 @@ +[e-acsl] beginning translation. +[e-acsl] warning: annotating undefined function `abort': + the generated program may miss memory instrumentation + if there are memory-related annotations. +[e-acsl] warning: annotating undefined function `exit': + the generated program may miss memory instrumentation + if there are memory-related annotations. +[e-acsl] warning: annotating undefined function `strlen': + the generated program may miss memory instrumentation + if there are memory-related annotations. +[e-acsl] warning: annotating undefined function `strchr': + the generated program may miss memory instrumentation + if there are memory-related annotations. +[e-acsl] warning: annotating undefined function `strcpy': + the generated program may miss memory instrumentation + if there are memory-related annotations. +FRAMAC_SHARE/libc/stdio.h:150:[kernel] warning: Neither code nor specification for function printf, generating default assigns from the prototype +FRAMAC_SHARE/libc/unistd.h:785:[kernel] warning: Neither code nor specification for function fork, generating default assigns from the prototype +FRAMAC_SHARE/libc/sys/wait.h:57:[kernel] warning: Neither code nor specification for function waitpid, generating default assigns from the prototype +:0:[kernel] warning: Neither code nor specification for function __fc_vla_free, generating default assigns from the prototype +:0:[kernel] warning: Neither code nor specification for function __fc_vla_alloc, generating default assigns from the prototype +FRAMAC_SHARE/libc/string.h:221:[e-acsl] warning: E-ACSL construct `logic function application' is not yet supported. + Ignoring annotation. +FRAMAC_SHARE/libc/string.h:222:[e-acsl] warning: E-ACSL construct `trange' is not yet supported. Ignoring annotation. +FRAMAC_SHARE/libc/string.h:224:[e-acsl] warning: E-ACSL construct `\separated' is not yet supported. Ignoring annotation. +FRAMAC_SHARE/libc/string.h:224:[e-acsl] warning: E-ACSL construct `assigns clause in behavior' is not yet supported. + Ignoring annotation. +FRAMAC_SHARE/libc/string.h:227:[e-acsl] warning: E-ACSL construct `logic function returning an integer' is not yet supported. + Ignoring annotation. +FRAMAC_SHARE/libc/string.h:227:[e-acsl] warning: E-ACSL construct `assigns clause in behavior' is not yet supported. + Ignoring annotation. +FRAMAC_SHARE/libc/string.h:124:[e-acsl] warning: E-ACSL construct `logic function application' is not yet supported. + Ignoring annotation. +FRAMAC_SHARE/libc/string.h:127:[e-acsl] warning: E-ACSL construct `user-defined logic type' is not yet supported. + Ignoring annotation. +FRAMAC_SHARE/libc/string.h:134:[e-acsl] warning: E-ACSL construct `user-defined logic type' is not yet supported. + Ignoring annotation. +FRAMAC_SHARE/libc/string.h:92:[e-acsl] warning: E-ACSL construct `logic function application' is not yet supported. + Ignoring annotation. +FRAMAC_SHARE/libc/string.h:92:[e-acsl] warning: E-ACSL construct `assigns clause in behavior' is not yet supported. + Ignoring annotation. +FRAMAC_SHARE/libc/string.h:94:[e-acsl] warning: E-ACSL construct `logic function returning an integer' is not yet supported. + Ignoring annotation. +FRAMAC_SHARE/libc/string.h:94:[e-acsl] warning: E-ACSL construct `assigns clause in behavior' is not yet supported. + Ignoring annotation. +FRAMAC_SHARE/libc/stdlib.h:396:[e-acsl] warning: E-ACSL construct `assigns clause in behavior' is not yet supported. + Ignoring annotation. +[e-acsl] translation done in project "e-acsl". +[value] Analyzing a complete application starting at main +[value] Computing initial state +[value] Initial state computed +[value:initial-state] Values of globals at initialization + __fc_rand_max ∈ {32767} + __fc_heap_status ∈ [--..--] + __e_acsl_init ∈ [--..--] + __fc_fopen[0..511] ∈ {0} + __fc_p_fopen ∈ {{ &__fc_fopen[0] }} + __e_acsl_internal_heap ∈ [--..--] + __e_acsl_heap_allocation_size ∈ [--..--] + __e_acsl_math_HUGE_VAL ∈ [-1.79769313486e+308 .. 1.79769313486e+308] + __e_acsl_math_HUGE_VALF ∈ [-3.40282346639e+38 .. 3.40282346639e+38] + __e_acsl_math_INFINITY ∈ [-1.79769313486e+308 .. 1.79769313486e+308] + __fc_time ∈ [--..--] + __fc_fds_state ∈ [--..--] + __fc_fds[0..1023] ∈ {0} + __fc_time_tm ∈ {0} + __fc_p_time_tm ∈ {{ &__fc_time_tm }} + valid_specifiers ∈ {{ "diouxfFeEgGaAcspn" }} + __gen_e_acsl_literal_string ∈ {0} + __gen_e_acsl_literal_string_2 ∈ {0} + __gen_e_acsl_literal_string_3 ∈ {0} + __gen_e_acsl_literal_string_4 ∈ {0} + __gen_e_acsl_literal_string_5 ∈ {0} + __gen_e_acsl_literal_string_6 ∈ {0} + __gen_e_acsl_literal_string_7 ∈ {0} + __gen_e_acsl_literal_string_8 ∈ {0} + __gen_e_acsl_literal_string_9 ∈ {0} +[value] using specification for function __e_acsl_memory_init +[value] using specification for function __e_acsl_store_block +[value] using specification for function __e_acsl_full_init +[value] using specification for function __e_acsl_mark_readonly +[value] using specification for function __e_acsl_delete_block +[value] using specification for function __e_acsl_memory_clean +[value] done for function main diff --git a/src/plugins/e-acsl/tests/format/oracle_ci/printf.err.oracle b/src/plugins/e-acsl/tests/format/oracle_ci/printf.err.oracle new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/plugins/e-acsl/tests/format/oracle_ci/printf.res.oracle b/src/plugins/e-acsl/tests/format/oracle_ci/printf.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..61c88433a84b1f2c0017dcf6b44e3cf8e7a45164 --- /dev/null +++ b/src/plugins/e-acsl/tests/format/oracle_ci/printf.res.oracle @@ -0,0 +1,459 @@ +[kernel:parser:decimal-float] tests/format/printf.c:88: Warning: + Floating-point constant 0.2 is not represented exactly. Will use 0x1.999999999999ap-3. + (warn-once: no further messages from category 'parser:decimal-float' will be emitted) +[e-acsl] beginning translation. +[e-acsl] Warning: annotating undefined function `abort': + the generated program may miss memory instrumentation + if there are memory-related annotations. +[e-acsl] Warning: annotating undefined function `exit': + the generated program may miss memory instrumentation + if there are memory-related annotations. +[e-acsl] Warning: annotating undefined function `strlen': + the generated program may miss memory instrumentation + if there are memory-related annotations. +[e-acsl] Warning: annotating undefined function `strchr': + the generated program may miss memory instrumentation + if there are memory-related annotations. +[e-acsl] Warning: annotating undefined function `strcpy': + the generated program may miss memory instrumentation + if there are memory-related annotations. +[e-acsl] FRAMAC_SHARE/libc/string.h:327: Warning: + E-ACSL construct `logic functions with labels' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/string.h:328: Warning: + E-ACSL construct `logic function returning an integer' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/string.h:330: Warning: + E-ACSL construct `\separated' is not yet supported. Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/string.h:330: Warning: + E-ACSL construct `assigns clause in behavior' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/string.h:333: Warning: + E-ACSL construct `logic functions performing read accesses' + is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/string.h:143: Warning: + E-ACSL construct `logic functions with labels' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/string.h:157: Warning: + E-ACSL construct `assigns clause in behavior' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/string.h:146: Warning: + E-ACSL construct `logic functions performing read accesses' + is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/string.h:146: Warning: + E-ACSL construct `logic functions performing read accesses' + is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/string.h:153: Warning: + E-ACSL construct `logic functions performing read accesses' + is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/string.h:111: Warning: + E-ACSL construct `logic functions with labels' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/string.h:111: Warning: + E-ACSL construct `assigns clause in behavior' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/string.h:113: Warning: + E-ACSL construct `logic functions performing read accesses' + is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/string.h:113: Warning: + E-ACSL construct `assigns clause in behavior' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/stdlib.h:406: Warning: + E-ACSL construct `assigns clause in behavior' is not yet supported. + Ignoring annotation. +[e-acsl] translation done in project "e-acsl". +[value] Analyzing a complete application starting at main +[value] Computing initial state +[value] Initial state computed +[value:initial-state] Values of globals at initialization + __e_acsl_init ∈ [--..--] + __e_acsl_heap_allocation_size ∈ [--..--] + __e_acsl_math_HUGE_VAL ∈ [-1.79769313486e+308 .. 1.79769313486e+308] + __e_acsl_math_HUGE_VALF ∈ [-3.40282346639e+38 .. 3.40282346639e+38] + __e_acsl_math_INFINITY ∈ [-1.79769313486e+308 .. 1.79769313486e+308] + testno ∈ {0} + valid_specifiers ∈ {{ "diouxfFeEgGaAcspn" }} + __gen_e_acsl_literal_string ∈ {0} + __gen_e_acsl_literal_string_2 ∈ {0} + __gen_e_acsl_literal_string_3 ∈ {0} + __gen_e_acsl_literal_string_4 ∈ {0} + __gen_e_acsl_literal_string_5 ∈ {0} + __gen_e_acsl_literal_string_6 ∈ {0} + __gen_e_acsl_literal_string_7 ∈ {0} + __gen_e_acsl_literal_string_8 ∈ {0} + __gen_e_acsl_literal_string_9 ∈ {0} + __gen_e_acsl_literal_string_10 ∈ {0} + __gen_e_acsl_literal_string_11 ∈ {0} + __gen_e_acsl_literal_string_12 ∈ {0} + __gen_e_acsl_literal_string_13 ∈ {0} + __gen_e_acsl_literal_string_14 ∈ {0} + __gen_e_acsl_literal_string_15 ∈ {0} + __gen_e_acsl_literal_string_16 ∈ {0} + __gen_e_acsl_literal_string_17 ∈ {0} + __gen_e_acsl_literal_string_18 ∈ {0} + __gen_e_acsl_literal_string_19 ∈ {0} + __gen_e_acsl_literal_string_20 ∈ {0} + __gen_e_acsl_literal_string_21 ∈ {0} + __gen_e_acsl_literal_string_22 ∈ {0} + __gen_e_acsl_literal_string_23 ∈ {0} + __gen_e_acsl_literal_string_24 ∈ {0} + __gen_e_acsl_literal_string_25 ∈ {0} + __gen_e_acsl_literal_string_26 ∈ {0} + __gen_e_acsl_literal_string_27 ∈ {0} + __gen_e_acsl_literal_string_28 ∈ {0} + __gen_e_acsl_literal_string_29 ∈ {0} + __gen_e_acsl_literal_string_30 ∈ {0} + __gen_e_acsl_literal_string_31 ∈ {0} + __gen_e_acsl_literal_string_32 ∈ {0} + __gen_e_acsl_literal_string_33 ∈ {0} + __gen_e_acsl_literal_string_34 ∈ {0} + __gen_e_acsl_literal_string_35 ∈ {0} + __gen_e_acsl_literal_string_36 ∈ {0} + __gen_e_acsl_literal_string_37 ∈ {0} + __gen_e_acsl_literal_string_38 ∈ {0} + __gen_e_acsl_literal_string_39 ∈ {0} + __gen_e_acsl_literal_string_40 ∈ {0} + __gen_e_acsl_literal_string_41 ∈ {0} + __gen_e_acsl_literal_string_42 ∈ {0} + __gen_e_acsl_literal_string_43 ∈ {0} + __gen_e_acsl_literal_string_44 ∈ {0} + __gen_e_acsl_literal_string_45 ∈ {0} + __gen_e_acsl_literal_string_46 ∈ {0} + __gen_e_acsl_literal_string_47 ∈ {0} + __gen_e_acsl_literal_string_48 ∈ {0} + __gen_e_acsl_literal_string_49 ∈ {0} + __gen_e_acsl_literal_string_50 ∈ {0} + __gen_e_acsl_literal_string_51 ∈ {0} + __gen_e_acsl_literal_string_52 ∈ {0} + __gen_e_acsl_literal_string_53 ∈ {0} + __gen_e_acsl_literal_string_54 ∈ {0} + __gen_e_acsl_literal_string_55 ∈ {0} + __gen_e_acsl_literal_string_56 ∈ {0} + __gen_e_acsl_literal_string_57 ∈ {0} + __gen_e_acsl_literal_string_58 ∈ {0} + __gen_e_acsl_literal_string_59 ∈ {0} + __gen_e_acsl_literal_string_60 ∈ {0} + __gen_e_acsl_literal_string_61 ∈ {0} + __gen_e_acsl_literal_string_62 ∈ {0} + __gen_e_acsl_literal_string_63 ∈ {0} + __gen_e_acsl_literal_string_64 ∈ {0} + __gen_e_acsl_literal_string_65 ∈ {0} + __gen_e_acsl_literal_string_66 ∈ {0} + __gen_e_acsl_literal_string_67 ∈ {0} + __gen_e_acsl_literal_string_68 ∈ {0} + __gen_e_acsl_literal_string_69 ∈ {0} + __gen_e_acsl_literal_string_70 ∈ {0} + __gen_e_acsl_literal_string_71 ∈ {0} + __gen_e_acsl_literal_string_72 ∈ {0} + __gen_e_acsl_literal_string_73 ∈ {0} + __gen_e_acsl_literal_string_74 ∈ {0} + __gen_e_acsl_literal_string_75 ∈ {0} + __gen_e_acsl_literal_string_76 ∈ {0} + __gen_e_acsl_literal_string_77 ∈ {0} + __gen_e_acsl_literal_string_78 ∈ {0} + __gen_e_acsl_literal_string_79 ∈ {0} + __gen_e_acsl_literal_string_80 ∈ {0} + __gen_e_acsl_literal_string_81 ∈ {0} + __gen_e_acsl_literal_string_82 ∈ {0} + __gen_e_acsl_literal_string_83 ∈ {0} + __gen_e_acsl_literal_string_84 ∈ {0} + __gen_e_acsl_literal_string_85 ∈ {0} + __gen_e_acsl_literal_string_86 ∈ {0} + __gen_e_acsl_literal_string_87 ∈ {0} + __gen_e_acsl_literal_string_88 ∈ {0} + __gen_e_acsl_literal_string_89 ∈ {0} + __gen_e_acsl_literal_string_90 ∈ {0} + __gen_e_acsl_literal_string_91 ∈ {0} + __gen_e_acsl_literal_string_92 ∈ {0} + __gen_e_acsl_literal_string_93 ∈ {0} + __gen_e_acsl_literal_string_94 ∈ {0} + __gen_e_acsl_literal_string_95 ∈ {0} + __gen_e_acsl_literal_string_96 ∈ {0} + __gen_e_acsl_literal_string_97 ∈ {0} + __gen_e_acsl_literal_string_98 ∈ {0} + __gen_e_acsl_literal_string_99 ∈ {0} + __gen_e_acsl_literal_string_100 ∈ {0} + __gen_e_acsl_literal_string_101 ∈ {0} + __gen_e_acsl_literal_string_102 ∈ {0} + __gen_e_acsl_literal_string_103 ∈ {0} + __gen_e_acsl_literal_string_104 ∈ {0} + __gen_e_acsl_literal_string_105 ∈ {0} + __gen_e_acsl_literal_string_106 ∈ {0} + __gen_e_acsl_literal_string_107 ∈ {0} + __gen_e_acsl_literal_string_108 ∈ {0} + __gen_e_acsl_literal_string_109 ∈ {0} + __gen_e_acsl_literal_string_110 ∈ {0} + __gen_e_acsl_literal_string_111 ∈ {0} + __gen_e_acsl_literal_string_112 ∈ {0} + __gen_e_acsl_literal_string_113 ∈ {0} + __gen_e_acsl_literal_string_114 ∈ {0} + __gen_e_acsl_literal_string_115 ∈ {0} + __gen_e_acsl_literal_string_116 ∈ {0} + __gen_e_acsl_literal_string_117 ∈ {0} + __gen_e_acsl_literal_string_118 ∈ {0} + __gen_e_acsl_literal_string_119 ∈ {0} + __gen_e_acsl_literal_string_120 ∈ {0} + __gen_e_acsl_literal_string_121 ∈ {0} + __gen_e_acsl_literal_string_122 ∈ {0} + __gen_e_acsl_literal_string_123 ∈ {0} + __gen_e_acsl_literal_string_124 ∈ {0} + __gen_e_acsl_literal_string_125 ∈ {0} + __gen_e_acsl_literal_string_126 ∈ {0} + __gen_e_acsl_literal_string_127 ∈ {0} + __gen_e_acsl_literal_string_128 ∈ {0} + __gen_e_acsl_literal_string_129 ∈ {0} + __gen_e_acsl_literal_string_130 ∈ {0} + __gen_e_acsl_literal_string_131 ∈ {0} + __gen_e_acsl_literal_string_132 ∈ {0} + __gen_e_acsl_literal_string_133 ∈ {0} + __gen_e_acsl_literal_string_134 ∈ {0} + __gen_e_acsl_literal_string_135 ∈ {0} + __gen_e_acsl_literal_string_136 ∈ {0} + __gen_e_acsl_literal_string_137 ∈ {0} + __gen_e_acsl_literal_string_138 ∈ {0} + __gen_e_acsl_literal_string_139 ∈ {0} + __gen_e_acsl_literal_string_140 ∈ {0} + __gen_e_acsl_literal_string_141 ∈ {0} + __gen_e_acsl_literal_string_142 ∈ {0} + __gen_e_acsl_literal_string_143 ∈ {0} + __gen_e_acsl_literal_string_144 ∈ {0} + __gen_e_acsl_literal_string_145 ∈ {0} + __gen_e_acsl_literal_string_146 ∈ {0} + __gen_e_acsl_literal_string_147 ∈ {0} + __gen_e_acsl_literal_string_148 ∈ {0} + __gen_e_acsl_literal_string_149 ∈ {0} + __gen_e_acsl_literal_string_150 ∈ {0} + __gen_e_acsl_literal_string_151 ∈ {0} + __gen_e_acsl_literal_string_152 ∈ {0} + __gen_e_acsl_literal_string_153 ∈ {0} + __gen_e_acsl_literal_string_154 ∈ {0} + __gen_e_acsl_literal_string_155 ∈ {0} + __gen_e_acsl_literal_string_156 ∈ {0} + __gen_e_acsl_literal_string_157 ∈ {0} + __gen_e_acsl_literal_string_158 ∈ {0} + __gen_e_acsl_literal_string_159 ∈ {0} + __gen_e_acsl_literal_string_160 ∈ {0} + __gen_e_acsl_literal_string_161 ∈ {0} + __gen_e_acsl_literal_string_162 ∈ {0} + __gen_e_acsl_literal_string_163 ∈ {0} + __gen_e_acsl_literal_string_164 ∈ {0} + __gen_e_acsl_literal_string_165 ∈ {0} + __gen_e_acsl_literal_string_166 ∈ {0} + __gen_e_acsl_literal_string_167 ∈ {0} + __gen_e_acsl_literal_string_168 ∈ {0} + __gen_e_acsl_literal_string_169 ∈ {0} + __gen_e_acsl_literal_string_170 ∈ {0} + __gen_e_acsl_literal_string_171 ∈ {0} + __gen_e_acsl_literal_string_172 ∈ {0} + __gen_e_acsl_literal_string_173 ∈ {0} + __gen_e_acsl_literal_string_174 ∈ {0} + __gen_e_acsl_literal_string_175 ∈ {0} + __gen_e_acsl_literal_string_176 ∈ {0} + __gen_e_acsl_literal_string_177 ∈ {0} + __gen_e_acsl_literal_string_178 ∈ {0} + __gen_e_acsl_literal_string_179 ∈ {0} + __gen_e_acsl_literal_string_180 ∈ {0} + __gen_e_acsl_literal_string_181 ∈ {0} + __gen_e_acsl_literal_string_182 ∈ {0} + __gen_e_acsl_literal_string_183 ∈ {0} + __gen_e_acsl_literal_string_184 ∈ {0} + __gen_e_acsl_literal_string_185 ∈ {0} + __gen_e_acsl_literal_string_186 ∈ {0} + __gen_e_acsl_literal_string_187 ∈ {0} + __gen_e_acsl_literal_string_188 ∈ {0} + __gen_e_acsl_literal_string_189 ∈ {0} + __gen_e_acsl_literal_string_190 ∈ {0} + __gen_e_acsl_literal_string_191 ∈ {0} + __gen_e_acsl_literal_string_192 ∈ {0} + __gen_e_acsl_literal_string_193 ∈ {0} + __gen_e_acsl_literal_string_194 ∈ {0} + __gen_e_acsl_literal_string_195 ∈ {0} + __gen_e_acsl_literal_string_196 ∈ {0} + __gen_e_acsl_literal_string_197 ∈ {0} + __gen_e_acsl_literal_string_198 ∈ {0} + __gen_e_acsl_literal_string_199 ∈ {0} + __gen_e_acsl_literal_string_200 ∈ {0} + __gen_e_acsl_literal_string_201 ∈ {0} + __gen_e_acsl_literal_string_202 ∈ {0} + __gen_e_acsl_literal_string_203 ∈ {0} + __gen_e_acsl_literal_string_204 ∈ {0} + __gen_e_acsl_literal_string_205 ∈ {0} + __gen_e_acsl_literal_string_206 ∈ {0} + __gen_e_acsl_literal_string_207 ∈ {0} + __gen_e_acsl_literal_string_208 ∈ {0} + __gen_e_acsl_literal_string_209 ∈ {0} + __gen_e_acsl_literal_string_210 ∈ {0} + __gen_e_acsl_literal_string_211 ∈ {0} + __gen_e_acsl_literal_string_212 ∈ {0} + __gen_e_acsl_literal_string_213 ∈ {0} + __gen_e_acsl_literal_string_214 ∈ {0} + __gen_e_acsl_literal_string_215 ∈ {0} + __gen_e_acsl_literal_string_216 ∈ {0} + __gen_e_acsl_literal_string_217 ∈ {0} + __gen_e_acsl_literal_string_218 ∈ {0} + __gen_e_acsl_literal_string_219 ∈ {0} + __gen_e_acsl_literal_string_220 ∈ {0} + __gen_e_acsl_literal_string_221 ∈ {0} + __gen_e_acsl_literal_string_222 ∈ {0} + __gen_e_acsl_literal_string_223 ∈ {0} + __gen_e_acsl_literal_string_224 ∈ {0} + __gen_e_acsl_literal_string_225 ∈ {0} + __gen_e_acsl_literal_string_226 ∈ {0} + __gen_e_acsl_literal_string_227 ∈ {0} + __gen_e_acsl_literal_string_228 ∈ {0} + __gen_e_acsl_literal_string_229 ∈ {0} + __gen_e_acsl_literal_string_230 ∈ {0} + __gen_e_acsl_literal_string_231 ∈ {0} + __gen_e_acsl_literal_string_232 ∈ {0} + __gen_e_acsl_literal_string_233 ∈ {0} + __gen_e_acsl_literal_string_234 ∈ {0} + __gen_e_acsl_literal_string_235 ∈ {0} + __gen_e_acsl_literal_string_236 ∈ {0} + __gen_e_acsl_literal_string_237 ∈ {0} + __gen_e_acsl_literal_string_238 ∈ {0} + __gen_e_acsl_literal_string_239 ∈ {0} + __gen_e_acsl_literal_string_240 ∈ {0} + __gen_e_acsl_literal_string_241 ∈ {0} + __gen_e_acsl_literal_string_242 ∈ {0} + __gen_e_acsl_literal_string_243 ∈ {0} + __gen_e_acsl_literal_string_244 ∈ {0} + __gen_e_acsl_literal_string_245 ∈ {0} + __gen_e_acsl_literal_string_246 ∈ {0} + __gen_e_acsl_literal_string_247 ∈ {0} + __gen_e_acsl_literal_string_248 ∈ {0} + __gen_e_acsl_literal_string_249 ∈ {0} + __gen_e_acsl_literal_string_250 ∈ {0} + __gen_e_acsl_literal_string_251 ∈ {0} + __gen_e_acsl_literal_string_252 ∈ {0} + __gen_e_acsl_literal_string_253 ∈ {0} + __gen_e_acsl_literal_string_254 ∈ {0} + __gen_e_acsl_literal_string_255 ∈ {0} + __gen_e_acsl_literal_string_256 ∈ {0} + __gen_e_acsl_literal_string_257 ∈ {0} + __gen_e_acsl_literal_string_258 ∈ {0} + __gen_e_acsl_literal_string_259 ∈ {0} + __gen_e_acsl_literal_string_260 ∈ {0} + __gen_e_acsl_literal_string_261 ∈ {0} + __gen_e_acsl_literal_string_262 ∈ {0} + __gen_e_acsl_literal_string_263 ∈ {0} + __gen_e_acsl_literal_string_264 ∈ {0} + __gen_e_acsl_literal_string_265 ∈ {0} + __gen_e_acsl_literal_string_266 ∈ {0} + __gen_e_acsl_literal_string_267 ∈ {0} + __gen_e_acsl_literal_string_268 ∈ {0} + __gen_e_acsl_literal_string_269 ∈ {0} + __gen_e_acsl_literal_string_270 ∈ {0} + __gen_e_acsl_literal_string_271 ∈ {0} + __gen_e_acsl_literal_string_272 ∈ {0} + __gen_e_acsl_literal_string_273 ∈ {0} + __gen_e_acsl_literal_string_274 ∈ {0} + __gen_e_acsl_literal_string_275 ∈ {0} + __gen_e_acsl_literal_string_276 ∈ {0} + __gen_e_acsl_literal_string_277 ∈ {0} + __gen_e_acsl_literal_string_278 ∈ {0} + __gen_e_acsl_literal_string_279 ∈ {0} + __gen_e_acsl_literal_string_280 ∈ {0} + __gen_e_acsl_literal_string_281 ∈ {0} + __gen_e_acsl_literal_string_282 ∈ {0} + __gen_e_acsl_literal_string_283 ∈ {0} + __gen_e_acsl_literal_string_284 ∈ {0} + __gen_e_acsl_literal_string_285 ∈ {0} + __gen_e_acsl_literal_string_286 ∈ {0} + __gen_e_acsl_literal_string_287 ∈ {0} + __gen_e_acsl_literal_string_288 ∈ {0} + __gen_e_acsl_literal_string_289 ∈ {0} + __gen_e_acsl_literal_string_290 ∈ {0} + __gen_e_acsl_literal_string_291 ∈ {0} + __gen_e_acsl_literal_string_292 ∈ {0} + __gen_e_acsl_literal_string_293 ∈ {0} + __gen_e_acsl_literal_string_294 ∈ {0} + __gen_e_acsl_literal_string_295 ∈ {0} + __gen_e_acsl_literal_string_296 ∈ {0} + __gen_e_acsl_literal_string_297 ∈ {0} + __gen_e_acsl_literal_string_298 ∈ {0} + __gen_e_acsl_literal_string_299 ∈ {0} + __gen_e_acsl_literal_string_300 ∈ {0} + __gen_e_acsl_literal_string_301 ∈ {0} + __gen_e_acsl_literal_string_302 ∈ {0} + __gen_e_acsl_literal_string_303 ∈ {0} + __gen_e_acsl_literal_string_304 ∈ {0} + __gen_e_acsl_literal_string_305 ∈ {0} + __gen_e_acsl_literal_string_306 ∈ {0} + __gen_e_acsl_literal_string_307 ∈ {0} + __gen_e_acsl_literal_string_308 ∈ {0} + __gen_e_acsl_literal_string_309 ∈ {0} + __gen_e_acsl_literal_string_310 ∈ {0} + __gen_e_acsl_literal_string_311 ∈ {0} + __gen_e_acsl_literal_string_312 ∈ {0} + __gen_e_acsl_literal_string_313 ∈ {0} + __gen_e_acsl_literal_string_314 ∈ {0} + __gen_e_acsl_literal_string_315 ∈ {0} + __gen_e_acsl_literal_string_316 ∈ {0} + __gen_e_acsl_literal_string_317 ∈ {0} + __gen_e_acsl_literal_string_318 ∈ {0} + __gen_e_acsl_literal_string_319 ∈ {0} + __gen_e_acsl_literal_string_320 ∈ {0} + __gen_e_acsl_literal_string_321 ∈ {0} + __gen_e_acsl_literal_string_322 ∈ {0} + __gen_e_acsl_literal_string_323 ∈ {0} + __gen_e_acsl_literal_string_324 ∈ {0} + __gen_e_acsl_literal_string_325 ∈ {0} + __gen_e_acsl_literal_string_326 ∈ {0} + __gen_e_acsl_literal_string_327 ∈ {0} + __gen_e_acsl_literal_string_328 ∈ {0} + __gen_e_acsl_literal_string_329 ∈ {0} + __gen_e_acsl_literal_string_330 ∈ {0} + __gen_e_acsl_literal_string_331 ∈ {0} + __gen_e_acsl_literal_string_332 ∈ {0} + __gen_e_acsl_literal_string_333 ∈ {0} + __gen_e_acsl_literal_string_334 ∈ {0} + __gen_e_acsl_literal_string_335 ∈ {0} + __gen_e_acsl_literal_string_336 ∈ {0} + __gen_e_acsl_literal_string_337 ∈ {0} + __gen_e_acsl_literal_string_338 ∈ {0} +[value] using specification for function __e_acsl_memory_init +[value] using specification for function __e_acsl_store_block +[value] using specification for function __e_acsl_full_init +[value] using specification for function __e_acsl_mark_readonly +[value] using specification for function fork +[value] using specification for function __e_acsl_builtin_printf +[value] using specification for function exit +[value] using specification for function waitpid +[value:alarm] tests/format/printf.c:179: Warning: + accessing uninitialized left-value. assert \initialized(&process_status); +[value] using specification for function __e_acsl_delete_block +[value:alarm] tests/format/printf.c:182: Warning: + accessing uninitialized left-value. assert \initialized(&process_status_0); +[value:alarm] tests/format/printf.c:185: Warning: + accessing uninitialized left-value. assert \initialized(&process_status_1); +[value:alarm] tests/format/printf.c:188: Warning: + accessing uninitialized left-value. assert \initialized(&process_status_2); +[value] using specification for function __e_acsl_initialize +[value:alarm] tests/format/printf.c:193: Warning: + accessing uninitialized left-value. assert \initialized(&process_status_3); +[value:alarm] tests/format/printf.c:196: Warning: + accessing uninitialized left-value. assert \initialized(&process_status_4); +[value:alarm] tests/format/printf.c:198: Warning: + accessing uninitialized left-value. assert \initialized(&process_status_5); +[value:alarm] tests/format/printf.c:200: Warning: + accessing uninitialized left-value. assert \initialized(&process_status_6); +[value:alarm] tests/format/printf.c:203: Warning: + accessing uninitialized left-value. assert \initialized(&process_status_7); +[value:alarm] tests/format/printf.c:205: Warning: + accessing uninitialized left-value. assert \initialized(&process_status_8); +[value] using specification for function __gmpz_init_set_si +[value] using specification for function __gmpz_init_set_ui +[value] using specification for function __gmpz_cmp +[value] using specification for function __gmpz_clear +[value] using specification for function __e_acsl_assert +[value:alarm] tests/format/printf.c:50: Warning: + function __e_acsl_assert: precondition got status unknown. +[value] using specification for function __builtin_alloca +[value:alarm] tests/format/printf.c:51: Warning: + function __gen_e_acsl_strcpy: precondition 'room_string' got status invalid. +[value] done for function main diff --git a/src/plugins/e-acsl/tests/format/oracle_dev/fprintf.res.oracle b/src/plugins/e-acsl/tests/format/oracle_dev/fprintf.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..b26c0b6174b2a72251653d396860c71ab5ba9664 --- /dev/null +++ b/src/plugins/e-acsl/tests/format/oracle_dev/fprintf.res.oracle @@ -0,0 +1,4 @@ +[kernel] User Error: cannot load plug-in 'frama-c-e_acsl': cannot load module + Details: error loading shared library: Dynlink.Error (Dynlink.Cannot_open_dll "Failure(\"./top/E_ACSL.cmxs: cannot open shared object file: No such file or directory\")") +[kernel] User Error: Deferred error message was emitted during execution. See above messages for more information. +[kernel] Frama-C aborted: invalid user input. diff --git a/src/plugins/e-acsl/tests/format/oracle_dev/printf.err.oracle b/src/plugins/e-acsl/tests/format/oracle_dev/printf.err.oracle new file mode 100644 index 0000000000000000000000000000000000000000..60a52ebd46155be20698d85e73b20037d3e455ed --- /dev/null +++ b/src/plugins/e-acsl/tests/format/oracle_dev/printf.err.oracle @@ -0,0 +1,6 @@ +gcc: error: ./tests/print.cmxs.startup.o: No such file or directory +gcc: error: ./tests/print.o: No such file or directory +gcc: fatal error: no input files +compilation terminated. +File "caml_startup", line 1: +Error: Error during linking diff --git a/src/plugins/e-acsl/tests/format/oracle_dev/printf.res.oracle b/src/plugins/e-acsl/tests/format/oracle_dev/printf.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..0e725129643c7b30e93ea6195c25aba9922e6972 --- /dev/null +++ b/src/plugins/e-acsl/tests/format/oracle_dev/printf.res.oracle @@ -0,0 +1,5 @@ +[kernel] User Error: cannot load plug-in 'frama-c-e_acsl': cannot load module + Details: error loading shared library: Dynlink.Error (Dynlink.Cannot_open_dll "Failure(\"./top/E_ACSL.cmxs: cannot open shared object file: No such file or directory\")") +[kernel] User Error: compilation of './tests/print.ml' failed +[kernel] User Error: Deferred error message was emitted during execution. See above messages for more information. +[kernel] Frama-C aborted: invalid user input. diff --git a/src/plugins/e-acsl/tests/format/printf.c b/src/plugins/e-acsl/tests/format/printf.c new file mode 100644 index 0000000000000000000000000000000000000000..6417933f418847160c8d273ae928268b02520d07 --- /dev/null +++ b/src/plugins/e-acsl/tests/format/printf.c @@ -0,0 +1,478 @@ +/* run.config_ci,run.config_dev + COMMENT: Check detection of format-string vulnerabilities via printf + DONTRUN: +*/ + +#include <stddef.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <signal.h> +#include <unistd.h> +#include <stdint.h> +#include <limits.h> +#include <wchar.h> +#include "signalled.h" + +#define ABRT_AT(code,at) SIGNALLED_AT(code, 1, at) +#define OK_AT(code,at) SIGNALLED_AT(code, 0, at) + +/* All valid format specifiers */ +const char *valid_specifiers = "diouxfFeEgGaAcspn"; + +/* Given a format string with a specifier at the last position + run printf with this format picking the right type */ +void apply_specifier(char *format, int spec) { + int n; + void *p = NULL; + if (strchr("fFeEgGaA", spec) != NULL) + printf(format, 1.0); + else if (strchr("uoxX", spec) != NULL) + printf(format, 1U); + else if (strchr("dic", spec) != NULL) + printf(format, 97); + else if (spec == 's') + printf(format, "foo"); + else if (spec == 'n') + printf(format, &n); + else if (spec == 'p') + printf(format, p); + else + abort(); +} + +/* Given a string consisting of format specifiers (`allowed`) and a mutable + format string `fmt` with a specifier located at the last position + run positive tests for all specifiers from `allowed` and negative ones + for the remaining one. If `only_negative` is true then only negative tests + are run */ +void test_specifier_application(const char *allowed, const char *fmt, int only_negative, char *at) { + int len = strlen(fmt); + char format[len + 1]; + strcpy(format, fmt); + int i; + for (int i = 0; i < strlen(valid_specifiers); i++) { + int c = valid_specifiers[i]; + format[len - 1] = c; + if (strchr(allowed, c)) { + if (!only_negative) { + OK_AT(apply_specifier(format,c),at); + } + } else { + ABRT_AT(apply_specifier(format,c),at); + } + } +} + +int main(int argc, const char **argv) { + // pointers + char *pstr = "Hello world!"; + char astr[] = "Hello world!"; + signed char *sastr = astr; + void *vptr = (void*)&argc; + // char + char chr = 'T'; + unsigned char uchr = 'U'; + // short + short shrt = 4569; + unsigned short ushrt = 4567; + // int + int i = 268; + unsigned ui = 516; + wint_t wi = 123; + // long + long li = 3134; + unsigned long lu = 7845216; + long long lli = 123LL; + unsigned long long llu = 123LL; + // double + float flt = 0.2; + double dbl = 0.3; + long double ldbl = 0.3; + // typedefs + intmax_t imax = 10; + uintmax_t uimax = 10; + size_t szt = 10; + ptrdiff_t ptrdf = 147; + + // An undefined behaviour occurs if: + // 1. a format directive has no corresponding argument + // 2. a format string is not NUL-terminated + // +Argument Number + // 3. numbered and non-numbered arguments cannot be mixed + // +Precision + // 4. precision is specified for a CS other than [diouxXaAeEfFgG] + // (csn%) + // +Flags: + // 5. a flag is not one of [-+ #0'] + // 6. '#' flag is used with a CS other than [oxXaAeEfFgG] + // 7. '0' flag is used with a CS other than [diouxXaAeEfFgG] + // +Length modifiers (LM): + // 8. a LM is not one of [hljztL] or [ll] or [hh] + // 9. there are more than one LM per one CS + // 10. 'hh' used with a CS other than [diouxXn] + // 11. 'h' used with a CS other than [diouxXn] + // 12. 'l' used with a CS other than [diouxXncsaAeEfFgG] + // 13. 'll' used with a CS other than [diouxXn] + // 14. 'j' used with a CS other than [diouxXn] + // 15. 'z' used with a CS other than [diouxXn] + // 16. 't' used with a CS other than [diouxXn] + // 17. 'L' used with a CS other than [aAeEfFgG] + // +Conversion specifiers (CS): + // 18. Not one of [diouxfFeEgGaAcspnCS%] + // - [di] + // 19. no LM is present and the argument corresponding to + // the above specifier is not of type 'int' + // 20. LM is present and the argument corresponding to the above + // CS is not of signed integral type given by the LM + // - [ouxX] + // 21. no LM is present and the argument corresponding to + // the above specifier is not of type 'unsigned int' + // 22. LM is present and the argument corresponding to the above + // CS is not of unsigned integral type given by the LM + // - [aAeEgGfF] + // 23. no LM is present and the argument corresponding to the above CS + // is not of type 'double' + // 24. LM is present (only 'L' is possible) and the argument + // corresponding to the above CS is not of type 'long double' + // - [c] + // 25. no LM is present and the argument corresponding to the above CS + // is not of type 'int' + // 26. LM is present (only 'l') and the argument corresponding to + // the above CS is not of type 'wint_t' + // - [s] + // 27. no LM is present and the argument corresponding to the above CS + // is not a valid pointer of any character type. + // 28. no LM is present and no precision is specified and the argument + // corresponding to the above CS is not NUL-terminated array of + // characters. An undefined behaviour also occurs if the precision + // is given but it is greater then the size of array and the array + // does not contain a NUL character + // 29. LM is present and the argument corresponding to the above CS is + // not a valid pointer of wchar_t type. + // 30. LM is present and no precision is specified and the argument + // corresponding to the above CS is not wide NUL-terminated (L'\0') + // array of wchar_t. An undefined behaviour also occurs if the + // precision is given but it is greater then the size of array + // and the array does not contain a NUL character + // - [p] + // 31. the argument corresponding to the above CS is not a valid pointer + // of void type + // - [n] + // 32. the argument corresponding to the above CS is not a valid pointer + // of signed int type + // 33. directive involving the above CS contains flags or field width or + // or precision + // - [%] + // 34. The complete specification for the above CS is other than '%%' + // + // Additional undefined behaviours for functions other than printf + // 35. fprintf: stream that fprintf writes to is not a valid open filehandle + // 36. dprintf: file descriptor dprintf writes to is not a file descriptor + // for a file opened for writing + // 37. sprintf/snprintf: buffer that sprintf or snprintf write to is not + // a writeable allocated block of whose size if equal to or larger than + // written bytes + // 38. sprintf/snprintf: memory spaces given by the buffer and the rest of + // the arguments are not disjoint + + // Simplest case + OK(printf("Hello world\n")); + + // A few conversion specifiers + OK(printf("%s - %s! Say it %d or %u times \n", astr, pstr, i, ui)); + + // Undef 1: insifficient arguments + ABRT(printf("%s - %s and say it %d or %u more times \n", astr, pstr, i)); + + // Excessive arguments are fine. They are discarded + OK(printf("%s - %s. Say it %d or %u times \n", astr, pstr, i, ui, ui)); + + // Undef 2: unterminated format string + char fmt[7] = "fmt:%s"; + fmt[6] = 'a'; + ABRT(printf(fmt, pstr)); + + // Support for numbered arguments + OK(printf("%3$s Say it %2$d or %1$u times \n", ui, i, astr)); + // Excessive arguments lead to undefined behaviors + ABRT(printf("%4$s Say it %2$d or %1$u times \n", ui, i, astr)); + // There is no argument 0 + ABRT(printf("%0$s Say it %2$d or %1$u times \n", ui, i, astr)); + + // Undef 3: numbered and non-numbered arguments cannot be mixed ... + ABRT(printf("%s Say it %2$d or %3$u times \n", astr, i, ui)); + // ... except for a complete specification '%%' + OK(printf("%1$d - %% - %2$u times \n", i, ui)); + + // Undef 4. precision is specified for a CS other than [diouxXaAeEfFgGs] + test_specifier_application("diouxXaAeEfFgGs", "%.3X", 0, AT); + + // Undef 5. a flag is not one of [-+ #0'] + // Guarded by internal assertion + + // Undef 6. '#' flag is used with a CS other than [oxXaAeEfFgG] (i.e.,udicsn) + test_specifier_application("oxXaAeEfFgG", "%#X", 0, AT); + + // Undef 7. '0' flag is used with a CS other than [diouxXaAeEfFgG] (i.e., csn) + test_specifier_application("diouxXaAeEfFgG", "%0X", 0, AT); + + // Undef 8. a LM is not one of [hljztL] or [ll] or [hh] + // Guarded by internal assertion + + // Undef 9. there are more than one LM per one CS + OK(printf("%ld\n", 1L)); + OK(printf("%lld\n",1LL)); + ABRT(printf("%llld\n", 1LL)); + + // FIXME: an issue with positive tests here. This is because length modifiers + // change expected types and types used in the `apply_specifier` no longer apply. + + // Undef 10. 'hh' used with a CS other than [diouxXn] + test_specifier_application("diouxXn", "%hhX", 1, AT); + OK(printf("%hhd", 1)); OK(printf("%hhi", 1)); + OK(printf("%hhu", 1)); OK(printf("%hho", 1)); + OK(printf("%hhx", 1)); OK(printf("%hhX", 1)); OK(printf("%hhn", &chr)); + + // Undef 11. 'h' used with a CS other than [diouxXn] + test_specifier_application("diouxXn", "%hX", 1, AT); + OK(printf("%hd", 1)); OK(printf("%hi", 1)); + OK(printf("%hu", 1)); OK(printf("%ho", 1)); + OK(printf("%hx", 1)); OK(printf("%hX", 1)); OK(printf("%hn", &shrt)); + + // Undef 12. 'l' used with a CS other than [diouxXncsaAeEfFgG] + test_specifier_application("diouxXncsaAeEfFgG", "%lX", 1, AT); + OK(printf("%ld", 1L)); OK(printf("%li", 1L)); + OK(printf("%lu", 1UL)); OK(printf("%lo", 1UL)); + OK(printf("%lx", 1UL)); OK(printf("%lX", 1UL)); + // No effect on [aAeEfFgG] + OK(printf("%f", dbl)); OK(printf("%F", dbl)); + OK(printf("%e", dbl)); OK(printf("%E", dbl)); + OK(printf("%a", dbl)); OK(printf("%A", dbl)); + OK(printf("%g", dbl)); OK(printf("%G", dbl)); + // Pointer to long int for [n] + OK(printf("%ln", &li)); + // wint_t for [c], since wint_t is essentially short then it is the subject + // to promotions and "%lc" expects an int + OK(printf("%lc", wi)); + + // Undef 13. 'll' used with a CS other than [diouxXn] + //test_specifier_application("diouxXn", "%llX", 1, AT); + OK(printf("%lld", 1LL)); OK(printf("%lli", 1LL)); + OK(printf("%llu", 1ULL)); OK(printf("%llo", 1ULL)); + OK(printf("%llx", 1ULL)); OK(printf("%llX", 1ULL)); OK(printf("%lln", &lli)); + + // Undef 14. 'j' used with a CS other than [diouxXn] + test_specifier_application("diouxXn", "%jX", 1, AT); + OK(printf("%jd", imax)); OK(printf("%ji", imax)); + OK(printf("%ju", uimax)); OK(printf("%jo", uimax)); + OK(printf("%jx", uimax)); OK(printf("%jX", uimax)); OK(printf("%jn", &imax)); + + // Undef 15. 'z' used with a CS other than [diouxXn] + test_specifier_application("diouxXn", "%zX", 1, AT); + // For 'zi' and 'zd' modifiers we need type of `size_t` size but signed. + // For simplicity the below assumes that in a 32-bit system it is `int` and + // `long` in 64 bit. This may fail though, so use with caution. +#if __WORDSIZE == 64 + OK(printf("%zd", li)); OK(printf("%zi", li)); +#elif __WORDSIZE == 32 + OK(printf("%zd", i)); OK(printf("%zi", i)); +#endif + OK(printf("%zu", szt)); OK(printf("%zo", szt)); + OK(printf("%zx", szt)); OK(printf("%zX", szt)); OK(printf("%zn", &szt)); + + // Undef 16. 't' used with a CS other than [diouxXn] + // Same as above but since ptrdiff_t is sizned we have to tweak types for + // [uoxX] + test_specifier_application("diouxXn", "%tX", 1, AT); +#if __WORDSIZE == 64 + OK(printf("%tu", lu)); OK(printf("%to", lu)); + OK(printf("%tx", lu)); OK(printf("%tX", lu)); +#elif __WORDSIZE == 32 + OK(printf("%tu", u)); OK(printf("%to", u)); + OK(printf("%tx", u)); OK(printf("%tX", u)); +#endif + OK(printf("%td", ptrdf)); OK(printf("%ti", ptrdf)); + OK(printf("%tn", &ptrdf)); + + // Undef 17. 'L' used with a CS other than [aAeEfFgG] + test_specifier_application("aAeEfFgG", "%LX", 1, AT); + OK(printf("%Lf", ldbl)); OK(printf("%LF", ldbl)); + OK(printf("%Le", ldbl)); OK(printf("%LE", ldbl)); + OK(printf("%La", ldbl)); OK(printf("%LA", ldbl)); + OK(printf("%Lg", ldbl)); OK(printf("%LG", ldbl)); + + // Undef 18. CS is not one of [diouxfFeEgGaAcspnCS%] + // Try some of specifiers supported by GLIBC printf but not in C99 + ABRT(printf("%C\n",1)); + ABRT(printf("%S\n",1)); + ABRT(printf("%m\n",1)); + + // Undef 19. [di]: no LM is present and the argument is not of type 'int' + OK(printf("%i\n", i)); OK(printf("%d\n", i)); + OK(printf("%i\n", chr)); OK(printf("%d\n", chr)); // promoted to int + OK(printf("%i\n", shrt)); OK(printf("%d\n", shrt)); // promoted to int + ABRT(printf("%i\n", li)); ABRT(printf("%d\n", li)); + ABRT(printf("%i\n", ui)); ABRT(printf("%d\n", ui)); + ABRT(printf("%i\n", vptr)); ABRT(printf("%d\n", vptr)); + ABRT(printf("%i\n", flt)); ABRT(printf("%d\n", flt)); + + // Undef 20. [di]: LM is present and the argument is not of type given by LM + OK(printf("%li\n", li)); OK(printf("%ld\n", li)); + OK(printf("%lli\n", lli)); OK(printf("%lld\n", lli)); + OK(printf("%hi\n", shrt)); OK(printf("%hd\n", shrt)); + OK(printf("%hhi\n", chr)); OK(printf("%hhd\n", chr)); +#if __WORDSIZE == 64 + OK(printf("%ji\n", li)); OK(printf("%jd\n", li)); +#elif __WORDSIZE == 32 + OK(printf("%zi\n", i)); OK(printf("%zd\n", i)); +#endif + OK(printf("%ti\n", ptrdf)); OK(printf("%td\n", ptrdf)); + + // Undef 21. [ouxX]: no LM is present and the argument is not 'unsigned int' + OK(printf("%u\n", ui)); OK(printf("%o\n", ui)); OK(printf("%x\n", ui)); OK(printf("%X\n", ui)); + ABRT(printf("%u\n", li)); ABRT(printf("%o\n", li)); ABRT(printf("%x\n", li)); ABRT(printf("%X\n", li)); + ABRT(printf("%u\n", lu)); ABRT(printf("%o\n", lu)); ABRT(printf("%x\n", lu)); ABRT(printf("%X\n", lu)); + ABRT(printf("%u\n", flt)); ABRT(printf("%o\n", flt)); ABRT(printf("%x\n", flt)); ABRT(printf("%X\n", flt)); + ABRT(printf("%u\n", vptr)); ABRT(printf("%o\n", vptr)); ABRT(printf("%x\n", vptr)); ABRT(printf("%X\n", vptr)); + ABRT(printf("%u\n", astr)); ABRT(printf("%o\n", astr)); ABRT(printf("%x\n", astr)); ABRT(printf("%X\n", astr)); + + // Undef 22. [ouxX]: LM is present and the argument is not of type given by the LM + OK(printf("%lu\n", lu)); OK(printf("%lo\n", lu)); OK(printf("%lx\n", lu)); OK(printf("%lX\n", lu)); + OK(printf("%llu\n", llu)); OK(printf("%llo\n", llu)); OK(printf("%llx\n", llu)); OK(printf("%llX\n", llu)); + // subject to promotion so expects int + OK(printf("%hu\n", i)); OK(printf("%ho\n", i)); OK(printf("%hx\n", i)); OK(printf("%hX\n", i)); + // subject to promotion so expects int + OK(printf("%hhu\n", i)); OK(printf("%hho\n", i)); OK(printf("%hhx\n", i)); OK(printf("%hhX\n", i)); + OK(printf("%ju\n", uimax)); OK(printf("%jo\n", uimax)); OK(printf("%jx\n", uimax)); OK(printf("%jX\n", uimax)); + OK(printf("%zu\n", szt)); OK(printf("%zo\n", szt)); OK(printf("%zx\n", szt)); OK(printf("%zX\n", szt)); +#if __WORDSIZE == 64 + OK(printf("%tu\n", lu)); OK(printf("%to\n", lu)); OK(printf("%tx\n", lu)); OK(printf("%tX\n", lu)); +#endif + + // Undef 23. [aAgGfFeE]: no LM is present and the argument is not of type 'double' + OK(printf("%f\n",dbl)); OK(printf("%F\n",dbl)); + ABRT(printf("%f\n",ldbl)); ABRT(printf("%F\n",ldbl)); + ABRT(printf("%f\n",i)); ABRT(printf("%F\n",i)); + ABRT(printf("%f\n",lu)); ABRT(printf("%F\n",lu)); + OK(printf("%a\n",dbl)); OK(printf("%A\n",dbl)); + ABRT(printf("%a\n",ldbl)); ABRT(printf("%A\n",ldbl)); + ABRT(printf("%a\n",i)); ABRT(printf("%A\n",i)); + ABRT(printf("%a\n",lu)); ABRT(printf("%A\n",lu)); + OK(printf("%e\n",dbl)); OK(printf("%E\n",dbl)); + ABRT(printf("%e\n",ldbl)); ABRT(printf("%E\n",ldbl)); + ABRT(printf("%e\n",i)); ABRT(printf("%E\n",i)); + ABRT(printf("%e\n",lu)); ABRT(printf("%E\n",lu)); + OK(printf("%g\n",dbl)); OK(printf("%G\n",dbl)); + ABRT(printf("%g\n",ldbl)); ABRT(printf("%G\n",ldbl)); + ABRT(printf("%g\n",i)); ABRT(printf("%G\n",i)); + ABRT(printf("%g\n",lu)); ABRT(printf("%G\n",lu)); + + // 24. [aAgGfFeE]: 'L' LM is present and the argument is not of type 'long double' + ABRT(printf("%Lf\n",dbl)); ABRT(printf("%LF\n",dbl)); + OK(printf("%Lf\n",ldbl)); OK(printf("%LF\n",ldbl)); + ABRT(printf("%Lf\n",i)); ABRT(printf("%LF\n",i)); + ABRT(printf("%Lf\n",lu)); ABRT(printf("%LF\n",lu)); + ABRT(printf("%La\n",dbl)); ABRT(printf("%LA\n",dbl)); + OK(printf("%La\n",ldbl)); OK(printf("%LA\n",ldbl)); + ABRT(printf("%La\n",i)); ABRT(printf("%LA\n",i)); + ABRT(printf("%La\n",lu)); ABRT(printf("%LA\n",lu)); + ABRT(printf("%Le\n",dbl)); ABRT(printf("%LE\n",dbl)); + OK(printf("%Le\n",ldbl)); OK(printf("%LE\n",ldbl)); + ABRT(printf("%Le\n",i)); ABRT(printf("%LE\n",i)); + ABRT(printf("%Le\n",lu)); ABRT(printf("%LE\n",lu)); + ABRT(printf("%Lg\n",dbl)); ABRT(printf("%LG\n",dbl)); + OK(printf("%Lg\n",ldbl)); OK(printf("%LG\n",ldbl)); + ABRT(printf("%Lg\n",i)); ABRT(printf("%LG\n",i)); + ABRT(printf("%Lg\n",lu)); ABRT(printf("%LG\n",lu)); + + // Undef 25. [c] no LM is present and the argument is not of type 'int' + OK(printf("%c\n", i)); + OK(printf("%c\n", chr)); + OK(printf("%c\n", shrt)); + ABRT(printf("%c\n", ui)); + ABRT(printf("%c\n", li)); + ABRT(printf("%c\n", flt)); + ABRT(printf("%c\n", astr)); + + // Undef 26. [c]: 'l' LM is present and the argument is not of type 'wint_t' + OK(printf("%lc\n", wi)); // Both are fine because size comparison is performed + ABRT(printf("%lc\n", li)); + + // Undef 27/28. no LM is present and + // - the argument is not a valid pointer of any character type + // - no precision is specified the argument is not NUL-terminated + // - the precision is given but it is greater then the size of array + // and the array does not contain a NUL character + OK(printf("%s\n", astr)); + OK(printf("%s\n", pstr)); + ABRT(printf("%s\n", i)); + ABRT(printf("%s\n", vptr)); + + char *s1 = NULL; + char *s2; + + ABRT(printf("%s\n", s1)); // Unallocated + ABRT(printf("%s\n", s2)); // Unallocated + + char s4[4] = "cat"; + OK(printf("%s\n", s4)); + s4[3] = 's'; + ABRT(printf("%s\n", s4)); // Not NUL-terminated + + // Precision + OK(printf("%.s\n", s1)); // The precision is zero, so print nothing + OK(printf("%.0s\n", s1)); // The precision is zero, so print nothing + OK(printf("%.3s\n", s4)); // Within allocated limits even though no NUL + OK(printf("%.4s\n", s4)); // Within allocated limits even though no NUL + ABRT(printf("%.5s\n", s4)); // Precision goes over limits + + // Undef 29/30. Same as 27/28 but for '%ls' and wchar_t* +#ifdef WIDE_STRING + ABRT(printf("%ls\n", astr)); + ABRT(printf("%ls\n", pstr)); + ABRT(printf("%ls\n", NULL)); + + wchar_t *ls1; + wchar_t *ls2 = NULL; + wchar_t ls4[4] = L"cat"; + + ABRT(printf("%ls\n", ls1)); + ABRT(printf("%ls\n", ls2)); + OK(printf("%ls\n", ls4)); + + // Precision + OK(printf("%.ls\n", ls1)); // The precision is zero, so print nothing + OK(printf("%.0ls\n", ls1)); // The precision is zero, so print nothing + OK(printf("%.3ls\n", ls4)); // Within allocated limits even though no NUL + OK(printf("%.4ls\n", ls4)); // Within allocated limits even though no NUL + ABRT(printf("%.5ls\n", ls4)); // Precision goes over limits +#endif + + // Undef 31. [p]: the argument is not a valid pointer of void type + OK(printf("%p", vptr)); + ABRT(printf("%p", astr)); + ABRT(printf("%p", NULL)); + + // Undef 32. [n]: the argument is not a valid pointer of signed int type + OK(printf("%n", &i)); + ABRT(printf("%n", &ui)); // pointer to unsigned type + ABRT(printf("%n", NULL)); // NULL + ABRT(printf("%n", (int*)pstr)); // cast of read-only string + + // Undef 33. [n]: directive using [n] contains flags or field width or precision + ABRT(printf("%'n", &i)); + ABRT(printf("%0n", &i)); + ABRT(printf("%#n", &i)); + ABRT(printf("% n", &i)); + ABRT(printf("%+n", &i)); + ABRT(printf("%-n", &i)); + ABRT(printf("%.n", &i)); + ABRT(printf("%.2n", &i)); + ABRT(printf("%.2n", &i)); + ABRT(printf("%10n", &i)); + + // Undef 34. [%]: the complete specification is other than '%%' + ABRT(printf("%d - %'% - %u times \n", i, ui)); + return 0; +} diff --git a/src/plugins/e-acsl/tests/format/signalled.h b/src/plugins/e-acsl/tests/format/signalled.h new file mode 100644 index 0000000000000000000000000000000000000000..fd980c5ca6409cccc2663994e105d487438fc466 --- /dev/null +++ b/src/plugins/e-acsl/tests/format/signalled.h @@ -0,0 +1,44 @@ +#include <stdlib.h> +#include <stdio.h> +#include <sys/wait.h> + +#define STRINGIFY(x) #x +#define TOSTRING(x) STRINGIFY(x) +#define AT __FILE__ ":" TOSTRING(__LINE__) + +int testno = 0; + +void signal_eval(int status, int expect_signal, const char *at) { + printf("TEST %d: ", ++testno); + int signalled = WIFSIGNALED(status); + if (signalled && expect_signal) + printf("OK: Expected signal at %s\n", at); + else if (!signalled && !expect_signal) + printf("OK: Expected execution at %s\n", at); + else if (!signalled && expect_signal) { + printf("FAIL: Unexpected execution at %s\n", at); + exit(1); + } else if (signalled && !expect_signal) { + printf("FAIL: Unexpected signal at %s\n", at); + exit(2); + } +} + +/* The following macro runs a chunk of code in a subprocess and evaluates + the result. This macro assumes that fork is always successful. */ +#define SIGNALLED_AT(code, expect_signal, at) { \ + pid_t pid = fork(); \ + if(!pid) { \ + code; \ + exit(0); \ + } else { \ + int process_status; \ + waitpid(pid, &process_status, 0); \ + signal_eval(process_status, expect_signal, at); \ + } \ +} + +#define ABRT(code) SIGNALLED_AT(code, 1, AT) +#define OK(code) SIGNALLED_AT(code, 0, AT); +#define ABRT_AT(code,at) SIGNALLED_AT(code, 1, at) +#define OK_AT(code,at) SIGNALLED_AT(code, 0, at) diff --git a/src/plugins/e-acsl/tests/format/test_config_ci b/src/plugins/e-acsl/tests/format/test_config_ci new file mode 100644 index 0000000000000000000000000000000000000000..eeaea353f8aafc1309b0f8b93ac86c545a2dd08a --- /dev/null +++ b/src/plugins/e-acsl/tests/format/test_config_ci @@ -0,0 +1 @@ +STDOPT: #"-e-acsl-validate-format-strings" diff --git a/src/plugins/e-acsl/tests/format/test_config_dev b/src/plugins/e-acsl/tests/format/test_config_dev new file mode 100644 index 0000000000000000000000000000000000000000..f8b17db695efee4a9fa9ba7fbad64c1211016eef --- /dev/null +++ b/src/plugins/e-acsl/tests/format/test_config_dev @@ -0,0 +1,4 @@ +MACRO: DEST @PTEST_RESULT@/gen_@PTEST_NAME@ +MACRO: OUT @PTEST_NAME@.res.log +MACRO: ERR @PTEST_NAME@.err.log +EXEC: ./scripts/e-acsl-gcc.sh --validate-format-strings -q -c -X --frama-c-extra="-verbose 0 -kernel-warn-key *=inactive" -o @DEST@.run.c -O @DEST@.out @PTEST_FILE@ > @PTEST_RESULT@/@OUT@ 2> @PTEST_RESULT@/@ERR@ && ./@DEST@.e-acsl > /dev/null diff --git a/src/plugins/e-acsl/tests/full-mmodel/README.md b/src/plugins/e-acsl/tests/full-mmodel/README.md new file mode 100644 index 0000000000000000000000000000000000000000..9e2bd153f80c9ad4ef7ffcb5754a14f665378aa7 --- /dev/null +++ b/src/plugins/e-acsl/tests/full-mmodel/README.md @@ -0,0 +1 @@ +Like runtime, but also test instrumentation with --e-acsl-full-mmodel diff --git a/src/plugins/e-acsl/tests/full-mmodel/addrOf.i b/src/plugins/e-acsl/tests/full-mmodel/addrOf.i new file mode 100644 index 0000000000000000000000000000000000000000..c797facb0f9c1ea90d23dd783c7e380668314ce0 --- /dev/null +++ b/src/plugins/e-acsl/tests/full-mmodel/addrOf.i @@ -0,0 +1,18 @@ +/* run.config + COMMENT: addrOf +*/ + +void f(){ + int m, *u, *p; + u = &m; + p = u; + m = 123; + //@ assert \initialized(p); +} + +int main(void) { + int x = 0; + f(); + /*@ assert &x == &x; */ ; + return 0; +} diff --git a/src/plugins/e-acsl/tests/full-mmodel/oracle_ci/addrOf.0.res.oracle b/src/plugins/e-acsl/tests/full-mmodel/oracle_ci/addrOf.0.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..25dfbfef069fb1a71fc6f837a41f73a9eaa741c6 --- /dev/null +++ b/src/plugins/e-acsl/tests/full-mmodel/oracle_ci/addrOf.0.res.oracle @@ -0,0 +1,19 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". +[eva] Analyzing a complete application starting at main +[eva] Computing initial state +[eva] Initial state computed +[eva:initial-state] Values of globals at initialization + __e_acsl_init ∈ [--..--] + __e_acsl_heap_allocation_size ∈ [--..--] + __e_acsl_math_HUGE_VAL ∈ [-1.79769313486e+308 .. 1.79769313486e+308] + __e_acsl_math_HUGE_VALF ∈ [-3.40282346639e+38 .. 3.40282346639e+38] + __e_acsl_math_INFINITY ∈ [-1.79769313486e+308 .. 1.79769313486e+308] +[eva] using specification for function __e_acsl_memory_init +[eva] using specification for function __e_acsl_store_block +[eva] using specification for function __e_acsl_full_init +[eva] using specification for function __e_acsl_initialized +[eva] using specification for function __e_acsl_assert +[eva] using specification for function __e_acsl_delete_block +[eva] using specification for function __e_acsl_memory_clean +[eva] done for function main diff --git a/src/plugins/e-acsl/tests/full-mmodel/oracle_ci/addrOf.1.res.oracle b/src/plugins/e-acsl/tests/full-mmodel/oracle_ci/addrOf.1.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..25dfbfef069fb1a71fc6f837a41f73a9eaa741c6 --- /dev/null +++ b/src/plugins/e-acsl/tests/full-mmodel/oracle_ci/addrOf.1.res.oracle @@ -0,0 +1,19 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". +[eva] Analyzing a complete application starting at main +[eva] Computing initial state +[eva] Initial state computed +[eva:initial-state] Values of globals at initialization + __e_acsl_init ∈ [--..--] + __e_acsl_heap_allocation_size ∈ [--..--] + __e_acsl_math_HUGE_VAL ∈ [-1.79769313486e+308 .. 1.79769313486e+308] + __e_acsl_math_HUGE_VALF ∈ [-3.40282346639e+38 .. 3.40282346639e+38] + __e_acsl_math_INFINITY ∈ [-1.79769313486e+308 .. 1.79769313486e+308] +[eva] using specification for function __e_acsl_memory_init +[eva] using specification for function __e_acsl_store_block +[eva] using specification for function __e_acsl_full_init +[eva] using specification for function __e_acsl_initialized +[eva] using specification for function __e_acsl_assert +[eva] using specification for function __e_acsl_delete_block +[eva] using specification for function __e_acsl_memory_clean +[eva] done for function main diff --git a/src/plugins/e-acsl/tests/full-mmodel/oracle_ci/addrOf.res.oracle b/src/plugins/e-acsl/tests/full-mmodel/oracle_ci/addrOf.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..efd026311297e55d8fefb674326118e6ece88624 --- /dev/null +++ b/src/plugins/e-acsl/tests/full-mmodel/oracle_ci/addrOf.res.oracle @@ -0,0 +1,2 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". diff --git a/src/plugins/e-acsl/tests/full-mmodel/oracle_ci/gen_addrOf.c b/src/plugins/e-acsl/tests/full-mmodel/oracle_ci/gen_addrOf.c new file mode 100644 index 0000000000000000000000000000000000000000..3c2bad6f858c1f3248748229c2c4d76d1e06bc24 --- /dev/null +++ b/src/plugins/e-acsl/tests/full-mmodel/oracle_ci/gen_addrOf.c @@ -0,0 +1,82 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +void f(void) +{ + int m; + int *u; + int *p; + __e_acsl_store_block((void *)(& p),(size_t)8); + __e_acsl_store_block((void *)(& u),(size_t)8); + __e_acsl_store_block((void *)(& m),(size_t)4); + __e_acsl_full_init((void *)(& u)); + u = & m; + __e_acsl_full_init((void *)(& p)); + p = u; + __e_acsl_full_init((void *)(& m)); + m = 123; + /*@ assert \initialized(p); */ + { + int __gen_e_acsl_initialized; + __gen_e_acsl_initialized = __e_acsl_initialized((void *)p,sizeof(int)); + __e_acsl_assert(__gen_e_acsl_initialized,(char *)"Assertion",(char *)"f", + (char *)"\\initialized(p)",10); + } + __e_acsl_delete_block((void *)(& p)); + __e_acsl_delete_block((void *)(& u)); + __e_acsl_delete_block((void *)(& m)); + return; +} + +void __e_acsl_globals_init(void) +{ + static char __e_acsl_already_run = 0; + if (! __e_acsl_already_run) { + __e_acsl_already_run = 1; + __e_acsl_store_block((void *)(& f),(size_t)1); + __e_acsl_full_init((void *)(& f)); + __e_acsl_store_block((void *)(& __fc_p_fopen),(size_t)8); + __e_acsl_full_init((void *)(& __fc_p_fopen)); + __e_acsl_store_block((void *)(__fc_fopen),(size_t)128); + __e_acsl_full_init((void *)(& __fc_fopen)); + __e_acsl_store_block((void *)(& __fc_p_random48_counter),(size_t)8); + __e_acsl_full_init((void *)(& __fc_p_random48_counter)); + __e_acsl_store_block((void *)(random48_counter),(size_t)6); + __e_acsl_full_init((void *)(& random48_counter)); + __e_acsl_store_block((void *)(& __fc_random48_init),(size_t)4); + __e_acsl_full_init((void *)(& __fc_random48_init)); + __e_acsl_store_block((void *)(& __fc_rand_max),(size_t)8); + __e_acsl_full_init((void *)(& __fc_rand_max)); + } + return; +} + +int main(void) +{ + int __retres; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + __e_acsl_globals_init(); + __e_acsl_store_block((void *)(& __retres),(size_t)4); + int x = 0; + __e_acsl_store_block((void *)(& x),(size_t)4); + __e_acsl_full_init((void *)(& x)); + f(); + /*@ assert &x ≡ &x; */ + __e_acsl_assert(& x == & x,(char *)"Assertion",(char *)"main", + (char *)"&x == &x",16); + __e_acsl_full_init((void *)(& __retres)); + __retres = 0; + __e_acsl_delete_block((void *)(& f)); + __e_acsl_delete_block((void *)(& __fc_p_fopen)); + __e_acsl_delete_block((void *)(__fc_fopen)); + __e_acsl_delete_block((void *)(& __fc_p_random48_counter)); + __e_acsl_delete_block((void *)(random48_counter)); + __e_acsl_delete_block((void *)(& __fc_random48_init)); + __e_acsl_delete_block((void *)(& __fc_rand_max)); + __e_acsl_delete_block((void *)(& x)); + __e_acsl_delete_block((void *)(& __retres)); + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/full-mmodel/oracle_ci/gen_addrOf2.c b/src/plugins/e-acsl/tests/full-mmodel/oracle_ci/gen_addrOf2.c new file mode 100644 index 0000000000000000000000000000000000000000..3c2bad6f858c1f3248748229c2c4d76d1e06bc24 --- /dev/null +++ b/src/plugins/e-acsl/tests/full-mmodel/oracle_ci/gen_addrOf2.c @@ -0,0 +1,82 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +void f(void) +{ + int m; + int *u; + int *p; + __e_acsl_store_block((void *)(& p),(size_t)8); + __e_acsl_store_block((void *)(& u),(size_t)8); + __e_acsl_store_block((void *)(& m),(size_t)4); + __e_acsl_full_init((void *)(& u)); + u = & m; + __e_acsl_full_init((void *)(& p)); + p = u; + __e_acsl_full_init((void *)(& m)); + m = 123; + /*@ assert \initialized(p); */ + { + int __gen_e_acsl_initialized; + __gen_e_acsl_initialized = __e_acsl_initialized((void *)p,sizeof(int)); + __e_acsl_assert(__gen_e_acsl_initialized,(char *)"Assertion",(char *)"f", + (char *)"\\initialized(p)",10); + } + __e_acsl_delete_block((void *)(& p)); + __e_acsl_delete_block((void *)(& u)); + __e_acsl_delete_block((void *)(& m)); + return; +} + +void __e_acsl_globals_init(void) +{ + static char __e_acsl_already_run = 0; + if (! __e_acsl_already_run) { + __e_acsl_already_run = 1; + __e_acsl_store_block((void *)(& f),(size_t)1); + __e_acsl_full_init((void *)(& f)); + __e_acsl_store_block((void *)(& __fc_p_fopen),(size_t)8); + __e_acsl_full_init((void *)(& __fc_p_fopen)); + __e_acsl_store_block((void *)(__fc_fopen),(size_t)128); + __e_acsl_full_init((void *)(& __fc_fopen)); + __e_acsl_store_block((void *)(& __fc_p_random48_counter),(size_t)8); + __e_acsl_full_init((void *)(& __fc_p_random48_counter)); + __e_acsl_store_block((void *)(random48_counter),(size_t)6); + __e_acsl_full_init((void *)(& random48_counter)); + __e_acsl_store_block((void *)(& __fc_random48_init),(size_t)4); + __e_acsl_full_init((void *)(& __fc_random48_init)); + __e_acsl_store_block((void *)(& __fc_rand_max),(size_t)8); + __e_acsl_full_init((void *)(& __fc_rand_max)); + } + return; +} + +int main(void) +{ + int __retres; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + __e_acsl_globals_init(); + __e_acsl_store_block((void *)(& __retres),(size_t)4); + int x = 0; + __e_acsl_store_block((void *)(& x),(size_t)4); + __e_acsl_full_init((void *)(& x)); + f(); + /*@ assert &x ≡ &x; */ + __e_acsl_assert(& x == & x,(char *)"Assertion",(char *)"main", + (char *)"&x == &x",16); + __e_acsl_full_init((void *)(& __retres)); + __retres = 0; + __e_acsl_delete_block((void *)(& f)); + __e_acsl_delete_block((void *)(& __fc_p_fopen)); + __e_acsl_delete_block((void *)(__fc_fopen)); + __e_acsl_delete_block((void *)(& __fc_p_random48_counter)); + __e_acsl_delete_block((void *)(random48_counter)); + __e_acsl_delete_block((void *)(& __fc_random48_init)); + __e_acsl_delete_block((void *)(& __fc_rand_max)); + __e_acsl_delete_block((void *)(& x)); + __e_acsl_delete_block((void *)(& __retres)); + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/full-mmodel/oracle_dev/addrOf.res.oracle b/src/plugins/e-acsl/tests/full-mmodel/oracle_dev/addrOf.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..e53ffdec61d97f8b6372416756249550b782b0c3 --- /dev/null +++ b/src/plugins/e-acsl/tests/full-mmodel/oracle_dev/addrOf.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/full-mmodel/addrOf.i (no preprocessing) diff --git a/src/plugins/e-acsl/tests/full-mmodel/test_config_ci b/src/plugins/e-acsl/tests/full-mmodel/test_config_ci new file mode 100644 index 0000000000000000000000000000000000000000..82cdcaaa69d16cc0e2427322763c59b35a07268b --- /dev/null +++ b/src/plugins/e-acsl/tests/full-mmodel/test_config_ci @@ -0,0 +1 @@ +STDOPT: #"-e-acsl-full-mmodel" diff --git a/src/plugins/e-acsl/tests/full-mmodel/test_config_dev b/src/plugins/e-acsl/tests/full-mmodel/test_config_dev new file mode 100644 index 0000000000000000000000000000000000000000..47c27064d6a7cced263a412954d891030819eaf6 --- /dev/null +++ b/src/plugins/e-acsl/tests/full-mmodel/test_config_dev @@ -0,0 +1,4 @@ +MACRO: DEST @PTEST_RESULT@/gen_@PTEST_NAME@ +MACRO: OUT @PTEST_NAME@.res.log +MACRO: ERR @PTEST_NAME@.err.log +EXEC: ./scripts/e-acsl-gcc.sh --full-mmodel -q -c -X --frama-c-extra="-journal-disable -verbose 0 -kernel-warn-key *=inactive" -o @DEST@.run.c -O @DEST@.out @PTEST_FILE@ > @PTEST_RESULT@/@OUT@ 2> @PTEST_RESULT@/@ERR@ && ./@DEST@.e-acsl > /dev/null diff --git a/src/plugins/e-acsl/tests/gmp-only/arith.i b/src/plugins/e-acsl/tests/gmp-only/arith.i new file mode 100644 index 0000000000000000000000000000000000000000..df97877fb148968c52cd69013790c311dcf6160b --- /dev/null +++ b/src/plugins/e-acsl/tests/gmp-only/arith.i @@ -0,0 +1,39 @@ +/* run.config + COMMENT: arithmetic operations +*/ + +int main(void) { + int x = -3; + int y = 2; + long z = 2L; + + /*@ assert -3 == x; */ ; + /*@ assert x == -3; */ ; + /*@ assert 0 != ~0; */ ; + + /*@ assert x+1 == -2; */ ; + /*@ assert x-1 == -4; */ ; + /*@ assert x*3 == -9; */ ; + /*@ assert x/3 == -1; */ ; + /*@ assert 0xffffffffffffffffffffff/0xffffffffffffffffffffff == 1; */ ; + /*@ assert x % 2 == -1; */ ; + /*@ assert -3 % -2 == -1; */ ; + /*@ assert 3 % -2 == 1; */ ; + + /*@ assert x * 2 + (3 + y) - 4 + (x - y) == -10; */ ; + + /*@ assert (0 == 1) == !(0 == 0); */ ; + /*@ assert (0 <= -1) == (0 > 0); */ ; + /*@ assert (0 >= -1) == (0 <= 0); */ ; + /*@ assert (0 != 1) == !(0 != 0); */ ; + + /*@ assert 0 == !1; */ ; + /*@ assert 4 / y == 2; */ // non trivial division added when fixing bts #751 + + // example from the JFLA'15 paper (but for a 64-bit architecture) + /*@ assert 1 + ((z+1) / (y-123456789123456789)) == 1; */ + + /*@ assert 1 - x == -x + 1; */ // test GIT issue #37 + + return 0; +} diff --git a/src/plugins/e-acsl/tests/gmp-only/functions.c b/src/plugins/e-acsl/tests/gmp-only/functions.c new file mode 100644 index 0000000000000000000000000000000000000000..9d0bc001ab61c0b89201f3c3ecffae481965c120 --- /dev/null +++ b/src/plugins/e-acsl/tests/gmp-only/functions.c @@ -0,0 +1,73 @@ +/* run.config + COMMENT: logic functions without labels +*/ + +/*@ predicate p1(int x, int y) = x + y > 0; */ +/*@ predicate p2(integer x, integer y) = x + y > 0; */ + +/*@ logic integer f1(integer x, integer y) = x + y; */ + +// E-ACSL integer typing: +// types less than int are considered as int +/*@ logic char h_char(char c) = c; */ +/*@ logic short h_short(short s) = s; */ + +/*@ logic int g_hidden(int x) = x; */ +/*@ logic int g(int x) = g_hidden(x); */ + +struct mystruct { int k, l; }; +typedef struct mystruct mystruct; +/*@ logic mystruct t1(mystruct m) = m; */ +/*@ logic integer t2(mystruct m) = m.k + m.l; */ + +// To test function call in other clauses than assert: +/*@ predicate k_pred(integer x) = x > 0; */ +/*@ requires k_pred(x); */ +void k(int x) {} + +// To test non-interference with global inits: +int glob = 5; + +// To test that functions that are never called are not generated: +/*@ predicate never_called(int x) = x == x; */ + +/*@ logic double f2(double x) = (double)(1/x); */ /* handle in MR !226 */ + +// To test not_yet: +/*@ predicate p_notyet{L}(integer x) = x > 0; */ +/*@ logic integer f_notyet{L}(integer x) = x; */ + +int main (void) { + int x = 1, y = 2; + /*@ assert p1(x, y); */ ; + /*@ assert p2(3, 4); */ ; + /*@ assert p2(5, 99999999999999999999999999999); */ ; + + /*@ assert f1(x, y) == 3; */ ; + /*@ assert p2(x, f1(3, 4)); */ ; + /*@ assert f1(9, 99999999999999999999999999999) > 0; */ ; + /*@ assert f1(99999999999999999999999999999, + 99999999999999999999999999999) == + 199999999999999999999999999998; */ ; + + /*@ assert g(x) == x; */ ; + + char c = 'c'; + /*@ assert h_char(c) == c; */ ; + short s = 1; + /*@ assert h_short(s) == s; */ ; + + mystruct m; + m.k = 8; + m.l = 9; + /*@ assert t2(t1(m)) == 17; */ ; + + k(9); + + double d = 2.0; + /*@ assert f2(d) > 0; */ ; + + // not yet supported + /* /\*@ assert p_notyet(27); *\/ ; */ + /* /\*@ assert f_notyet(27) == 27; *\/ ; */ +} diff --git a/src/plugins/e-acsl/tests/gmp-only/oracle_ci/arith.res.oracle b/src/plugins/e-acsl/tests/gmp-only/oracle_ci/arith.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..58ff928b06ae06fc7cc29f0189bd96640c51f53b --- /dev/null +++ b/src/plugins/e-acsl/tests/gmp-only/oracle_ci/arith.res.oracle @@ -0,0 +1,44 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". +[eva:alarm] tests/gmp-only/arith.i:10: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/gmp-only/arith.i:11: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/gmp-only/arith.i:12: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/gmp-only/arith.i:14: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/gmp-only/arith.i:15: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/gmp-only/arith.i:16: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/gmp-only/arith.i:17: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/gmp-only/arith.i:18: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/gmp-only/arith.i:19: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/gmp-only/arith.i:20: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/gmp-only/arith.i:21: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/gmp-only/arith.i:23: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/gmp-only/arith.i:25: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/gmp-only/arith.i:26: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/gmp-only/arith.i:27: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/gmp-only/arith.i:28: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/gmp-only/arith.i:30: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/gmp-only/arith.i:31: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/gmp-only/arith.i:34: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/gmp-only/arith.i:34: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/gmp-only/arith.i:36: Warning: + function __e_acsl_assert: precondition got status unknown. diff --git a/src/plugins/e-acsl/tests/gmp-only/oracle_ci/functions.res.oracle b/src/plugins/e-acsl/tests/gmp-only/oracle_ci/functions.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..3a0b1952d64396dde8a2ee52c59bb7dcc12fa20a --- /dev/null +++ b/src/plugins/e-acsl/tests/gmp-only/oracle_ci/functions.res.oracle @@ -0,0 +1,33 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". +[eva:alarm] tests/gmp-only/functions.c:42: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/gmp-only/functions.c:43: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/gmp-only/functions.c:44: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/gmp-only/functions.c:46: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/gmp-only/functions.c:47: Warning: + accessing uninitialized left-value. + assert \initialized((__e_acsl_mpz_struct *)__gen_e_acsl_f1_4); +[eva:alarm] tests/gmp-only/functions.c:47: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/gmp-only/functions.c:48: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/gmp-only/functions.c:49: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/gmp-only/functions.c:53: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/gmp-only/functions.c:56: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/gmp-only/functions.c:58: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/gmp-only/functions.c:63: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/gmp-only/functions.c:25: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/gmp-only/functions.c:68: Warning: + non-finite double value. assert \is_finite(__gen_e_acsl__15); +[eva:alarm] tests/gmp-only/functions.c:68: Warning: + function __e_acsl_assert: precondition got status unknown. diff --git a/src/plugins/e-acsl/tests/gmp-only/oracle_ci/gen_arith.c b/src/plugins/e-acsl/tests/gmp-only/oracle_ci/gen_arith.c new file mode 100644 index 0000000000000000000000000000000000000000..7c7f1a19d0de927ca250ae4a1fed2f6f33891a7b --- /dev/null +++ b/src/plugins/e-acsl/tests/gmp-only/oracle_ci/gen_arith.c @@ -0,0 +1,685 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +int main(void) +{ + int __retres; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + int x = -3; + int y = 2; + long z = 2L; + /*@ assert -3 ≡ x; */ + { + __e_acsl_mpz_t __gen_e_acsl_; + __e_acsl_mpz_t __gen_e_acsl_neg; + __e_acsl_mpz_t __gen_e_acsl_x; + int __gen_e_acsl_eq; + __gmpz_init_set_si(__gen_e_acsl_,3L); + __gmpz_init(__gen_e_acsl_neg); + __gmpz_neg(__gen_e_acsl_neg,(__e_acsl_mpz_struct const *)(__gen_e_acsl_)); + __gmpz_init_set_si(__gen_e_acsl_x,(long)x); + __gen_e_acsl_eq = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_neg), + (__e_acsl_mpz_struct const *)(__gen_e_acsl_x)); + __e_acsl_assert(__gen_e_acsl_eq == 0,(char *)"Assertion",(char *)"main", + (char *)"-3 == x",10); + __gmpz_clear(__gen_e_acsl_); + __gmpz_clear(__gen_e_acsl_neg); + __gmpz_clear(__gen_e_acsl_x); + } + /*@ assert x ≡ -3; */ + { + __e_acsl_mpz_t __gen_e_acsl_x_2; + __e_acsl_mpz_t __gen_e_acsl__2; + __e_acsl_mpz_t __gen_e_acsl_neg_2; + int __gen_e_acsl_eq_2; + __gmpz_init_set_si(__gen_e_acsl_x_2,(long)x); + __gmpz_init_set_si(__gen_e_acsl__2,3L); + __gmpz_init(__gen_e_acsl_neg_2); + __gmpz_neg(__gen_e_acsl_neg_2, + (__e_acsl_mpz_struct const *)(__gen_e_acsl__2)); + __gen_e_acsl_eq_2 = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_x_2), + (__e_acsl_mpz_struct const *)(__gen_e_acsl_neg_2)); + __e_acsl_assert(__gen_e_acsl_eq_2 == 0,(char *)"Assertion", + (char *)"main",(char *)"x == -3",11); + __gmpz_clear(__gen_e_acsl_x_2); + __gmpz_clear(__gen_e_acsl__2); + __gmpz_clear(__gen_e_acsl_neg_2); + } + /*@ assert 0 ≢ ~0; */ + { + __e_acsl_mpz_t __gen_e_acsl__3; + __e_acsl_mpz_t __gen_e_acsl_bnot; + int __gen_e_acsl_ne; + __gmpz_init_set_si(__gen_e_acsl__3,0L); + __gmpz_init(__gen_e_acsl_bnot); + __gmpz_com(__gen_e_acsl_bnot, + (__e_acsl_mpz_struct const *)(__gen_e_acsl__3)); + __gen_e_acsl_ne = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl__3), + (__e_acsl_mpz_struct const *)(__gen_e_acsl_bnot)); + __e_acsl_assert(__gen_e_acsl_ne != 0,(char *)"Assertion",(char *)"main", + (char *)"0 != ~0",12); + __gmpz_clear(__gen_e_acsl__3); + __gmpz_clear(__gen_e_acsl_bnot); + } + /*@ assert x + 1 ≡ -2; */ + { + __e_acsl_mpz_t __gen_e_acsl_x_3; + __e_acsl_mpz_t __gen_e_acsl__4; + __e_acsl_mpz_t __gen_e_acsl_add; + __e_acsl_mpz_t __gen_e_acsl__5; + __e_acsl_mpz_t __gen_e_acsl_neg_3; + int __gen_e_acsl_eq_3; + __gmpz_init_set_si(__gen_e_acsl_x_3,(long)x); + __gmpz_init_set_si(__gen_e_acsl__4,1L); + __gmpz_init(__gen_e_acsl_add); + __gmpz_add(__gen_e_acsl_add, + (__e_acsl_mpz_struct const *)(__gen_e_acsl_x_3), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__4)); + __gmpz_init_set_si(__gen_e_acsl__5,2L); + __gmpz_init(__gen_e_acsl_neg_3); + __gmpz_neg(__gen_e_acsl_neg_3, + (__e_acsl_mpz_struct const *)(__gen_e_acsl__5)); + __gen_e_acsl_eq_3 = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_add), + (__e_acsl_mpz_struct const *)(__gen_e_acsl_neg_3)); + __e_acsl_assert(__gen_e_acsl_eq_3 == 0,(char *)"Assertion", + (char *)"main",(char *)"x + 1 == -2",14); + __gmpz_clear(__gen_e_acsl_x_3); + __gmpz_clear(__gen_e_acsl__4); + __gmpz_clear(__gen_e_acsl_add); + __gmpz_clear(__gen_e_acsl__5); + __gmpz_clear(__gen_e_acsl_neg_3); + } + /*@ assert x - 1 ≡ -4; */ + { + __e_acsl_mpz_t __gen_e_acsl_x_4; + __e_acsl_mpz_t __gen_e_acsl__6; + __e_acsl_mpz_t __gen_e_acsl_sub; + __e_acsl_mpz_t __gen_e_acsl__7; + __e_acsl_mpz_t __gen_e_acsl_neg_4; + int __gen_e_acsl_eq_4; + __gmpz_init_set_si(__gen_e_acsl_x_4,(long)x); + __gmpz_init_set_si(__gen_e_acsl__6,1L); + __gmpz_init(__gen_e_acsl_sub); + __gmpz_sub(__gen_e_acsl_sub, + (__e_acsl_mpz_struct const *)(__gen_e_acsl_x_4), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__6)); + __gmpz_init_set_si(__gen_e_acsl__7,4L); + __gmpz_init(__gen_e_acsl_neg_4); + __gmpz_neg(__gen_e_acsl_neg_4, + (__e_acsl_mpz_struct const *)(__gen_e_acsl__7)); + __gen_e_acsl_eq_4 = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_sub), + (__e_acsl_mpz_struct const *)(__gen_e_acsl_neg_4)); + __e_acsl_assert(__gen_e_acsl_eq_4 == 0,(char *)"Assertion", + (char *)"main",(char *)"x - 1 == -4",15); + __gmpz_clear(__gen_e_acsl_x_4); + __gmpz_clear(__gen_e_acsl__6); + __gmpz_clear(__gen_e_acsl_sub); + __gmpz_clear(__gen_e_acsl__7); + __gmpz_clear(__gen_e_acsl_neg_4); + } + /*@ assert x * 3 ≡ -9; */ + { + __e_acsl_mpz_t __gen_e_acsl_x_5; + __e_acsl_mpz_t __gen_e_acsl__8; + __e_acsl_mpz_t __gen_e_acsl_mul; + __e_acsl_mpz_t __gen_e_acsl__9; + __e_acsl_mpz_t __gen_e_acsl_neg_5; + int __gen_e_acsl_eq_5; + __gmpz_init_set_si(__gen_e_acsl_x_5,(long)x); + __gmpz_init_set_si(__gen_e_acsl__8,3L); + __gmpz_init(__gen_e_acsl_mul); + __gmpz_mul(__gen_e_acsl_mul, + (__e_acsl_mpz_struct const *)(__gen_e_acsl_x_5), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__8)); + __gmpz_init_set_si(__gen_e_acsl__9,9L); + __gmpz_init(__gen_e_acsl_neg_5); + __gmpz_neg(__gen_e_acsl_neg_5, + (__e_acsl_mpz_struct const *)(__gen_e_acsl__9)); + __gen_e_acsl_eq_5 = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_mul), + (__e_acsl_mpz_struct const *)(__gen_e_acsl_neg_5)); + __e_acsl_assert(__gen_e_acsl_eq_5 == 0,(char *)"Assertion", + (char *)"main",(char *)"x * 3 == -9",16); + __gmpz_clear(__gen_e_acsl_x_5); + __gmpz_clear(__gen_e_acsl__8); + __gmpz_clear(__gen_e_acsl_mul); + __gmpz_clear(__gen_e_acsl__9); + __gmpz_clear(__gen_e_acsl_neg_5); + } + /*@ assert x / 3 ≡ -1; */ + { + __e_acsl_mpz_t __gen_e_acsl_x_6; + __e_acsl_mpz_t __gen_e_acsl__10; + __e_acsl_mpz_t __gen_e_acsl__11; + int __gen_e_acsl_div_guard; + __e_acsl_mpz_t __gen_e_acsl_div; + __e_acsl_mpz_t __gen_e_acsl__12; + __e_acsl_mpz_t __gen_e_acsl_neg_6; + int __gen_e_acsl_eq_6; + __gmpz_init_set_si(__gen_e_acsl_x_6,(long)x); + __gmpz_init_set_si(__gen_e_acsl__10,3L); + __gmpz_init_set_si(__gen_e_acsl__11,0L); + __gen_e_acsl_div_guard = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl__10), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__11)); + __gmpz_init(__gen_e_acsl_div); + /*@ assert E_ACSL: 3 ≢ 0; */ + __e_acsl_assert(! (__gen_e_acsl_div_guard == 0),(char *)"Assertion", + (char *)"main",(char *)"3 == 0",17); + __gmpz_tdiv_q(__gen_e_acsl_div, + (__e_acsl_mpz_struct const *)(__gen_e_acsl_x_6), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__10)); + __gmpz_init_set_si(__gen_e_acsl__12,1L); + __gmpz_init(__gen_e_acsl_neg_6); + __gmpz_neg(__gen_e_acsl_neg_6, + (__e_acsl_mpz_struct const *)(__gen_e_acsl__12)); + __gen_e_acsl_eq_6 = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_div), + (__e_acsl_mpz_struct const *)(__gen_e_acsl_neg_6)); + __e_acsl_assert(__gen_e_acsl_eq_6 == 0,(char *)"Assertion", + (char *)"main",(char *)"x / 3 == -1",17); + __gmpz_clear(__gen_e_acsl_x_6); + __gmpz_clear(__gen_e_acsl__10); + __gmpz_clear(__gen_e_acsl__11); + __gmpz_clear(__gen_e_acsl_div); + __gmpz_clear(__gen_e_acsl__12); + __gmpz_clear(__gen_e_acsl_neg_6); + } + /*@ assert 0xffffffffffffffffffffff / 0xffffffffffffffffffffff ≡ 1; */ + { + __e_acsl_mpz_t __gen_e_acsl__13; + __e_acsl_mpz_t __gen_e_acsl__14; + int __gen_e_acsl_div_guard_2; + __e_acsl_mpz_t __gen_e_acsl_div_2; + __e_acsl_mpz_t __gen_e_acsl__15; + int __gen_e_acsl_eq_7; + __gmpz_init_set_str(__gen_e_acsl__13,"309485009821345068724781055",10); + __gmpz_init_set_si(__gen_e_acsl__14,0L); + __gen_e_acsl_div_guard_2 = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl__13), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__14)); + __gmpz_init(__gen_e_acsl_div_2); + /*@ assert E_ACSL: 0xffffffffffffffffffffff ≢ 0; */ + __e_acsl_assert(! (__gen_e_acsl_div_guard_2 == 0),(char *)"Assertion", + (char *)"main",(char *)"0xffffffffffffffffffffff == 0", + 18); + __gmpz_tdiv_q(__gen_e_acsl_div_2, + (__e_acsl_mpz_struct const *)(__gen_e_acsl__13), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__13)); + __gmpz_init_set_si(__gen_e_acsl__15,1L); + __gen_e_acsl_eq_7 = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_div_2), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__15)); + __e_acsl_assert(__gen_e_acsl_eq_7 == 0,(char *)"Assertion", + (char *)"main", + (char *)"0xffffffffffffffffffffff / 0xffffffffffffffffffffff == 1", + 18); + __gmpz_clear(__gen_e_acsl__13); + __gmpz_clear(__gen_e_acsl__14); + __gmpz_clear(__gen_e_acsl_div_2); + __gmpz_clear(__gen_e_acsl__15); + } + /*@ assert x % 2 ≡ -1; */ + { + __e_acsl_mpz_t __gen_e_acsl_x_7; + __e_acsl_mpz_t __gen_e_acsl__16; + __e_acsl_mpz_t __gen_e_acsl__17; + int __gen_e_acsl_mod_guard; + __e_acsl_mpz_t __gen_e_acsl_mod; + __e_acsl_mpz_t __gen_e_acsl__18; + __e_acsl_mpz_t __gen_e_acsl_neg_7; + int __gen_e_acsl_eq_8; + __gmpz_init_set_si(__gen_e_acsl_x_7,(long)x); + __gmpz_init_set_si(__gen_e_acsl__16,2L); + __gmpz_init_set_si(__gen_e_acsl__17,0L); + __gen_e_acsl_mod_guard = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl__16), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__17)); + __gmpz_init(__gen_e_acsl_mod); + /*@ assert E_ACSL: 2 ≢ 0; */ + __e_acsl_assert(! (__gen_e_acsl_mod_guard == 0),(char *)"Assertion", + (char *)"main",(char *)"2 == 0",19); + __gmpz_tdiv_r(__gen_e_acsl_mod, + (__e_acsl_mpz_struct const *)(__gen_e_acsl_x_7), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__16)); + __gmpz_init_set_si(__gen_e_acsl__18,1L); + __gmpz_init(__gen_e_acsl_neg_7); + __gmpz_neg(__gen_e_acsl_neg_7, + (__e_acsl_mpz_struct const *)(__gen_e_acsl__18)); + __gen_e_acsl_eq_8 = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_mod), + (__e_acsl_mpz_struct const *)(__gen_e_acsl_neg_7)); + __e_acsl_assert(__gen_e_acsl_eq_8 == 0,(char *)"Assertion", + (char *)"main",(char *)"x % 2 == -1",19); + __gmpz_clear(__gen_e_acsl_x_7); + __gmpz_clear(__gen_e_acsl__16); + __gmpz_clear(__gen_e_acsl__17); + __gmpz_clear(__gen_e_acsl_mod); + __gmpz_clear(__gen_e_acsl__18); + __gmpz_clear(__gen_e_acsl_neg_7); + } + /*@ assert -3 % -2 ≡ -1; */ + { + __e_acsl_mpz_t __gen_e_acsl__19; + __e_acsl_mpz_t __gen_e_acsl_neg_8; + __e_acsl_mpz_t __gen_e_acsl__20; + __e_acsl_mpz_t __gen_e_acsl_neg_9; + __e_acsl_mpz_t __gen_e_acsl__21; + int __gen_e_acsl_mod_guard_2; + __e_acsl_mpz_t __gen_e_acsl_mod_2; + __e_acsl_mpz_t __gen_e_acsl__22; + __e_acsl_mpz_t __gen_e_acsl_neg_10; + int __gen_e_acsl_eq_9; + __gmpz_init_set_si(__gen_e_acsl__19,3L); + __gmpz_init(__gen_e_acsl_neg_8); + __gmpz_neg(__gen_e_acsl_neg_8, + (__e_acsl_mpz_struct const *)(__gen_e_acsl__19)); + __gmpz_init_set_si(__gen_e_acsl__20,2L); + __gmpz_init(__gen_e_acsl_neg_9); + __gmpz_neg(__gen_e_acsl_neg_9, + (__e_acsl_mpz_struct const *)(__gen_e_acsl__20)); + __gmpz_init_set_si(__gen_e_acsl__21,0L); + __gen_e_acsl_mod_guard_2 = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_neg_9), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__21)); + __gmpz_init(__gen_e_acsl_mod_2); + /*@ assert E_ACSL: -2 ≢ 0; */ + __e_acsl_assert(! (__gen_e_acsl_mod_guard_2 == 0),(char *)"Assertion", + (char *)"main",(char *)"-2 == 0",20); + __gmpz_tdiv_r(__gen_e_acsl_mod_2, + (__e_acsl_mpz_struct const *)(__gen_e_acsl_neg_8), + (__e_acsl_mpz_struct const *)(__gen_e_acsl_neg_9)); + __gmpz_init_set_si(__gen_e_acsl__22,1L); + __gmpz_init(__gen_e_acsl_neg_10); + __gmpz_neg(__gen_e_acsl_neg_10, + (__e_acsl_mpz_struct const *)(__gen_e_acsl__22)); + __gen_e_acsl_eq_9 = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_mod_2), + (__e_acsl_mpz_struct const *)(__gen_e_acsl_neg_10)); + __e_acsl_assert(__gen_e_acsl_eq_9 == 0,(char *)"Assertion", + (char *)"main",(char *)"-3 % -2 == -1",20); + __gmpz_clear(__gen_e_acsl__19); + __gmpz_clear(__gen_e_acsl_neg_8); + __gmpz_clear(__gen_e_acsl__20); + __gmpz_clear(__gen_e_acsl_neg_9); + __gmpz_clear(__gen_e_acsl__21); + __gmpz_clear(__gen_e_acsl_mod_2); + __gmpz_clear(__gen_e_acsl__22); + __gmpz_clear(__gen_e_acsl_neg_10); + } + /*@ assert 3 % -2 ≡ 1; */ + { + __e_acsl_mpz_t __gen_e_acsl__23; + __e_acsl_mpz_t __gen_e_acsl__24; + __e_acsl_mpz_t __gen_e_acsl_neg_11; + __e_acsl_mpz_t __gen_e_acsl__25; + int __gen_e_acsl_mod_guard_3; + __e_acsl_mpz_t __gen_e_acsl_mod_3; + __e_acsl_mpz_t __gen_e_acsl__26; + int __gen_e_acsl_eq_10; + __gmpz_init_set_si(__gen_e_acsl__23,3L); + __gmpz_init_set_si(__gen_e_acsl__24,2L); + __gmpz_init(__gen_e_acsl_neg_11); + __gmpz_neg(__gen_e_acsl_neg_11, + (__e_acsl_mpz_struct const *)(__gen_e_acsl__24)); + __gmpz_init_set_si(__gen_e_acsl__25,0L); + __gen_e_acsl_mod_guard_3 = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_neg_11), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__25)); + __gmpz_init(__gen_e_acsl_mod_3); + /*@ assert E_ACSL: -2 ≢ 0; */ + __e_acsl_assert(! (__gen_e_acsl_mod_guard_3 == 0),(char *)"Assertion", + (char *)"main",(char *)"-2 == 0",21); + __gmpz_tdiv_r(__gen_e_acsl_mod_3, + (__e_acsl_mpz_struct const *)(__gen_e_acsl__23), + (__e_acsl_mpz_struct const *)(__gen_e_acsl_neg_11)); + __gmpz_init_set_si(__gen_e_acsl__26,1L); + __gen_e_acsl_eq_10 = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_mod_3), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__26)); + __e_acsl_assert(__gen_e_acsl_eq_10 == 0,(char *)"Assertion", + (char *)"main",(char *)"3 % -2 == 1",21); + __gmpz_clear(__gen_e_acsl__23); + __gmpz_clear(__gen_e_acsl__24); + __gmpz_clear(__gen_e_acsl_neg_11); + __gmpz_clear(__gen_e_acsl__25); + __gmpz_clear(__gen_e_acsl_mod_3); + __gmpz_clear(__gen_e_acsl__26); + } + /*@ assert ((x * 2 + (3 + y)) - 4) + (x - y) ≡ -10; */ + { + __e_acsl_mpz_t __gen_e_acsl_x_8; + __e_acsl_mpz_t __gen_e_acsl__27; + __e_acsl_mpz_t __gen_e_acsl_mul_2; + __e_acsl_mpz_t __gen_e_acsl__28; + __e_acsl_mpz_t __gen_e_acsl_y; + __e_acsl_mpz_t __gen_e_acsl_add_2; + __e_acsl_mpz_t __gen_e_acsl_add_3; + __e_acsl_mpz_t __gen_e_acsl__29; + __e_acsl_mpz_t __gen_e_acsl_sub_2; + __e_acsl_mpz_t __gen_e_acsl_sub_3; + __e_acsl_mpz_t __gen_e_acsl_add_4; + __e_acsl_mpz_t __gen_e_acsl__30; + __e_acsl_mpz_t __gen_e_acsl_neg_12; + int __gen_e_acsl_eq_11; + __gmpz_init_set_si(__gen_e_acsl_x_8,(long)x); + __gmpz_init_set_si(__gen_e_acsl__27,2L); + __gmpz_init(__gen_e_acsl_mul_2); + __gmpz_mul(__gen_e_acsl_mul_2, + (__e_acsl_mpz_struct const *)(__gen_e_acsl_x_8), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__27)); + __gmpz_init_set_si(__gen_e_acsl__28,3L); + __gmpz_init_set_si(__gen_e_acsl_y,(long)y); + __gmpz_init(__gen_e_acsl_add_2); + __gmpz_add(__gen_e_acsl_add_2, + (__e_acsl_mpz_struct const *)(__gen_e_acsl__28), + (__e_acsl_mpz_struct const *)(__gen_e_acsl_y)); + __gmpz_init(__gen_e_acsl_add_3); + __gmpz_add(__gen_e_acsl_add_3, + (__e_acsl_mpz_struct const *)(__gen_e_acsl_mul_2), + (__e_acsl_mpz_struct const *)(__gen_e_acsl_add_2)); + __gmpz_init_set_si(__gen_e_acsl__29,4L); + __gmpz_init(__gen_e_acsl_sub_2); + __gmpz_sub(__gen_e_acsl_sub_2, + (__e_acsl_mpz_struct const *)(__gen_e_acsl_add_3), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__29)); + __gmpz_init(__gen_e_acsl_sub_3); + __gmpz_sub(__gen_e_acsl_sub_3, + (__e_acsl_mpz_struct const *)(__gen_e_acsl_x_8), + (__e_acsl_mpz_struct const *)(__gen_e_acsl_y)); + __gmpz_init(__gen_e_acsl_add_4); + __gmpz_add(__gen_e_acsl_add_4, + (__e_acsl_mpz_struct const *)(__gen_e_acsl_sub_2), + (__e_acsl_mpz_struct const *)(__gen_e_acsl_sub_3)); + __gmpz_init_set_si(__gen_e_acsl__30,10L); + __gmpz_init(__gen_e_acsl_neg_12); + __gmpz_neg(__gen_e_acsl_neg_12, + (__e_acsl_mpz_struct const *)(__gen_e_acsl__30)); + __gen_e_acsl_eq_11 = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_add_4), + (__e_acsl_mpz_struct const *)(__gen_e_acsl_neg_12)); + __e_acsl_assert(__gen_e_acsl_eq_11 == 0,(char *)"Assertion", + (char *)"main", + (char *)"((x * 2 + (3 + y)) - 4) + (x - y) == -10",23); + __gmpz_clear(__gen_e_acsl_x_8); + __gmpz_clear(__gen_e_acsl__27); + __gmpz_clear(__gen_e_acsl_mul_2); + __gmpz_clear(__gen_e_acsl__28); + __gmpz_clear(__gen_e_acsl_y); + __gmpz_clear(__gen_e_acsl_add_2); + __gmpz_clear(__gen_e_acsl_add_3); + __gmpz_clear(__gen_e_acsl__29); + __gmpz_clear(__gen_e_acsl_sub_2); + __gmpz_clear(__gen_e_acsl_sub_3); + __gmpz_clear(__gen_e_acsl_add_4); + __gmpz_clear(__gen_e_acsl__30); + __gmpz_clear(__gen_e_acsl_neg_12); + } + /*@ assert (0 ≡ 1) ≡ !(0 ≡ 0); */ + { + __e_acsl_mpz_t __gen_e_acsl__31; + __e_acsl_mpz_t __gen_e_acsl__32; + int __gen_e_acsl_eq_12; + __e_acsl_mpz_t __gen_e_acsl__33; + int __gen_e_acsl_eq_13; + __e_acsl_mpz_t __gen_e_acsl__34; + int __gen_e_acsl_not; + __e_acsl_mpz_t __gen_e_acsl__35; + int __gen_e_acsl_eq_14; + __gmpz_init_set_si(__gen_e_acsl__31,0L); + __gmpz_init_set_si(__gen_e_acsl__32,1L); + __gen_e_acsl_eq_12 = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl__31), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__32)); + __gmpz_init_set_si(__gen_e_acsl__33,(long)(__gen_e_acsl_eq_12 == 0)); + __gen_e_acsl_eq_13 = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl__31), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__31)); + __gmpz_init_set_si(__gen_e_acsl__34,(long)(__gen_e_acsl_eq_13 == 0)); + __gen_e_acsl_not = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl__34), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__31)); + __gmpz_init_set_si(__gen_e_acsl__35,(long)(__gen_e_acsl_not == 0)); + __gen_e_acsl_eq_14 = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl__33), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__35)); + __e_acsl_assert(__gen_e_acsl_eq_14 == 0,(char *)"Assertion", + (char *)"main",(char *)"(0 == 1) == !(0 == 0)",25); + __gmpz_clear(__gen_e_acsl__31); + __gmpz_clear(__gen_e_acsl__32); + __gmpz_clear(__gen_e_acsl__33); + __gmpz_clear(__gen_e_acsl__34); + __gmpz_clear(__gen_e_acsl__35); + } + /*@ assert (0 ≤ -1) ≡ (0 > 0); */ + { + __e_acsl_mpz_t __gen_e_acsl__36; + __e_acsl_mpz_t __gen_e_acsl__37; + __e_acsl_mpz_t __gen_e_acsl_neg_13; + int __gen_e_acsl_le; + __e_acsl_mpz_t __gen_e_acsl__38; + int __gen_e_acsl_gt; + __e_acsl_mpz_t __gen_e_acsl__39; + int __gen_e_acsl_eq_15; + __gmpz_init_set_si(__gen_e_acsl__36,0L); + __gmpz_init_set_si(__gen_e_acsl__37,1L); + __gmpz_init(__gen_e_acsl_neg_13); + __gmpz_neg(__gen_e_acsl_neg_13, + (__e_acsl_mpz_struct const *)(__gen_e_acsl__37)); + __gen_e_acsl_le = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl__36), + (__e_acsl_mpz_struct const *)(__gen_e_acsl_neg_13)); + __gmpz_init_set_si(__gen_e_acsl__38,(long)(__gen_e_acsl_le <= 0)); + __gen_e_acsl_gt = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl__36), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__36)); + __gmpz_init_set_si(__gen_e_acsl__39,(long)(__gen_e_acsl_gt > 0)); + __gen_e_acsl_eq_15 = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl__38), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__39)); + __e_acsl_assert(__gen_e_acsl_eq_15 == 0,(char *)"Assertion", + (char *)"main",(char *)"(0 <= -1) == (0 > 0)",26); + __gmpz_clear(__gen_e_acsl__36); + __gmpz_clear(__gen_e_acsl__37); + __gmpz_clear(__gen_e_acsl_neg_13); + __gmpz_clear(__gen_e_acsl__38); + __gmpz_clear(__gen_e_acsl__39); + } + /*@ assert (0 ≥ -1) ≡ (0 ≤ 0); */ + { + __e_acsl_mpz_t __gen_e_acsl__40; + __e_acsl_mpz_t __gen_e_acsl__41; + __e_acsl_mpz_t __gen_e_acsl_neg_14; + int __gen_e_acsl_ge; + __e_acsl_mpz_t __gen_e_acsl__42; + int __gen_e_acsl_le_2; + __e_acsl_mpz_t __gen_e_acsl__43; + int __gen_e_acsl_eq_16; + __gmpz_init_set_si(__gen_e_acsl__40,0L); + __gmpz_init_set_si(__gen_e_acsl__41,1L); + __gmpz_init(__gen_e_acsl_neg_14); + __gmpz_neg(__gen_e_acsl_neg_14, + (__e_acsl_mpz_struct const *)(__gen_e_acsl__41)); + __gen_e_acsl_ge = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl__40), + (__e_acsl_mpz_struct const *)(__gen_e_acsl_neg_14)); + __gmpz_init_set_si(__gen_e_acsl__42,(long)(__gen_e_acsl_ge >= 0)); + __gen_e_acsl_le_2 = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl__40), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__40)); + __gmpz_init_set_si(__gen_e_acsl__43,(long)(__gen_e_acsl_le_2 <= 0)); + __gen_e_acsl_eq_16 = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl__42), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__43)); + __e_acsl_assert(__gen_e_acsl_eq_16 == 0,(char *)"Assertion", + (char *)"main",(char *)"(0 >= -1) == (0 <= 0)",27); + __gmpz_clear(__gen_e_acsl__40); + __gmpz_clear(__gen_e_acsl__41); + __gmpz_clear(__gen_e_acsl_neg_14); + __gmpz_clear(__gen_e_acsl__42); + __gmpz_clear(__gen_e_acsl__43); + } + /*@ assert (0 ≢ 1) ≡ !(0 ≢ 0); */ + { + __e_acsl_mpz_t __gen_e_acsl__44; + __e_acsl_mpz_t __gen_e_acsl__45; + int __gen_e_acsl_ne_2; + __e_acsl_mpz_t __gen_e_acsl__46; + int __gen_e_acsl_ne_3; + __e_acsl_mpz_t __gen_e_acsl__47; + int __gen_e_acsl_not_2; + __e_acsl_mpz_t __gen_e_acsl__48; + int __gen_e_acsl_eq_17; + __gmpz_init_set_si(__gen_e_acsl__44,0L); + __gmpz_init_set_si(__gen_e_acsl__45,1L); + __gen_e_acsl_ne_2 = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl__44), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__45)); + __gmpz_init_set_si(__gen_e_acsl__46,(long)(__gen_e_acsl_ne_2 != 0)); + __gen_e_acsl_ne_3 = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl__44), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__44)); + __gmpz_init_set_si(__gen_e_acsl__47,(long)(__gen_e_acsl_ne_3 != 0)); + __gen_e_acsl_not_2 = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl__47), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__44)); + __gmpz_init_set_si(__gen_e_acsl__48,(long)(__gen_e_acsl_not_2 == 0)); + __gen_e_acsl_eq_17 = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl__46), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__48)); + __e_acsl_assert(__gen_e_acsl_eq_17 == 0,(char *)"Assertion", + (char *)"main",(char *)"(0 != 1) == !(0 != 0)",28); + __gmpz_clear(__gen_e_acsl__44); + __gmpz_clear(__gen_e_acsl__45); + __gmpz_clear(__gen_e_acsl__46); + __gmpz_clear(__gen_e_acsl__47); + __gmpz_clear(__gen_e_acsl__48); + } + /*@ assert (0 ≢ 0) ≡ !(1 ≢ 0); */ + { + __e_acsl_mpz_t __gen_e_acsl__49; + int __gen_e_acsl_ne_4; + __e_acsl_mpz_t __gen_e_acsl__50; + __e_acsl_mpz_t __gen_e_acsl__51; + int __gen_e_acsl_ne_5; + __e_acsl_mpz_t __gen_e_acsl__52; + int __gen_e_acsl_not_3; + __e_acsl_mpz_t __gen_e_acsl__53; + int __gen_e_acsl_eq_18; + __gmpz_init_set_si(__gen_e_acsl__49,0L); + __gen_e_acsl_ne_4 = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl__49), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__49)); + __gmpz_init_set_si(__gen_e_acsl__50,(long)(__gen_e_acsl_ne_4 != 0)); + __gmpz_init_set_si(__gen_e_acsl__51,1L); + __gen_e_acsl_ne_5 = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl__51), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__49)); + __gmpz_init_set_si(__gen_e_acsl__52,(long)(__gen_e_acsl_ne_5 != 0)); + __gen_e_acsl_not_3 = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl__52), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__49)); + __gmpz_init_set_si(__gen_e_acsl__53,(long)(__gen_e_acsl_not_3 == 0)); + __gen_e_acsl_eq_18 = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl__50), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__53)); + __e_acsl_assert(__gen_e_acsl_eq_18 == 0,(char *)"Assertion", + (char *)"main",(char *)"(0 != 0) == !(1 != 0)",30); + __gmpz_clear(__gen_e_acsl__49); + __gmpz_clear(__gen_e_acsl__50); + __gmpz_clear(__gen_e_acsl__51); + __gmpz_clear(__gen_e_acsl__52); + __gmpz_clear(__gen_e_acsl__53); + } + /*@ assert 4 / y ≡ 2; */ + { + __e_acsl_mpz_t __gen_e_acsl__54; + __e_acsl_mpz_t __gen_e_acsl_y_2; + __e_acsl_mpz_t __gen_e_acsl__55; + int __gen_e_acsl_div_guard_3; + __e_acsl_mpz_t __gen_e_acsl_div_3; + __e_acsl_mpz_t __gen_e_acsl__56; + int __gen_e_acsl_eq_19; + __gmpz_init_set_si(__gen_e_acsl__54,4L); + __gmpz_init_set_si(__gen_e_acsl_y_2,(long)y); + __gmpz_init_set_si(__gen_e_acsl__55,0L); + __gen_e_acsl_div_guard_3 = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_y_2), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__55)); + __gmpz_init(__gen_e_acsl_div_3); + /*@ assert E_ACSL: y ≢ 0; */ + __e_acsl_assert(! (__gen_e_acsl_div_guard_3 == 0),(char *)"Assertion", + (char *)"main",(char *)"y == 0",31); + __gmpz_tdiv_q(__gen_e_acsl_div_3, + (__e_acsl_mpz_struct const *)(__gen_e_acsl__54), + (__e_acsl_mpz_struct const *)(__gen_e_acsl_y_2)); + __gmpz_init_set_si(__gen_e_acsl__56,2L); + __gen_e_acsl_eq_19 = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_div_3), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__56)); + __e_acsl_assert(__gen_e_acsl_eq_19 == 0,(char *)"Assertion", + (char *)"main",(char *)"4 / y == 2",31); + __gmpz_clear(__gen_e_acsl__54); + __gmpz_clear(__gen_e_acsl_y_2); + __gmpz_clear(__gen_e_acsl__55); + __gmpz_clear(__gen_e_acsl_div_3); + __gmpz_clear(__gen_e_acsl__56); + } + /*@ assert 1 + (z + 1) / (y - 123456789123456789) ≡ 1; */ + { + __e_acsl_mpz_t __gen_e_acsl__57; + __e_acsl_mpz_t __gen_e_acsl_z; + __e_acsl_mpz_t __gen_e_acsl_add_5; + __e_acsl_mpz_t __gen_e_acsl_y_3; + __e_acsl_mpz_t __gen_e_acsl__58; + __e_acsl_mpz_t __gen_e_acsl_sub_4; + __e_acsl_mpz_t __gen_e_acsl__59; + int __gen_e_acsl_div_guard_4; + __e_acsl_mpz_t __gen_e_acsl_div_4; + __e_acsl_mpz_t __gen_e_acsl_add_6; + int __gen_e_acsl_eq_20; + __gmpz_init_set_si(__gen_e_acsl__57,1L); + __gmpz_init_set_si(__gen_e_acsl_z,z); + __gmpz_init(__gen_e_acsl_add_5); + __gmpz_add(__gen_e_acsl_add_5, + (__e_acsl_mpz_struct const *)(__gen_e_acsl_z), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__57)); + __gmpz_init_set_si(__gen_e_acsl_y_3,(long)y); + __gmpz_init_set_ui(__gen_e_acsl__58,123456789123456789UL); + __gmpz_init(__gen_e_acsl_sub_4); + __gmpz_sub(__gen_e_acsl_sub_4, + (__e_acsl_mpz_struct const *)(__gen_e_acsl_y_3), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__58)); + __gmpz_init_set_si(__gen_e_acsl__59,0L); + __gen_e_acsl_div_guard_4 = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_sub_4), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__59)); + __gmpz_init(__gen_e_acsl_div_4); + /*@ assert E_ACSL: y - 123456789123456789 ≢ 0; */ + __e_acsl_assert(! (__gen_e_acsl_div_guard_4 == 0),(char *)"Assertion", + (char *)"main",(char *)"y - 123456789123456789 == 0",34); + __gmpz_tdiv_q(__gen_e_acsl_div_4, + (__e_acsl_mpz_struct const *)(__gen_e_acsl_add_5), + (__e_acsl_mpz_struct const *)(__gen_e_acsl_sub_4)); + __gmpz_init(__gen_e_acsl_add_6); + __gmpz_add(__gen_e_acsl_add_6, + (__e_acsl_mpz_struct const *)(__gen_e_acsl__57), + (__e_acsl_mpz_struct const *)(__gen_e_acsl_div_4)); + __gen_e_acsl_eq_20 = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_add_6), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__57)); + __e_acsl_assert(__gen_e_acsl_eq_20 == 0,(char *)"Assertion", + (char *)"main", + (char *)"1 + (z + 1) / (y - 123456789123456789) == 1",34); + __gmpz_clear(__gen_e_acsl__57); + __gmpz_clear(__gen_e_acsl_z); + __gmpz_clear(__gen_e_acsl_add_5); + __gmpz_clear(__gen_e_acsl_y_3); + __gmpz_clear(__gen_e_acsl__58); + __gmpz_clear(__gen_e_acsl_sub_4); + __gmpz_clear(__gen_e_acsl__59); + __gmpz_clear(__gen_e_acsl_div_4); + __gmpz_clear(__gen_e_acsl_add_6); + } + /*@ assert 1 - x ≡ -x + 1; */ + { + __e_acsl_mpz_t __gen_e_acsl__60; + __e_acsl_mpz_t __gen_e_acsl_x_9; + __e_acsl_mpz_t __gen_e_acsl_sub_5; + __e_acsl_mpz_t __gen_e_acsl_neg_15; + __e_acsl_mpz_t __gen_e_acsl_add_7; + int __gen_e_acsl_eq_21; + __gmpz_init_set_si(__gen_e_acsl__60,1L); + __gmpz_init_set_si(__gen_e_acsl_x_9,(long)x); + __gmpz_init(__gen_e_acsl_sub_5); + __gmpz_sub(__gen_e_acsl_sub_5, + (__e_acsl_mpz_struct const *)(__gen_e_acsl__60), + (__e_acsl_mpz_struct const *)(__gen_e_acsl_x_9)); + __gmpz_init(__gen_e_acsl_neg_15); + __gmpz_neg(__gen_e_acsl_neg_15, + (__e_acsl_mpz_struct const *)(__gen_e_acsl_x_9)); + __gmpz_init(__gen_e_acsl_add_7); + __gmpz_add(__gen_e_acsl_add_7, + (__e_acsl_mpz_struct const *)(__gen_e_acsl_neg_15), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__60)); + __gen_e_acsl_eq_21 = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_sub_5), + (__e_acsl_mpz_struct const *)(__gen_e_acsl_add_7)); + __e_acsl_assert(__gen_e_acsl_eq_21 == 0,(char *)"Assertion", + (char *)"main",(char *)"1 - x == -x + 1",36); + __gmpz_clear(__gen_e_acsl__60); + __gmpz_clear(__gen_e_acsl_x_9); + __gmpz_clear(__gen_e_acsl_sub_5); + __gmpz_clear(__gen_e_acsl_neg_15); + __gmpz_clear(__gen_e_acsl_add_7); + } + __retres = 0; + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/gmp-only/oracle_ci/gen_functions.c b/src/plugins/e-acsl/tests/gmp-only/oracle_ci/gen_functions.c new file mode 100644 index 0000000000000000000000000000000000000000..bae23e804b7d2fb84f744002042546441c257e2f --- /dev/null +++ b/src/plugins/e-acsl/tests/gmp-only/oracle_ci/gen_functions.c @@ -0,0 +1,479 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +extern int __e_acsl_sound_verdict; + +struct mystruct { + int k ; + int l ; +}; +typedef struct mystruct mystruct; +/*@ predicate p1(int x, int y) = x + y > 0; + */ +int __gen_e_acsl_p1(int x, int y); + +/*@ predicate p2(ℤ x, ℤ y) = x + y > 0; + +*/ +int __gen_e_acsl_p2(int x, int y); + +int __gen_e_acsl_p2_3(int x, __e_acsl_mpz_struct * y); + +/*@ logic ℤ f1(ℤ x, ℤ y) = x + y; + +*/ +void __gen_e_acsl_f1(__e_acsl_mpz_t *__retres_arg, int x, int y); + +void __gen_e_acsl_f1_5(__e_acsl_mpz_t *__retres_arg, int x, + __e_acsl_mpz_struct * y); + +void __gen_e_acsl_f1_7(__e_acsl_mpz_t *__retres_arg, __e_acsl_mpz_struct * x, + __e_acsl_mpz_struct * y); + +/*@ logic char h_char(char c) = c; + */ +int __gen_e_acsl_h_char(int c); + +/*@ logic short h_short(short s) = s; + */ +int __gen_e_acsl_h_short(int s); + +/*@ logic int g_hidden(int x) = x; + */ +int __gen_e_acsl_g_hidden(int x); + +/*@ logic int g(int x) = g_hidden(x); + */ +int __gen_e_acsl_g(int x); + +/*@ logic mystruct t1(mystruct m) = m; + */ +mystruct __gen_e_acsl_t1(mystruct m); + +/*@ logic ℤ t2(mystruct m) = m.k + m.l; + */ +void __gen_e_acsl_t2(__e_acsl_mpz_t *__retres_arg, mystruct m); + +/*@ predicate k_pred(ℤ x) = x > 0; + +*/ +int __gen_e_acsl_k_pred(int x); + +/*@ requires k_pred(x); */ +void __gen_e_acsl_k(int x); + +void k(int x) +{ + return; +} + +int glob = 5; +/*@ predicate never_called(int x) = x ≡ x; + */ +/*@ logic double f2(double x) = (double)(1 / x); + */ +double __gen_e_acsl_f2(double x); + +/*@ predicate p_notyet{L}(ℤ x) = x > 0; + */ +/*@ logic ℤ f_notyet{L}(ℤ x) = x; + +*/ +int main(void) +{ + int __retres; + mystruct m; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + int x = 1; + int y = 2; + /*@ assert p1(x, y); */ + { + int __gen_e_acsl_p1_2; + __gen_e_acsl_p1_2 = __gen_e_acsl_p1(x,y); + __e_acsl_assert(__gen_e_acsl_p1_2,(char *)"Assertion",(char *)"main", + (char *)"p1(x, y)",42); + } + /*@ assert p2(3, 4); */ + { + int __gen_e_acsl_p2_2; + __gen_e_acsl_p2_2 = __gen_e_acsl_p2(3,4); + __e_acsl_assert(__gen_e_acsl_p2_2,(char *)"Assertion",(char *)"main", + (char *)"p2(3, 4)",43); + } + /*@ assert p2(5, 99999999999999999999999999999); */ + { + __e_acsl_mpz_t __gen_e_acsl__3; + int __gen_e_acsl_p2_4; + __gmpz_init_set_str(__gen_e_acsl__3,"99999999999999999999999999999",10); + __gen_e_acsl_p2_4 = __gen_e_acsl_p2_3(5, + (__e_acsl_mpz_struct *)__gen_e_acsl__3); + __e_acsl_assert(__gen_e_acsl_p2_4,(char *)"Assertion",(char *)"main", + (char *)"p2(5, 99999999999999999999999999999)",44); + __gmpz_clear(__gen_e_acsl__3); + } + /*@ assert f1(x, y) ≡ 3; */ + { + __e_acsl_mpz_t __gen_e_acsl_f1_2; + __e_acsl_mpz_t __gen_e_acsl__5; + int __gen_e_acsl_eq; + __gen_e_acsl_f1(& __gen_e_acsl_f1_2,x,y); + __gmpz_init_set_si(__gen_e_acsl__5,3L); + __gen_e_acsl_eq = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_f1_2), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__5)); + __e_acsl_assert(__gen_e_acsl_eq == 0,(char *)"Assertion",(char *)"main", + (char *)"f1(x, y) == 3",46); + __gmpz_clear(__gen_e_acsl_f1_2); + __gmpz_clear(__gen_e_acsl__5); + } + /*@ assert p2(x, f1(3, 4)); */ + { + __e_acsl_mpz_t __gen_e_acsl_f1_4; + int __gen_e_acsl_p2_6; + __gen_e_acsl_f1(& __gen_e_acsl_f1_4,3,4); + /*@ assert + Eva: initialization: + \initialized((__e_acsl_mpz_struct *)__gen_e_acsl_f1_4); + */ + __gen_e_acsl_p2_6 = __gen_e_acsl_p2_3(x, + (__e_acsl_mpz_struct *)__gen_e_acsl_f1_4); + __e_acsl_assert(__gen_e_acsl_p2_6,(char *)"Assertion",(char *)"main", + (char *)"p2(x, f1(3, 4))",47); + __gmpz_clear(__gen_e_acsl_f1_4); + } + /*@ assert f1(9, 99999999999999999999999999999) > 0; */ + { + __e_acsl_mpz_t __gen_e_acsl__6; + __e_acsl_mpz_t __gen_e_acsl_f1_6; + __e_acsl_mpz_t __gen_e_acsl__7; + int __gen_e_acsl_gt_4; + __gmpz_init_set_str(__gen_e_acsl__6,"99999999999999999999999999999",10); + __gen_e_acsl_f1_5(& __gen_e_acsl_f1_6,9, + (__e_acsl_mpz_struct *)__gen_e_acsl__6); + __gmpz_init_set_si(__gen_e_acsl__7,0L); + __gen_e_acsl_gt_4 = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_f1_6), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__7)); + __e_acsl_assert(__gen_e_acsl_gt_4 > 0,(char *)"Assertion",(char *)"main", + (char *)"f1(9, 99999999999999999999999999999) > 0",48); + __gmpz_clear(__gen_e_acsl__6); + __gmpz_clear(__gen_e_acsl_f1_6); + __gmpz_clear(__gen_e_acsl__7); + } + /*@ assert + f1(99999999999999999999999999999, 99999999999999999999999999999) ≡ + 199999999999999999999999999998; + */ + { + __e_acsl_mpz_t __gen_e_acsl__8; + __e_acsl_mpz_t __gen_e_acsl_f1_8; + __e_acsl_mpz_t __gen_e_acsl__9; + int __gen_e_acsl_eq_2; + __gmpz_init_set_str(__gen_e_acsl__8,"99999999999999999999999999999",10); + __gen_e_acsl_f1_7(& __gen_e_acsl_f1_8, + (__e_acsl_mpz_struct *)__gen_e_acsl__8, + (__e_acsl_mpz_struct *)__gen_e_acsl__8); + __gmpz_init_set_str(__gen_e_acsl__9,"199999999999999999999999999998",10); + __gen_e_acsl_eq_2 = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_f1_8), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__9)); + __e_acsl_assert(__gen_e_acsl_eq_2 == 0,(char *)"Assertion", + (char *)"main", + (char *)"f1(99999999999999999999999999999, 99999999999999999999999999999) ==\n199999999999999999999999999998", + 49); + __gmpz_clear(__gen_e_acsl__8); + __gmpz_clear(__gen_e_acsl_f1_8); + __gmpz_clear(__gen_e_acsl__9); + } + /*@ assert g(x) ≡ x; */ + { + int __gen_e_acsl_g_2; + __e_acsl_mpz_t __gen_e_acsl_app; + __e_acsl_mpz_t __gen_e_acsl_x_6; + int __gen_e_acsl_eq_3; + __gen_e_acsl_g_2 = __gen_e_acsl_g(x); + __gmpz_init_set_si(__gen_e_acsl_app,(long)__gen_e_acsl_g_2); + __gmpz_init_set_si(__gen_e_acsl_x_6,(long)x); + __gen_e_acsl_eq_3 = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_app), + (__e_acsl_mpz_struct const *)(__gen_e_acsl_x_6)); + __e_acsl_assert(__gen_e_acsl_eq_3 == 0,(char *)"Assertion", + (char *)"main",(char *)"g(x) == x",53); + __gmpz_clear(__gen_e_acsl_app); + __gmpz_clear(__gen_e_acsl_x_6); + } + char c = (char)'c'; + /*@ assert h_char(c) ≡ c; */ + { + int __gen_e_acsl_h_char_2; + __e_acsl_mpz_t __gen_e_acsl_app_2; + __e_acsl_mpz_t __gen_e_acsl_c; + int __gen_e_acsl_eq_4; + __gen_e_acsl_h_char_2 = __gen_e_acsl_h_char((int)c); + __gmpz_init_set_si(__gen_e_acsl_app_2,(long)__gen_e_acsl_h_char_2); + __gmpz_init_set_si(__gen_e_acsl_c,(long)c); + __gen_e_acsl_eq_4 = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_app_2), + (__e_acsl_mpz_struct const *)(__gen_e_acsl_c)); + __e_acsl_assert(__gen_e_acsl_eq_4 == 0,(char *)"Assertion", + (char *)"main",(char *)"h_char(c) == c",56); + __gmpz_clear(__gen_e_acsl_app_2); + __gmpz_clear(__gen_e_acsl_c); + } + short s = (short)1; + /*@ assert h_short(s) ≡ s; */ + { + int __gen_e_acsl_h_short_2; + __e_acsl_mpz_t __gen_e_acsl_app_3; + __e_acsl_mpz_t __gen_e_acsl_s; + int __gen_e_acsl_eq_5; + __gen_e_acsl_h_short_2 = __gen_e_acsl_h_short((int)s); + __gmpz_init_set_si(__gen_e_acsl_app_3,(long)__gen_e_acsl_h_short_2); + __gmpz_init_set_si(__gen_e_acsl_s,(long)s); + __gen_e_acsl_eq_5 = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_app_3), + (__e_acsl_mpz_struct const *)(__gen_e_acsl_s)); + __e_acsl_assert(__gen_e_acsl_eq_5 == 0,(char *)"Assertion", + (char *)"main",(char *)"h_short(s) == s",58); + __gmpz_clear(__gen_e_acsl_app_3); + __gmpz_clear(__gen_e_acsl_s); + } + m.k = 8; + m.l = 9; + /*@ assert t2(t1(m)) ≡ 17; */ + { + mystruct __gen_e_acsl_t1_2; + __e_acsl_mpz_t __gen_e_acsl_t2_2; + __e_acsl_mpz_t __gen_e_acsl__12; + int __gen_e_acsl_eq_6; + __gen_e_acsl_t1_2 = __gen_e_acsl_t1(m); + __gen_e_acsl_t2(& __gen_e_acsl_t2_2,__gen_e_acsl_t1_2); + __gmpz_init_set_si(__gen_e_acsl__12,17L); + __gen_e_acsl_eq_6 = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_t2_2), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__12)); + __e_acsl_assert(__gen_e_acsl_eq_6 == 0,(char *)"Assertion", + (char *)"main",(char *)"t2(t1(m)) == 17",63); + __gmpz_clear(__gen_e_acsl_t2_2); + __gmpz_clear(__gen_e_acsl__12); + } + __gen_e_acsl_k(9); + double d = 2.0; + /*@ assert f2(d) > 0; */ + { + double __gen_e_acsl_f2_2; + __gen_e_acsl_f2_2 = __gen_e_acsl_f2(d); + __e_acsl_assert(__gen_e_acsl_f2_2 > 0.,(char *)"Assertion", + (char *)"main",(char *)"f2(d) > 0",68); + } + __retres = 0; + return __retres; +} + +/*@ requires k_pred(x); */ +void __gen_e_acsl_k(int x) +{ + { + int __gen_e_acsl_k_pred_2; + __gen_e_acsl_k_pred_2 = __gen_e_acsl_k_pred(x); + __e_acsl_assert(__gen_e_acsl_k_pred_2,(char *)"Precondition",(char *)"k", + (char *)"k_pred(x)",25); + } + k(x); + return; +} + +int __gen_e_acsl_h_char(int c) +{ + return c; +} + +int __gen_e_acsl_h_short(int s) +{ + return s; +} + +int __gen_e_acsl_g_hidden(int x) +{ + return x; +} + +double __gen_e_acsl_f2(double x) +{ + __e_acsl_mpq_t __gen_e_acsl__13; + __e_acsl_mpq_t __gen_e_acsl__14; + __e_acsl_mpq_t __gen_e_acsl_div; + double __gen_e_acsl__15; + __gmpq_init(__gen_e_acsl__13); + __gmpq_set_str(__gen_e_acsl__13,"1",10); + __gmpq_init(__gen_e_acsl__14); + __gmpq_set_d(__gen_e_acsl__14,x); + __gmpq_init(__gen_e_acsl_div); + __gmpq_div(__gen_e_acsl_div, + (__e_acsl_mpq_struct const *)(__gen_e_acsl__13), + (__e_acsl_mpq_struct const *)(__gen_e_acsl__14)); + __gen_e_acsl__15 = __gmpq_get_d((__e_acsl_mpq_struct const *)(__gen_e_acsl_div)); + __gmpq_clear(__gen_e_acsl__13); + __gmpq_clear(__gen_e_acsl__14); + __gmpq_clear(__gen_e_acsl_div); + /*@ assert Eva: is_nan_or_infinite: \is_finite(__gen_e_acsl__15); */ + return __gen_e_acsl__15; +} + +int __gen_e_acsl_g(int x) +{ + int __gen_e_acsl_g_hidden_2; + __gen_e_acsl_g_hidden_2 = __gen_e_acsl_g_hidden(x); + return __gen_e_acsl_g_hidden_2; +} + +mystruct __gen_e_acsl_t1(mystruct m) +{ + return m; +} + +int __gen_e_acsl_p1(int x, int y) +{ + __e_acsl_mpz_t __gen_e_acsl_x; + __e_acsl_mpz_t __gen_e_acsl_y; + __e_acsl_mpz_t __gen_e_acsl_add; + __e_acsl_mpz_t __gen_e_acsl_; + int __gen_e_acsl_gt; + __gmpz_init_set_si(__gen_e_acsl_x,(long)x); + __gmpz_init_set_si(__gen_e_acsl_y,(long)y); + __gmpz_init(__gen_e_acsl_add); + __gmpz_add(__gen_e_acsl_add,(__e_acsl_mpz_struct const *)(__gen_e_acsl_x), + (__e_acsl_mpz_struct const *)(__gen_e_acsl_y)); + __gmpz_init_set_si(__gen_e_acsl_,0L); + __gen_e_acsl_gt = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_add), + (__e_acsl_mpz_struct const *)(__gen_e_acsl_)); + int __retres = __gen_e_acsl_gt > 0; + __gmpz_clear(__gen_e_acsl_x); + __gmpz_clear(__gen_e_acsl_y); + __gmpz_clear(__gen_e_acsl_add); + __gmpz_clear(__gen_e_acsl_); + return __retres; +} + +void __gen_e_acsl_t2(__e_acsl_mpz_t *__retres_arg, mystruct m) +{ + __e_acsl_mpz_t __gen_e_acsl__10; + __e_acsl_mpz_t __gen_e_acsl__11; + __e_acsl_mpz_t __gen_e_acsl_add_7; + __gmpz_init_set_si(__gen_e_acsl__10,(long)m.k); + __gmpz_init_set_si(__gen_e_acsl__11,(long)m.l); + __gmpz_init(__gen_e_acsl_add_7); + __gmpz_add(__gen_e_acsl_add_7, + (__e_acsl_mpz_struct const *)(__gen_e_acsl__10), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__11)); + __gmpz_init_set(*__retres_arg, + (__e_acsl_mpz_struct const *)(__gen_e_acsl_add_7)); + __gmpz_clear(__gen_e_acsl__10); + __gmpz_clear(__gen_e_acsl__11); + __gmpz_clear(__gen_e_acsl_add_7); + return; +} + +int __gen_e_acsl_p2(int x, int y) +{ + __e_acsl_mpz_t __gen_e_acsl_x_2; + __e_acsl_mpz_t __gen_e_acsl_y_2; + __e_acsl_mpz_t __gen_e_acsl_add_2; + __e_acsl_mpz_t __gen_e_acsl__2; + int __gen_e_acsl_gt_2; + __gmpz_init_set_si(__gen_e_acsl_x_2,(long)x); + __gmpz_init_set_si(__gen_e_acsl_y_2,(long)y); + __gmpz_init(__gen_e_acsl_add_2); + __gmpz_add(__gen_e_acsl_add_2, + (__e_acsl_mpz_struct const *)(__gen_e_acsl_x_2), + (__e_acsl_mpz_struct const *)(__gen_e_acsl_y_2)); + __gmpz_init_set_si(__gen_e_acsl__2,0L); + __gen_e_acsl_gt_2 = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_add_2), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__2)); + int __retres = __gen_e_acsl_gt_2 > 0; + __gmpz_clear(__gen_e_acsl_x_2); + __gmpz_clear(__gen_e_acsl_y_2); + __gmpz_clear(__gen_e_acsl_add_2); + __gmpz_clear(__gen_e_acsl__2); + return __retres; +} + +int __gen_e_acsl_p2_3(int x, __e_acsl_mpz_struct * y) +{ + __e_acsl_mpz_t __gen_e_acsl_x_3; + __e_acsl_mpz_t __gen_e_acsl_add_3; + __e_acsl_mpz_t __gen_e_acsl__4; + int __gen_e_acsl_gt_3; + __gmpz_init_set_si(__gen_e_acsl_x_3,(long)x); + __gmpz_init(__gen_e_acsl_add_3); + __gmpz_add(__gen_e_acsl_add_3, + (__e_acsl_mpz_struct const *)(__gen_e_acsl_x_3), + (__e_acsl_mpz_struct const *)(y)); + __gmpz_init_set_si(__gen_e_acsl__4,0L); + __gen_e_acsl_gt_3 = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_add_3), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__4)); + int __retres = __gen_e_acsl_gt_3 > 0; + __gmpz_clear(__gen_e_acsl_x_3); + __gmpz_clear(__gen_e_acsl_add_3); + __gmpz_clear(__gen_e_acsl__4); + return __retres; +} + +int __gen_e_acsl_k_pred(int x) +{ + __e_acsl_mpz_t __gen_e_acsl_x; + __e_acsl_mpz_t __gen_e_acsl_; + int __gen_e_acsl_gt; + __gmpz_init_set_si(__gen_e_acsl_x,(long)x); + __gmpz_init_set_si(__gen_e_acsl_,0L); + __gen_e_acsl_gt = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_x), + (__e_acsl_mpz_struct const *)(__gen_e_acsl_)); + int __retres = __gen_e_acsl_gt > 0; + __gmpz_clear(__gen_e_acsl_x); + __gmpz_clear(__gen_e_acsl_); + return __retres; +} + +void __gen_e_acsl_f1(__e_acsl_mpz_t *__retres_arg, int x, int y) +{ + __e_acsl_mpz_t __gen_e_acsl_x_4; + __e_acsl_mpz_t __gen_e_acsl_y_3; + __e_acsl_mpz_t __gen_e_acsl_add_4; + __gmpz_init_set_si(__gen_e_acsl_x_4,(long)x); + __gmpz_init_set_si(__gen_e_acsl_y_3,(long)y); + __gmpz_init(__gen_e_acsl_add_4); + __gmpz_add(__gen_e_acsl_add_4, + (__e_acsl_mpz_struct const *)(__gen_e_acsl_x_4), + (__e_acsl_mpz_struct const *)(__gen_e_acsl_y_3)); + __gmpz_init_set(*__retres_arg, + (__e_acsl_mpz_struct const *)(__gen_e_acsl_add_4)); + __gmpz_clear(__gen_e_acsl_x_4); + __gmpz_clear(__gen_e_acsl_y_3); + __gmpz_clear(__gen_e_acsl_add_4); + return; +} + +void __gen_e_acsl_f1_5(__e_acsl_mpz_t *__retres_arg, int x, + __e_acsl_mpz_struct * y) +{ + __e_acsl_mpz_t __gen_e_acsl_x_5; + __e_acsl_mpz_t __gen_e_acsl_add_5; + __gmpz_init_set_si(__gen_e_acsl_x_5,(long)x); + __gmpz_init(__gen_e_acsl_add_5); + __gmpz_add(__gen_e_acsl_add_5, + (__e_acsl_mpz_struct const *)(__gen_e_acsl_x_5), + (__e_acsl_mpz_struct const *)(y)); + __gmpz_init_set(*__retres_arg, + (__e_acsl_mpz_struct const *)(__gen_e_acsl_add_5)); + __gmpz_clear(__gen_e_acsl_x_5); + __gmpz_clear(__gen_e_acsl_add_5); + return; +} + +void __gen_e_acsl_f1_7(__e_acsl_mpz_t *__retres_arg, __e_acsl_mpz_struct * x, + __e_acsl_mpz_struct * y) +{ + __e_acsl_mpz_t __gen_e_acsl_add_6; + __gmpz_init(__gen_e_acsl_add_6); + __gmpz_add(__gen_e_acsl_add_6,(__e_acsl_mpz_struct const *)(x), + (__e_acsl_mpz_struct const *)(y)); + __gmpz_init_set(*__retres_arg, + (__e_acsl_mpz_struct const *)(__gen_e_acsl_add_6)); + __gmpz_clear(__gen_e_acsl_add_6); + return; +} + + diff --git a/src/plugins/e-acsl/tests/gmp-only/oracle_dev/arith.res.oracle b/src/plugins/e-acsl/tests/gmp-only/oracle_dev/arith.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..252a6e43c513855c224c72e0dde01bdb64de093c --- /dev/null +++ b/src/plugins/e-acsl/tests/gmp-only/oracle_dev/arith.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/gmp-only/arith.i (no preprocessing) diff --git a/src/plugins/e-acsl/tests/gmp-only/oracle_dev/functions.res.oracle b/src/plugins/e-acsl/tests/gmp-only/oracle_dev/functions.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..6da7a17c6cbd609d91afb9420a61b43173acc0d6 --- /dev/null +++ b/src/plugins/e-acsl/tests/gmp-only/oracle_dev/functions.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/gmp-only/functions.c (with preprocessing) diff --git a/src/plugins/e-acsl/tests/gmp-only/test_config_ci b/src/plugins/e-acsl/tests/gmp-only/test_config_ci new file mode 100644 index 0000000000000000000000000000000000000000..e69447aecb415446e1813d1d1154ecdbb77a0a57 --- /dev/null +++ b/src/plugins/e-acsl/tests/gmp-only/test_config_ci @@ -0,0 +1 @@ +STDOPT: #"-e-acsl-gmp-only" diff --git a/src/plugins/e-acsl/tests/gmp-only/test_config_dev b/src/plugins/e-acsl/tests/gmp-only/test_config_dev new file mode 100644 index 0000000000000000000000000000000000000000..1c9f2ef180f697c6cc7dd5f278be6fe194a8d085 --- /dev/null +++ b/src/plugins/e-acsl/tests/gmp-only/test_config_dev @@ -0,0 +1,4 @@ +MACRO: DEST @PTEST_RESULT@/gen_@PTEST_NAME@ +MACRO: OUT @PTEST_NAME@.res.log +MACRO: ERR @PTEST_NAME@.err.log +EXEC: ./scripts/e-acsl-gcc.sh --gmp -q -c -X --frama-c-extra="-journal-disable -verbose 0 -kernel-warn-key *=inactive" -o @DEST@.run.c -O @DEST@.out @PTEST_FILE@ > @PTEST_RESULT@/@OUT@ 2> @PTEST_RESULT@/@ERR@ && ./@DEST@.e-acsl > /dev/null diff --git a/src/plugins/e-acsl/tests/memory/addrOf.i b/src/plugins/e-acsl/tests/memory/addrOf.i new file mode 100644 index 0000000000000000000000000000000000000000..c797facb0f9c1ea90d23dd783c7e380668314ce0 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/addrOf.i @@ -0,0 +1,18 @@ +/* run.config + COMMENT: addrOf +*/ + +void f(){ + int m, *u, *p; + u = &m; + p = u; + m = 123; + //@ assert \initialized(p); +} + +int main(void) { + int x = 0; + f(); + /*@ assert &x == &x; */ ; + return 0; +} diff --git a/src/plugins/e-acsl/tests/memory/alias.i b/src/plugins/e-acsl/tests/memory/alias.i new file mode 100644 index 0000000000000000000000000000000000000000..b72de86ae978b540858d26329699dfd86a06e538 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/alias.i @@ -0,0 +1,16 @@ +/* run.config + COMMENT: alias +*/ + +void f(int* dest, int val) +{ + int *ptr = dest; + *ptr = val; +} + +int main() { + int i; + f(&i, 255); + /*@ assert \initialized(&i); */ + return 0; +} diff --git a/src/plugins/e-acsl/tests/memory/base_addr.c b/src/plugins/e-acsl/tests/memory/base_addr.c new file mode 100644 index 0000000000000000000000000000000000000000..ad6c77d4a2ef7c556bd1979fe1808d30fa84f14a --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/base_addr.c @@ -0,0 +1,64 @@ +/* run.config + * COMMENT: Behaviours of the \base_addr E-ACSL predicate +*/ + +#include <stdlib.h> + +int A[] = { 1, 2, 3, 4}; +int *PA; + +int main(void) { + /* Global memory */ + PA = (int*)&A; + /*@ assert \base_addr(&A[0]) == \base_addr(&A); */ + /*@ assert \base_addr(&A[0]) == \base_addr(PA); */ + /*@ assert \base_addr(A+3) == \base_addr(PA); */ + PA++; + /*@ assert \base_addr(PA) == \base_addr(&A[0]); */ + /*@ assert \base_addr(PA+2) == \base_addr(A+3); */ + + /* Stack memory [long blocks] */ + int a[] = { 1, 2, 3, 4 }; + int *pa; + pa = (int*)&a; + + /*@ assert \base_addr(&a[0]) == \base_addr(&a); */ + /*@ assert \base_addr(&a[0]) == \base_addr(pa); */ + /*@ assert \base_addr(a+3) == \base_addr(pa); */ + pa++; + /*@ assert \base_addr(pa) == \base_addr(&a[0]); */ + /*@ assert \base_addr(pa+2) == \base_addr(&a[0]); */ + + /* Stack memory [Short blocks] */ + long l = 4; + char *pl = (char*)&l; + /*@ assert \base_addr(&l) == \base_addr(pl); */ + /*@ assert \base_addr(pl+2) == \base_addr(&l); */ + short *pi = (short*)&l; + pi++; + pl++; + /*@ assert \base_addr(pi) == \base_addr(pl); */ + /*@ assert \base_addr(pl) == \base_addr(&l); */ + + /* Heap memory [single segment] */ + char *p = malloc(12); + char *pd = p; + /*@ assert \base_addr(p) == \base_addr(pd); */ + /*@ assert \base_addr(p+1) == \base_addr(pd+5); */ + /*@ assert \base_addr(p+11) == \base_addr(pd+1); */ + p += 5; + /*@ assert \base_addr(p+5) == \base_addr(pd); */ + /*@ assert \base_addr(p-5) == \base_addr(pd); */ + + /* Heap memory [multiple segments] */ + long *q = malloc(30*sizeof(long)); + long *qd = q; + + /*@ assert \base_addr(q) == \base_addr(qd); */ + q++; + /*@ assert \base_addr(q) == \base_addr(qd); */ + q += 2; + /*@ assert \base_addr(q) == \base_addr(qd); */ + q += 4; + /*@ assert \base_addr(q) == \base_addr(qd); */ +} diff --git a/src/plugins/e-acsl/tests/memory/block_length.c b/src/plugins/e-acsl/tests/memory/block_length.c new file mode 100644 index 0000000000000000000000000000000000000000..d06573ba766b34b0506be8de5aafd5d3c49d0670 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/block_length.c @@ -0,0 +1,62 @@ +/* run.config + COMMENT: Behaviours of the \block_length E-ACSL predicate +*/ + +#include <stdlib.h> + +int A[] = { 1, 2, 3, 4}; +int *PA; + +struct Zero { } ZERO; + +int main(void) { + /* Zero-sized blocks */ + struct Zero zero; + /*@ assert \block_length(&ZERO) == 0; */ + /*@ assert \block_length(&zero) == 0; */ + + /* Global memory */ + PA = (int*)&A; + /*@ assert \block_length(&A[0]) == sizeof(A); */ + /*@ assert \block_length(A+3) == sizeof(A); */ + /*@ assert \block_length(PA) == sizeof(A); */ + PA++; + /*@ assert \block_length(PA+1) == \block_length(A+1); */ + + /* Stack memory [long blocks] */ + int a[] = { 1, 2, 3, 4}; + int *pa = (int*)&a; + /*@ assert \block_length(&a[0]) == sizeof(a); */ + /*@ assert \block_length(a+3) == sizeof(a); */ + /*@ assert \block_length(pa) == sizeof(a); */ + pa++; + /*@ assert \block_length(pa+1) == \block_length(a+1); */ + + /* Stack memory [Short blocks] */ + + long l = 4; + char *pl = (char*)&l; + /*@ assert \block_length(&l) == sizeof(long); */ + /*@ assert \block_length(pl) == sizeof(long); */ + /*@ assert \block_length(pl+7) == sizeof(long); */ + int *pi = (int*)&l; + /*@ assert \block_length(pi) == \block_length(&l); */ + pi++; + /*@ assert \block_length(pi) == \block_length(&l); */ + + /* Heap memory [single segment] */ + size_t size = 12; + char *p = malloc(size); + /*@ assert \block_length(p) == size; */ + /*@ assert \block_length(p+11) == size; */ + p += 5; + /*@ assert \block_length(p+5) == \block_length(p-5); */ + + /* Heap memory [multiple segments] */ + size = 30*sizeof(long); + long *q = malloc(size); + + /*@ assert \block_length(q) == size; */ + q += 4; + /*@ assert \block_length(q) == size; */ +} diff --git a/src/plugins/e-acsl/tests/memory/block_valid.c b/src/plugins/e-acsl/tests/memory/block_valid.c new file mode 100644 index 0000000000000000000000000000000000000000..fcda2fa54e15112b86b9bebe3dbdf4dcbe008d81 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/block_valid.c @@ -0,0 +1,56 @@ +/* run.config + COMMENT: Check violations related to accessing an allocated memory block + COMMENT: through a pointer to another block +*/ + +#include <stdlib.h> +#include <stdint.h> + +#define ADDROF(_a) ((uintptr_t)_a) + +int A = 1, + B = 2, + C = 3; + +int main(int argc, char **argv) { + int *p = NULL, + *q = NULL; + + int a = 1, + b = 2, + c = 3; + + p = &b; + /*@assert \valid(p); */ + /* `p` points to `b`, `p+1` accesses either `a` or `c` */ + /*@assert ! \valid(p+1); */ + + p = &B; + /*@assert \valid(p); */ + /* `p` points to `B`, `p+1` accesses either `A` or `C` */ + /*@assert ! \valid(p+1); */ + + char *pmin = (char*)malloc(sizeof(int)); + char *pmax = (char*)malloc(sizeof(int)); + + /* Since `pmin` is allocated before `pmax` it is likely that the start + * address of `pmin` is less than the start address of `pmax`, still, + * just in case, make sure it is true and swap the addresses otherwise. */ + if (ADDROF(pmin) > ADDROF(pmax)) { + char *t = pmin; + pmin = pmax; + pmax = t; + } + + *pmin = 'P'; + *pmax = 'L'; + + int diff = (uintptr_t)pmax - (uintptr_t)pmin; + /*@assert \valid(pmin); */ + /*@assert \valid(pmax); */ + /* Access `pmax` through `pmin` */ + /*@assert ! \valid(pmin + diff); */ + /* Access `pmin` through `pmax` */ + /*@assert ! \valid(pmax - diff); */ + return 0; +} diff --git a/src/plugins/e-acsl/tests/memory/bypassed_var.c b/src/plugins/e-acsl/tests/memory/bypassed_var.c new file mode 100644 index 0000000000000000000000000000000000000000..5201ef5f9cd6a62ba688ec1779d9c91deb5de918 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/bypassed_var.c @@ -0,0 +1,16 @@ +/* run.config + COMMENT: Variable, which declaration is bypassed by a goto jump +*/ + +int main(int argc, char const **argv) { + goto L; + { + int *p; + L: + p = &argc; /* Important to keep this statement here to make sure + initialize is ran after store_block */ + + /*@ assert \valid(&p); */ + } + return 0; +} diff --git a/src/plugins/e-acsl/tests/memory/call.c b/src/plugins/e-acsl/tests/memory/call.c new file mode 100644 index 0000000000000000000000000000000000000000..6d6cdccc6bd2d86d1844dd738d16bf22220a03d3 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/call.c @@ -0,0 +1,18 @@ +/* run.config + COMMENT: function call +*/ + +#include <stdlib.h> + +/*@ ensures \valid(\result); */ +int *f(int *x, int *y) { + *y = 1; + return x; +} + +int main() { + int x = 0, *p, *q = malloc(sizeof(int)), *r = malloc(sizeof(int)); + p = f(&x, q); + q = f(&x, r); + return 0; +} diff --git a/src/plugins/e-acsl/tests/memory/compound_initializers.c b/src/plugins/e-acsl/tests/memory/compound_initializers.c new file mode 100644 index 0000000000000000000000000000000000000000..81f941e4e954169b232c951e0a0dbb7b5599a1cd --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/compound_initializers.c @@ -0,0 +1,45 @@ +/* run.config + COMMENT: Compound initializers +*/ + + + +int _F; + +char *_A[2] = { "XX", "YY" }; +char *_B = "ZZ"; +char *_C; +int _D[] = { 44, 88 }; +int _E = 44; +int _F = 9;; + +struct ST { + char *str; + int num; +}; + +struct ST _G[] = { + { + .str = "First", + .num = 99 + }, + { + .str = "Second", + .num = 147 + } +}; + +int main(int argc, char **argv) { + /*@ assert \valid(&_A[0]); */ + /*@ assert \valid_read(_A[0]); */ + /*@ assert \valid_read(_A[1]); */ + /*@ assert \valid_read(_B); */ + /*@ assert \valid(&_C); */ + /*@ assert \valid(&_D[0]); */ + /*@ assert \valid(&_E); */ + /*@ assert \valid(&_F); */ + /*@ assert _E == 44; */ + /*@ assert \valid(&_G); */ + /*@ assert _G[0].num == 99; */ + return 0; +} diff --git a/src/plugins/e-acsl/tests/memory/constructor.c b/src/plugins/e-acsl/tests/memory/constructor.c new file mode 100644 index 0000000000000000000000000000000000000000..6600992870e3d1809cb467a56479b9060ad9bfdc --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/constructor.c @@ -0,0 +1,18 @@ +/* run.config + COMMENT: bts #2405. Memory not initialized for code executed before main. +*/ + +#include <stdio.h> +#include <stdlib.h> + +__attribute__((constructor)) +void f() { + printf("f\n"); + char *buf = (char*)malloc(10*sizeof(char)); + free(buf); +} + +int main() { + printf("main\n"); + return 0; +} \ No newline at end of file diff --git a/src/plugins/e-acsl/tests/memory/ctype_macros.c b/src/plugins/e-acsl/tests/memory/ctype_macros.c new file mode 100644 index 0000000000000000000000000000000000000000..b4ba9cc170ec6cadc01cb6fc81276bc31e3def48 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/ctype_macros.c @@ -0,0 +1,41 @@ +/* run.config_ci, run.config_dev + COMMENT: Tests for function-based implementation of ctype.h features +*/ + +/* ctype.h tests (e.g., `isalpha`, `isnumber` etc) in GLIBC are implemented as + macro-definitions featuring `__ctype_b_loc` function which returns an address + of an array with locale-specific data. Because of Frama-C normalization below + snippet: + char c = isupper(argc); + char *d = &c; + is approximately as follows: + char c; + unsigned short const **tmp; + char *d; + tmp = __ctype_b_loc(); + d = &c; + Since no implementation of `__ctype_b_loc` is provided, its return address + is not recorded (the bounds of the array are also implementation specific). + Then, `d` points to some internal array on stack and the assertion below + does not hold (while it should). + + This test checks that E-ACSL uses function-based implementations of ctype + tests (by defining __NO_CTYPE macro during preprocessing). Thus, the + normalized code should resemble the below snippet: + char c; + int tmp; + char *d; + tmp = isupper(argc); + c = (char)tmp; + d = & c; + Notably, since isupper returns an int, `d` points to `c` (on stack) and + therefore the assertion holds. */ + +#include <ctype.h> + +int main(int argc, const char **argv) { + char c = isupper(argc); + char *d = &c; + /*@ assert \valid(d); */ + return 0; +} diff --git a/src/plugins/e-acsl/tests/memory/early_exit.c b/src/plugins/e-acsl/tests/memory/early_exit.c new file mode 100644 index 0000000000000000000000000000000000000000..854a04a5573959c997e56c8ba44383e8bf05fb89 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/early_exit.c @@ -0,0 +1,161 @@ +/* run.config + COMMENT: test that local variables within a scope are removed from tracking + even if the execution exists the scope early via goto, break or + continue. +*/ + +/* Simple test case from BTS (#1740) */ +int goto_bts() { + int *p; + { + int a = 0; + p = &a; + /*@ assert \valid(p); */ + goto L; + } + +L: + /*@ assert ! \valid(p); */ + return 0; +} + +/* Make sure that when `goto` jumps over several scopes all locals + * from those scopes are removed. */ +int goto_valid() { + int a = 9; + int *p, *q, *r; + { + int a1 = 0; + p = &a1; + { + int a2 = 0; + q = &a2; + { + int a3 = 0; + r = &a3; + + goto FIRST; + /* Dead code */ + p = (void*)0; + r = q = &a; + } + } +FIRST: + /* At this point `a1` is still in scope, while `a2` and `a3` are not, thus + * `q` and `r` become invalid, whereas `p` is still valid. */ + /*@ assert \valid(p); */ + /*@ assert ! \valid(q); */ + /*@ assert ! \valid(r); */ + /* The following `goto` invalidates `p`. */ + goto SECOND; + /* Dead code */ + p = r = q = &a; + } + +SECOND: + /*@ assert ! \valid(p); */ + /*@ assert ! \valid(q); */ + /*@ assert ! \valid(r); */ + return 0; +} + +/* Make sure that when a break statement is executed within a switch statement + * then all local variables declared within that switch are removed. */ +int switch_valid() { + int i = 1; + int *p, *q, *s; + { + s = &i; + switch(i) { + default: { + int a1 = 0; + p = &a1; + { + int a2 = 0; + q = &a2; + /*@ assert \valid(p); */ + /*@ assert \valid(q); */ + /*@ assert \valid(s); */ + break; + } + /* Dead code */ + p = q = &i; + s = (void*)0; + } + } + /* Break invalidates `p` and `q` but `s` is still in scope. */ + /*@ assert ! \valid(q); */ + /*@ assert ! \valid(p); */ + /*@ assert \valid(s); */ + } + return 0; +} + +/* Same as switch_valid but for a break statement in a body of a loop. */ +int while_valid() { + int *p, *q, *r; + int i = 5; + { + int a0 = 0; + r = &a0; + while (--i) { + { + int a1 = 0; + p = &a1; + { + int a2 = 0; + q = &a2; + /*@ assert \valid(p); */ + /*@ assert \valid(q); */ + /*@ assert \valid(r); */ + if (!i) + break; + } + } + } + /*@ assert ! \valid(p); */ + /*@ assert ! \valid(q); */ + /*@ assert \valid(r); */ + } + return 0; +} + +/* Make sure that when `continue` is executed then local variables in scope + * are not recorded twice. */ +void continue_valid() { + int i = 0; + int *p, *q; + + while (i++) { + /*@ assert ! \valid(p); */ + /*@ assert ! \valid(q); */ + int a1 = 1; + p = &a1; + + /*@ assert \valid(p); */ + /*@ assert ! \valid(q); */ + + { + int a2 = 1; + q = &a2; + /*@ assert \valid(p); */ + /*@ assert \valid(q); */ + continue; + } + + if (i == 5) + break; + } + + /*@ assert ! \valid(p); */ + /*@ assert ! \valid(q); */ +} + +int main(int argc, const char *argv[]) { + goto_bts(); + goto_valid(); + switch_valid(); + while_valid(); + continue_valid(); + return 0; +} diff --git a/src/plugins/e-acsl/tests/memory/errno.c b/src/plugins/e-acsl/tests/memory/errno.c new file mode 100644 index 0000000000000000000000000000000000000000..6cd40348bb2e39ca76689f198b44d834211470c1 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/errno.c @@ -0,0 +1,13 @@ +/* run.config + COMMENT: Check whether location of errno is recorded +*/ + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> + +int main(int argc, const char **argv) { + int *p = &errno; + /*@ assert \valid(p); */ + return 0; +} diff --git a/src/plugins/e-acsl/tests/memory/freeable.c b/src/plugins/e-acsl/tests/memory/freeable.c new file mode 100644 index 0000000000000000000000000000000000000000..86422bb512c3b18e9e6e5fadc6f0d3ec4b3aad9f --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/freeable.c @@ -0,0 +1,25 @@ +/* run.config + COMMENT: \freeable +*/ + +#include <stdlib.h> + +extern void *malloc(size_t p); +extern void free(void* p); + +char array[1024]; + +int main(void) { + int *p; + /*@ assert ! \freeable(p); */ + /*@ assert ! \freeable((void*)0); */ + p = (int*)malloc(4*sizeof(int)); + /*@ assert ! \freeable(p+1); */ + /*@ assert \freeable(p); */ + free(p); + /*@ assert ! \freeable(p); */ + + // test cases for BTS #1830 + /*@ assert ! \freeable(&(array[0])); */ + /*@ assert ! \freeable(&(array[5])); */ +} diff --git a/src/plugins/e-acsl/tests/memory/goto.c b/src/plugins/e-acsl/tests/memory/goto.c new file mode 100644 index 0000000000000000000000000000000000000000..9369b871b5a9e886f1c485ff19ff4020009bc910 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/goto.c @@ -0,0 +1,17 @@ +/* run.config + COMMENT: check a fix of a bug which occured when a [full_init] stmt is + COMMENT: generated for a labeled statement which a goto points to. + COMMENT: test both backward and forward gotos. +*/ + +char a; + +int main(void) { + char *b; + goto _LOR; + _LOR: b = &a; + if (a) goto _LOR; // dead code in order to prevent infinite loop + // but still meaningfull in term of code generated by E-ACSL + /*@ assert \initialized(b); */ + return 0; +} diff --git a/src/plugins/e-acsl/tests/memory/hidden_malloc.c b/src/plugins/e-acsl/tests/memory/hidden_malloc.c new file mode 100644 index 0000000000000000000000000000000000000000..a33c036ea74cbcf53c637f434e6cb2af885841de --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/hidden_malloc.c @@ -0,0 +1,13 @@ +/* run.config + COMMENT: Malloc executed by a library function +*/ + +#include <limits.h> +#include <stdlib.h> + +int main(int argc, const char **argv) { + /* If the second argument of `realpath` is NULL it uses malloc. + Make sure that memory layout has been initialized. */ + char *cwd = realpath(".", NULL); + return 0; +} diff --git a/src/plugins/e-acsl/tests/memory/init.c b/src/plugins/e-acsl/tests/memory/init.c new file mode 100644 index 0000000000000000000000000000000000000000..8f2372a2f2eccb17a2f4b3ac03b570e0093cb60f --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/init.c @@ -0,0 +1,12 @@ +/* run.config + COMMENT: initialization of globals (bts #1818) +*/ + +int a = 0, b; + +int main(void) { + int *p = &a, *q = &b; + /*@assert \initialized(&b) ; */ + /*@assert \initialized(q) ; */ + /*@assert \initialized(p) ; */ +} diff --git a/src/plugins/e-acsl/tests/memory/init_function.c b/src/plugins/e-acsl/tests/memory/init_function.c new file mode 100644 index 0000000000000000000000000000000000000000..133c99f201d3abf69712aa1ea43009fa053e69eb --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/init_function.c @@ -0,0 +1,13 @@ +/* run.config + COMMENT: Check if the instrumentation engine still adds __e_acsl_memory init + COMMENT: is inserted for the case when no malloc is used but no no variable + COMMENT: is required tracking +*/ + +#include <stdlib.h> + +int main(void) { + /* @assert (__heap_allocation_size == 0); */ + char *a = malloc(7); + /* @assert (__heap_allocation_size == 7); */ +} diff --git a/src/plugins/e-acsl/tests/memory/initialized.c b/src/plugins/e-acsl/tests/memory/initialized.c new file mode 100644 index 0000000000000000000000000000000000000000..4af4918caa2b7445e02f84fe3e115ef369e3f150 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/initialized.c @@ -0,0 +1,126 @@ +/* run.config + COMMENT: Behaviours of the \initialized E-ACSL predicate +*/ + +#include <stdlib.h> + +int A = 0; +int B; + +#define ODD(_n) (_n%2 != 0) + +int main(void) { + /* All globals are initialized, even if the initializer is not given */ + int *p = &A; + int *q = &B; + /*@assert \initialized(&A) ; */ + /*@assert \initialized(&B) ; */ + /*@assert \initialized(p) ; */ + /*@assert \initialized(q) ; */ + + /* A local variable without an initializer is uninitialized */ + int a = 0; + int b; + long *r; + long c[2] = { 1, 1 }; + long d[2]; + p = &a; + q = &b; + + /*@assert \initialized(&a) ; */ + /*@assert ! \initialized(&b) ; */ + /*@assert \initialized(p) ; */ + /*@assert ! \initialized(q) ; */ + /*@assert \initialized(&c) ; */ + /*@assert ! \initialized(&d) ; */ + + /* Local variables can also be initialized by assignments */ + b = 0; + /*@assert \initialized(q); */ + /*@assert \initialized(&b); */ + + r = d; + /*@assert ! \initialized(&d[0]); */ + /*@assert ! \initialized(d+1); */ + /*@assert ! \initialized(&d); */ + /*@assert ! \initialized(r); */ + /*@assert ! \initialized(r+1); */ + + d[0] = 1; + /*@assert \initialized(&d[0]); */ + /*@assert ! \initialized(d+1); */ + /*@assert ! \initialized(&d); */ + /*@assert \initialized(r); */ + /*@assert ! \initialized(r+1); */ + + d[1] = 1; + /*@assert \initialized(&d[0]); */ + /*@assert \initialized(d+1); */ + /*@assert \initialized(&d); */ + /*@assert \initialized(r); */ + /*@assert \initialized(r+1); */ + + /* Malloc allocates un-initialized memory */ + p = (int*)malloc(sizeof(int*)); + /*@assert ! \initialized(p); */ + + /* Calloc allocates initialized memory */ + q = (int*)calloc(1, sizeof(int)); + /*@ assert \initialized(q); */ + + /* Block reallocared using `realloc' carries initialization of the + * existing fragment but does not initialize the newly allocated one */ + q = (int*)realloc(q, 2*sizeof(int)); + /*@assert \initialized(q); */ + q++; + /*@assert ! \initialized(q); */ + q--; + + /* An initialized on an un-allocated region is always false. This does not + * lead to undefined bevaviours in production mode or assertion failures in + * debug mode. */ + free(p); + free(q); + /*@assert ! \initialized(p); */ + /*@assert ! \initialized(q); */ + + /* Spoofing access to a non-existing stack address */ + q = (int*)(&q - 1024*5); + /*assert ! \initialized(q); */ + + /* Spoofing access to a non-existing global address */ + q = (int*)128; + /*@assert ! \initialized(q); */ + + p = NULL; + /*@assert ! \initialized(p); */ + + /* Partial initialization */ + int size = 100; + char *partsc = (char*)malloc(size*sizeof(char)); + char *partsi = (char*)malloc(size*sizeof(int)); + + for (int i = 0; i < size; i++) { + if (ODD(i)) + partsc[i] = '0'; + else + partsi[i] = 0; + } + + for (int i = 0; i < size; i++) { + if (ODD(i)) { + /* @assert \initialized(partsc + i); */ + /* @assert ! \initialized(partsi + i); */ + } else { + /* @assert \initialized(partsi + i); */ + /* @assert ! \initialized(partsc + i); */ + } + } + + /* Check duplicate initialization does not affect correct count of + * initialized bits (relevant for bittree model). */ + int dup [2]; + dup[0] = 1; + dup[0] = 1; + /* @assert ! \initialized(&dup); */ +} diff --git a/src/plugins/e-acsl/tests/memory/literal_string.i b/src/plugins/e-acsl/tests/memory/literal_string.i new file mode 100644 index 0000000000000000000000000000000000000000..553b9e3ed0dbcd42b9cf1841bc7d3c0facc87db8 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/literal_string.i @@ -0,0 +1,39 @@ +/* run.config + COMMENT: literal string +*/ + +int main(void); + +char *T = "bar"; +int G = 0; + +void f(void) { + /*@ assert T[G] == 'b'; */ ; + G++; +} + +char *S = "foo"; +char *S2 = "foo2"; +int IDX = 1; +int G2 = 2; + +const char *s_str = "the cat"; +const char *l_str = "the dog and the cat"; + +int main(void) { + char *SS = "ss"; + /*@ assert S[G2] == 'o'; */ + /*@ assert \initialized(S); */ + /*@ assert \valid_read(S2); */ + /*@ assert ! \valid(SS); */ + f(); + + /* Make sure that compiler does not "merge strings", i.e., represents literal + * strings as separate memory blocks. An assertion enabled in the debug mode + * fails the execution if `s_str` is used as a part of `l_str`. */ + s_str++; + l_str++; + return 0; +} + +char *U = "baz"; diff --git a/src/plugins/e-acsl/tests/memory/local_goto.c b/src/plugins/e-acsl/tests/memory/local_goto.c new file mode 100644 index 0000000000000000000000000000000000000000..2defb67029366fd074c7708a3103dc7431a9947e --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/local_goto.c @@ -0,0 +1,43 @@ +/* run.config + COMMENT: Check that deleting statements before goto jumps takes into + COMMENT: account variable declarations given via local inits +*/ +#include <stdio.h> + +#define describe(lab) \ + printf("t is %d, going to %s\n", t, #lab) + +int main(int argc, const char **argv) { + int t = 0; + + { +UP: + if (t == 2) { + describe(RET); + goto RET; + } + } + +AGAIN: + { + int a; + a = 1; + /*@assert \valid(&a); */ + + if (t == 2) { + describe(UP); + /* When jumping to UP label we need to make sure that the + program transformation does not insert a call deleting [b]. */ + goto UP; + } else + t++; + + int b = 15; + /*@assert \valid(&b); */ + describe(AGAIN); + goto AGAIN; + } + +RET: + return 0; +} diff --git a/src/plugins/e-acsl/tests/memory/local_init.c b/src/plugins/e-acsl/tests/memory/local_init.c new file mode 100644 index 0000000000000000000000000000000000000000..3f088213229d0076f623744b7ba65444efd8ce00 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/local_init.c @@ -0,0 +1,18 @@ +/* run.config_ci + COMMENT: test of a local initializer which contains an annotation + LOG: gen_@PTEST_NAME@.c + STDOPT: #"-lib-entry -eva -e-acsl-prepare -e-acsl-share ./share/e-acsl -then -no-lib-entry" +*/ + +int X = 0; +int *p = &X; + +int f(void) { + int x = *p; // Eva's alarm in -lib-entry on this local initializer + return x; +} + +int main(void) { + f(); + return 0; +} diff --git a/src/plugins/e-acsl/tests/memory/local_var.c b/src/plugins/e-acsl/tests/memory/local_var.c new file mode 100644 index 0000000000000000000000000000000000000000..e7239f6e861bcb73cba7ea12b285d572d58e2523 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/local_var.c @@ -0,0 +1,26 @@ +/* run.config + COMMENT: allocation and de-allocation of local variables +*/ + +#include <stdlib.h> + +struct list { + int element; + struct list * next; +}; + +struct list * add(struct list * l, int i) { + struct list * new; + new = malloc(sizeof(struct list)); + /*@ assert \valid(new); */ + new->element = i; + new->next = l; + return new; +} + +int main() { + struct list * l = NULL; + l = add(l, 4); + l = add(l, 7); + return 0; +} diff --git a/src/plugins/e-acsl/tests/memory/mainargs.c b/src/plugins/e-acsl/tests/memory/mainargs.c new file mode 100644 index 0000000000000000000000000000000000000000..19bfe02f55227e1f4a3e7e54b8f800de8e10be62 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/mainargs.c @@ -0,0 +1,22 @@ +/* run.config + COMMENT: the contents of argv should be valid +*/ + +#include <string.h> + +/*@ requires \valid(&argc); + @ requires \valid(&argv); */ +int main(int argc, char **argv) { + int i; + + /*@ assert \forall int k; 0 <= k && k < argc ==> \valid(argv + k) ; */ + /*@ assert \block_length(argv) == (argc+1)*sizeof(char*) ; */ + + /*@ assert argv[argc] == \null ; */ + /*@ assert ! \valid(argv[argc]) ; */ + for (i = 0; i < argc; i++) { + int len = strlen(argv[i]); + /*@ assert \valid(argv[i]) ; */ + /*@ assert \forall int k; 0 <= k && k <= len ==> \valid(&argv[i][k]) ; */ + } +} diff --git a/src/plugins/e-acsl/tests/memory/memalign.c b/src/plugins/e-acsl/tests/memory/memalign.c new file mode 100644 index 0000000000000000000000000000000000000000..f88e16873420998d41e04aa21655e3ae9524e8c3 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/memalign.c @@ -0,0 +1,41 @@ +/* run.config + COMMENT: Check aligned heap memory allocation +*/ + +#include <stdlib.h> + +int posix_memalign(void **memptr, size_t alignment, size_t size); +void *aligned_alloc(size_t alignment, size_t size); + +int main(int argc, const char **argv) { + char **memptr = malloc(sizeof(void*)); + int res2 = posix_memalign((void**)memptr, 256, 15); + + char *p = *memptr; + /*@assert \valid(p); */ + /*@assert \block_length(p) == 15; */ + /*@assert \freeable(p); */ + free(p); + /*@assert ! \valid(p); */ + + char *a; + a = aligned_alloc(256, 12); + /*@assert a == \null; */ + + a = aligned_alloc(255, 512); + /*@assert a == \null; */ + + a = aligned_alloc(0, 512); + /*@assert a == \null; */ + + a = aligned_alloc(256, 512); + /*@assert a != \null; */ + /*@assert \valid(a); */ + /*@assert \block_length(a) == 512; */ + /*@assert \freeable(a); */ + + free(a); + /*@assert ! \valid(a); */ + + return 0; +} diff --git a/src/plugins/e-acsl/tests/memory/memsize.c b/src/plugins/e-acsl/tests/memory/memsize.c new file mode 100644 index 0000000000000000000000000000000000000000..c214b60ebd4dcbb33a07b64bf3fddf3e7aec9a8e --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/memsize.c @@ -0,0 +1,63 @@ +/* run.config + COMMENT: Checking heap memory size +*/ + +#include <stdlib.h> +#include <stdio.h> +#include <stdint.h> + +extern size_t __e_acsl_heap_allocation_size; + +int main(int argc, char **argv) { + /* Allocation increases */ + char *a = malloc(7); + /*@assert (__e_acsl_heap_allocation_size == 7); */ + char *b = malloc(14); + /*@assert (__e_acsl_heap_allocation_size == 21); */ + + /* Allocation decreases */ + free(a); + /*@assert (__e_acsl_heap_allocation_size == 14); */ + + /* Make sure that free with NULL behaves and does not affect allocation */ + a = NULL; + free(a); + /*@assert (__e_acsl_heap_allocation_size == 14); */ + + /* Realloc decreases allocation */ + b = realloc(b, 9); + /*@assert (__e_acsl_heap_allocation_size == 9); */ + + /* Realloc increases allocation */ + b = realloc(b, 18); + /*@assert (__e_acsl_heap_allocation_size == 18); */ + + /* Realloc with 0 is equivalent to free */ + b = realloc(b, 0); + b = NULL; + /*@assert (__e_acsl_heap_allocation_size == 0); */ + + /* realloc with 0 is equivalent to malloc */ + b = realloc(b, 8); + /*@assert (__e_acsl_heap_allocation_size == 8); */ + + /* Abandon b and behave like malloc again */ + b = realloc(NULL, 8); + /*@assert (__e_acsl_heap_allocation_size == 16); */ + + /* Make realloc fail by supplying a huge number */ + b = realloc(NULL, SIZE_MAX); + /*@assert (__e_acsl_heap_allocation_size == 16); */ + /*@assert (b == NULL); */ + + /* Same as test for calloc ... */ + b = calloc(SIZE_MAX, SIZE_MAX); + /*@assert (__e_acsl_heap_allocation_size == 16); */ + /*@assert (b == NULL); */ + + /* ... and for malloc */ + b = malloc(SIZE_MAX); + /*@assert (__e_acsl_heap_allocation_size == 16); */ + /*@assert (b == NULL); */ + return 0; +} diff --git a/src/plugins/e-acsl/tests/memory/null.i b/src/plugins/e-acsl/tests/memory/null.i new file mode 100644 index 0000000000000000000000000000000000000000..ac480613edf6b36516834eeb96a04de4f4ba6741 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/null.i @@ -0,0 +1,8 @@ +/* run.config + COMMENT: assert \null == 0 +*/ + +int main(void) { + /*@ assert \null == 0; */ + return 0; +} diff --git a/src/plugins/e-acsl/tests/memory/offset.c b/src/plugins/e-acsl/tests/memory/offset.c new file mode 100644 index 0000000000000000000000000000000000000000..fc3dfa69b28685fd186254d7c67aa64ce17f96ec --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/offset.c @@ -0,0 +1,56 @@ +/* run.config + COMMENT: Behaviours of the \offset E-ACSL predicate +*/ + +#include <stdlib.h> + +int A[] = { 1, 2, 3, 4}; +int *PA; + +int main(void) { + /* Global memory */ + PA = (int*)&A; + /*@ assert \offset(&A[0]) == 0; */ + /*@ assert \offset(A+3) == 12; */ + /*@ assert \offset(PA) == 0; */ + PA++; + /*@ assert \offset(PA+1) == 8; */ + + /* Stack memory [long blocks] */ + int a[] = { 1, 2, 3, 4}; + /*@ assert \offset(&a[0]) == 0; */ + /*@ assert \offset(a+1) == 4; */ + /*@ assert \offset(a+3) == 12; */ + + /* Stack memory [Short blocks] */ + long l = 4; + char *pl = (char*)&l; + /*@ assert \offset(&l) == 0; */ + /*@ assert \offset(pl) == 0; */ + /*@ assert \offset(pl+1) == 1; */ + /*@ assert \offset(pl+7) == 7; */ + int *pi = (int*)&l; + /*@ assert \offset(pi) == 0; */ + pi++; + /*@ assert \offset(pi) == 4; */ + + /* Heap memory [single segment] */ + char *p = malloc(12); + /*@ assert \offset(p) == 0; */ + /*@ assert \offset(p+1) == 1; */ + /*@ assert \offset(p+11) == 11; */ + p += 5; + /*@ assert \offset(p+5) == 10; */ + /*@ assert \offset(p-5) == 0; */ + + /* Heap memory [multiple segments] */ + long *q = malloc(30*sizeof(long)); + + /*@ assert \offset(q) == 0; */ + q++; + /*@ assert \offset(q) == sizeof(long); */ + q += 2; + /*@ assert \offset(q) == sizeof(long)*3; */ + q += 4; + /*@ assert \offset(q) == sizeof(long)*7; */ +} diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/addrOf.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_ci/addrOf.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..efd026311297e55d8fefb674326118e6ece88624 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/addrOf.res.oracle @@ -0,0 +1,2 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/alias.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_ci/alias.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..efd026311297e55d8fefb674326118e6ece88624 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/alias.res.oracle @@ -0,0 +1,2 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/base_addr.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_ci/base_addr.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..efd026311297e55d8fefb674326118e6ece88624 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/base_addr.res.oracle @@ -0,0 +1,2 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/block_length.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_ci/block_length.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..efd026311297e55d8fefb674326118e6ece88624 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/block_length.res.oracle @@ -0,0 +1,2 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/block_valid.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_ci/block_valid.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..f7890eb4d148566132d047ad43471cd28b8bdb82 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/block_valid.res.oracle @@ -0,0 +1,14 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". +[eva:alarm] tests/memory/block_valid.c:49: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/memory/block_valid.c:50: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/memory/block_valid.c:52: Warning: + assertion got status unknown. +[eva:alarm] tests/memory/block_valid.c:52: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/memory/block_valid.c:54: Warning: + assertion got status unknown. +[eva:alarm] tests/memory/block_valid.c:54: Warning: + function __e_acsl_assert: precondition got status unknown. diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/bypassed_var.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_ci/bypassed_var.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..efd026311297e55d8fefb674326118e6ece88624 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/bypassed_var.res.oracle @@ -0,0 +1,2 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/call.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_ci/call.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..efd026311297e55d8fefb674326118e6ece88624 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/call.res.oracle @@ -0,0 +1,2 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/compound_initializers.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_ci/compound_initializers.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..efd026311297e55d8fefb674326118e6ece88624 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/compound_initializers.res.oracle @@ -0,0 +1,2 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/constructor.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_ci/constructor.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..9811cdbf49f1324c0f4cffd3aed7d450deac04cb --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/constructor.res.oracle @@ -0,0 +1,4 @@ +[e-acsl] beginning translation. +[kernel:annot:missing-spec] FRAMAC_SHARE/libc/stdio.h:169: Warning: + Neither code nor specification for function printf, generating default assigns from the prototype +[e-acsl] translation done in project "e-acsl". diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/ctype_macros.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_ci/ctype_macros.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..270dcdb0d84448a3889a178d504aa1b53f9de220 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/ctype_macros.res.oracle @@ -0,0 +1,23 @@ +[e-acsl] beginning translation. +[e-acsl] Warning: annotating undefined function `isupper': + the generated program may miss memory instrumentation + if there are memory-related annotations. +[e-acsl] tests/memory/ctype_macros.c:39: Warning: + E-ACSL construct `disjoint behaviors' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/ctype.h:174: Warning: + E-ACSL construct `assigns clause in behavior' is not yet supported. + Ignoring annotation. +[e-acsl] translation done in project "e-acsl". +[eva:alarm] tests/memory/ctype_macros.c:37: Warning: + function __gen_e_acsl_isupper: precondition 'c_uchar_or_eof' got status unknown. +[eva:alarm] FRAMAC_SHARE/libc/ctype.h:174: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] FRAMAC_SHARE/libc/ctype.h:178: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] FRAMAC_SHARE/libc/ctype.h:181: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] FRAMAC_SHARE/libc/ctype.h:178: Warning: + function __gen_e_acsl_isupper, behavior definitely_match: postcondition 'nonzero_result' got status unknown. (Behavior may be inactive, no reduction performed.) +[eva:alarm] FRAMAC_SHARE/libc/ctype.h:181: Warning: + function __gen_e_acsl_isupper, behavior definitely_not_match: postcondition 'zero_result' got status unknown. (Behavior may be inactive, no reduction performed.) diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/decl_in_switch.err.oracle b/src/plugins/e-acsl/tests/memory/oracle_ci/decl_in_switch.err.oracle new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/decl_in_switch.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_ci/decl_in_switch.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..c33737e3cac6e74853111a99a2a4002b6a9d7094 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/decl_in_switch.res.oracle @@ -0,0 +1,3 @@ +[e-acsl] beginning translation. +FRAMAC_SHARE/libc/stdlib.h:276:[kernel] warning: No code nor implicit assigns clause for function calloc, generating default assigns from the prototype +[e-acsl] translation done in project "e-acsl". diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/early_exit.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_ci/early_exit.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..965ff85803169a13ec505dc05504dd6b12557d30 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/early_exit.res.oracle @@ -0,0 +1,7 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". +[eva:locals-escaping] tests/memory/early_exit.c:14: Warning: + locals {a} escaping the scope of a block of goto_bts through p +[eva:alarm] tests/memory/early_exit.c:18: Warning: + accessing left-value that contains escaping addresses. + assert ¬\dangling(&p); diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/errno.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_ci/errno.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..efd026311297e55d8fefb674326118e6ece88624 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/errno.res.oracle @@ -0,0 +1,2 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/freeable.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_ci/freeable.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..bed0b61add3b254ae30b451a44775d4b857f6bdd --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/freeable.res.oracle @@ -0,0 +1,5 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". +[eva:alarm] tests/memory/freeable.c:14: Warning: assertion got status unknown. +[eva:alarm] tests/memory/freeable.c:14: Warning: + accessing uninitialized left-value. assert \initialized(&p); diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/gen_addrOf.c b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_addrOf.c new file mode 100644 index 0000000000000000000000000000000000000000..05cb6511ba08ed6fce4953414b0a3578544c1c77 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_addrOf.c @@ -0,0 +1,45 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +void f(void) +{ + int m; + int *u; + int *p; + __e_acsl_store_block((void *)(& p),(size_t)8); + __e_acsl_store_block((void *)(& u),(size_t)8); + __e_acsl_store_block((void *)(& m),(size_t)4); + __e_acsl_full_init((void *)(& u)); + u = & m; + __e_acsl_full_init((void *)(& p)); + p = u; + __e_acsl_full_init((void *)(& m)); + m = 123; + /*@ assert \initialized(p); */ + { + int __gen_e_acsl_initialized; + __gen_e_acsl_initialized = __e_acsl_initialized((void *)p,sizeof(int)); + __e_acsl_assert(__gen_e_acsl_initialized,(char *)"Assertion",(char *)"f", + (char *)"\\initialized(p)",10); + } + __e_acsl_delete_block((void *)(& p)); + __e_acsl_delete_block((void *)(& u)); + __e_acsl_delete_block((void *)(& m)); + return; +} + +int main(void) +{ + int __retres; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + int x = 0; + f(); + /*@ assert &x ≡ &x; */ + __e_acsl_assert(& x == & x,(char *)"Assertion",(char *)"main", + (char *)"&x == &x",16); + __retres = 0; + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/gen_alias.c b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_alias.c new file mode 100644 index 0000000000000000000000000000000000000000..bb994b44a4129cd4a760a28f03c71856a917214a --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_alias.c @@ -0,0 +1,38 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +void f(int *dest, int val) +{ + __e_acsl_store_block((void *)(& dest),(size_t)8); + int *ptr = dest; + __e_acsl_store_block((void *)(& ptr),(size_t)8); + __e_acsl_full_init((void *)(& ptr)); + __e_acsl_initialize((void *)ptr,sizeof(int)); + *ptr = val; + __e_acsl_delete_block((void *)(& dest)); + __e_acsl_delete_block((void *)(& ptr)); + return; +} + +int main(void) +{ + int __retres; + int i; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + __e_acsl_store_block((void *)(& i),(size_t)4); + f(& i,255); + /*@ assert \initialized(&i); */ + { + int __gen_e_acsl_initialized; + __gen_e_acsl_initialized = __e_acsl_initialized((void *)(& i), + sizeof(int)); + __e_acsl_assert(__gen_e_acsl_initialized,(char *)"Assertion", + (char *)"main",(char *)"\\initialized(&i)",14); + } + __retres = 0; + __e_acsl_delete_block((void *)(& i)); + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/gen_base_addr.c b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_base_addr.c new file mode 100644 index 0000000000000000000000000000000000000000..3fae5831d80aa68135a9a1b3cf7ee54bef8fe0c4 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_base_addr.c @@ -0,0 +1,315 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +int A[4] = {1, 2, 3, 4}; +int *PA; +void __e_acsl_globals_init(void) +{ + static char __e_acsl_already_run = 0; + if (! __e_acsl_already_run) { + __e_acsl_already_run = 1; + __e_acsl_store_block((void *)(& PA),(size_t)8); + __e_acsl_full_init((void *)(& PA)); + __e_acsl_store_block((void *)(A),(size_t)16); + __e_acsl_full_init((void *)(& A)); + } + return; +} + +int main(void) +{ + int __retres; + int *pa; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + __e_acsl_globals_init(); + __e_acsl_store_block((void *)(& pa),(size_t)8); + PA = (int *)(& A); + /*@ assert \base_addr((int *)A) ≡ \base_addr(&A); */ + { + void *__gen_e_acsl_base_addr; + void *__gen_e_acsl_base_addr_2; + __gen_e_acsl_base_addr = __e_acsl_base_addr((void *)(A)); + __gen_e_acsl_base_addr_2 = __e_acsl_base_addr((void *)(& A)); + __e_acsl_assert(__gen_e_acsl_base_addr == __gen_e_acsl_base_addr_2, + (char *)"Assertion",(char *)"main", + (char *)"\\base_addr((int *)A) == \\base_addr(&A)",13); + } + /*@ assert \base_addr((int *)A) ≡ \base_addr(PA); */ + { + void *__gen_e_acsl_base_addr_3; + void *__gen_e_acsl_base_addr_4; + __gen_e_acsl_base_addr_3 = __e_acsl_base_addr((void *)(A)); + __gen_e_acsl_base_addr_4 = __e_acsl_base_addr((void *)PA); + __e_acsl_assert(__gen_e_acsl_base_addr_3 == __gen_e_acsl_base_addr_4, + (char *)"Assertion",(char *)"main", + (char *)"\\base_addr((int *)A) == \\base_addr(PA)",14); + } + /*@ assert \base_addr(&A[3]) ≡ \base_addr(PA); */ + { + void *__gen_e_acsl_base_addr_5; + void *__gen_e_acsl_base_addr_6; + __gen_e_acsl_base_addr_5 = __e_acsl_base_addr((void *)(& A[3])); + __gen_e_acsl_base_addr_6 = __e_acsl_base_addr((void *)PA); + __e_acsl_assert(__gen_e_acsl_base_addr_5 == __gen_e_acsl_base_addr_6, + (char *)"Assertion",(char *)"main", + (char *)"\\base_addr(&A[3]) == \\base_addr(PA)",15); + } + PA ++; + /*@ assert \base_addr(PA) ≡ \base_addr((int *)A); */ + { + void *__gen_e_acsl_base_addr_7; + void *__gen_e_acsl_base_addr_8; + __gen_e_acsl_base_addr_7 = __e_acsl_base_addr((void *)PA); + __gen_e_acsl_base_addr_8 = __e_acsl_base_addr((void *)(A)); + __e_acsl_assert(__gen_e_acsl_base_addr_7 == __gen_e_acsl_base_addr_8, + (char *)"Assertion",(char *)"main", + (char *)"\\base_addr(PA) == \\base_addr((int *)A)",17); + } + /*@ assert \base_addr(PA + 2) ≡ \base_addr(&A[3]); */ + { + void *__gen_e_acsl_base_addr_9; + void *__gen_e_acsl_base_addr_10; + __gen_e_acsl_base_addr_9 = __e_acsl_base_addr((void *)(PA + 2)); + __gen_e_acsl_base_addr_10 = __e_acsl_base_addr((void *)(& A[3])); + __e_acsl_assert(__gen_e_acsl_base_addr_9 == __gen_e_acsl_base_addr_10, + (char *)"Assertion",(char *)"main", + (char *)"\\base_addr(PA + 2) == \\base_addr(&A[3])",18); + } + int a[4] = {1, 2, 3, 4}; + __e_acsl_store_block((void *)(a),(size_t)16); + __e_acsl_full_init((void *)(& a)); + __e_acsl_full_init((void *)(& pa)); + pa = (int *)(& a); + /*@ assert \base_addr((int *)a) ≡ \base_addr(&a); */ + { + void *__gen_e_acsl_base_addr_11; + void *__gen_e_acsl_base_addr_12; + __gen_e_acsl_base_addr_11 = __e_acsl_base_addr((void *)(a)); + __gen_e_acsl_base_addr_12 = __e_acsl_base_addr((void *)(& a)); + __e_acsl_assert(__gen_e_acsl_base_addr_11 == __gen_e_acsl_base_addr_12, + (char *)"Assertion",(char *)"main", + (char *)"\\base_addr((int *)a) == \\base_addr(&a)",25); + } + /*@ assert \base_addr((int *)a) ≡ \base_addr(pa); */ + { + void *__gen_e_acsl_base_addr_13; + void *__gen_e_acsl_base_addr_14; + __gen_e_acsl_base_addr_13 = __e_acsl_base_addr((void *)(a)); + __gen_e_acsl_base_addr_14 = __e_acsl_base_addr((void *)pa); + __e_acsl_assert(__gen_e_acsl_base_addr_13 == __gen_e_acsl_base_addr_14, + (char *)"Assertion",(char *)"main", + (char *)"\\base_addr((int *)a) == \\base_addr(pa)",26); + } + /*@ assert \base_addr(&a[3]) ≡ \base_addr(pa); */ + { + void *__gen_e_acsl_base_addr_15; + void *__gen_e_acsl_base_addr_16; + __gen_e_acsl_base_addr_15 = __e_acsl_base_addr((void *)(& a[3])); + __gen_e_acsl_base_addr_16 = __e_acsl_base_addr((void *)pa); + __e_acsl_assert(__gen_e_acsl_base_addr_15 == __gen_e_acsl_base_addr_16, + (char *)"Assertion",(char *)"main", + (char *)"\\base_addr(&a[3]) == \\base_addr(pa)",27); + } + __e_acsl_full_init((void *)(& pa)); + pa ++; + /*@ assert \base_addr(pa) ≡ \base_addr((int *)a); */ + { + void *__gen_e_acsl_base_addr_17; + void *__gen_e_acsl_base_addr_18; + __gen_e_acsl_base_addr_17 = __e_acsl_base_addr((void *)pa); + __gen_e_acsl_base_addr_18 = __e_acsl_base_addr((void *)(a)); + __e_acsl_assert(__gen_e_acsl_base_addr_17 == __gen_e_acsl_base_addr_18, + (char *)"Assertion",(char *)"main", + (char *)"\\base_addr(pa) == \\base_addr((int *)a)",29); + } + /*@ assert \base_addr(pa + 2) ≡ \base_addr((int *)a); */ + { + void *__gen_e_acsl_base_addr_19; + void *__gen_e_acsl_base_addr_20; + __gen_e_acsl_base_addr_19 = __e_acsl_base_addr((void *)(pa + 2)); + __gen_e_acsl_base_addr_20 = __e_acsl_base_addr((void *)(a)); + __e_acsl_assert(__gen_e_acsl_base_addr_19 == __gen_e_acsl_base_addr_20, + (char *)"Assertion",(char *)"main", + (char *)"\\base_addr(pa + 2) == \\base_addr((int *)a)", + 30); + } + long l = (long)4; + __e_acsl_store_block((void *)(& l),(size_t)8); + __e_acsl_full_init((void *)(& l)); + char *pl = (char *)(& l); + __e_acsl_store_block((void *)(& pl),(size_t)8); + __e_acsl_full_init((void *)(& pl)); + /*@ assert \base_addr(&l) ≡ \base_addr(pl); */ + { + void *__gen_e_acsl_base_addr_21; + void *__gen_e_acsl_base_addr_22; + __gen_e_acsl_base_addr_21 = __e_acsl_base_addr((void *)(& l)); + __gen_e_acsl_base_addr_22 = __e_acsl_base_addr((void *)pl); + __e_acsl_assert(__gen_e_acsl_base_addr_21 == __gen_e_acsl_base_addr_22, + (char *)"Assertion",(char *)"main", + (char *)"\\base_addr(&l) == \\base_addr(pl)",35); + } + /*@ assert \base_addr(pl + 2) ≡ \base_addr(&l); */ + { + void *__gen_e_acsl_base_addr_23; + void *__gen_e_acsl_base_addr_24; + __gen_e_acsl_base_addr_23 = __e_acsl_base_addr((void *)(pl + 2)); + __gen_e_acsl_base_addr_24 = __e_acsl_base_addr((void *)(& l)); + __e_acsl_assert(__gen_e_acsl_base_addr_23 == __gen_e_acsl_base_addr_24, + (char *)"Assertion",(char *)"main", + (char *)"\\base_addr(pl + 2) == \\base_addr(&l)",36); + } + short *pi = (short *)(& l); + __e_acsl_store_block((void *)(& pi),(size_t)8); + __e_acsl_full_init((void *)(& pi)); + __e_acsl_full_init((void *)(& pi)); + pi ++; + __e_acsl_full_init((void *)(& pl)); + pl ++; + /*@ assert \base_addr(pi) ≡ \base_addr(pl); */ + { + void *__gen_e_acsl_base_addr_25; + void *__gen_e_acsl_base_addr_26; + __gen_e_acsl_base_addr_25 = __e_acsl_base_addr((void *)pi); + __gen_e_acsl_base_addr_26 = __e_acsl_base_addr((void *)pl); + __e_acsl_assert(__gen_e_acsl_base_addr_25 == __gen_e_acsl_base_addr_26, + (char *)"Assertion",(char *)"main", + (char *)"\\base_addr(pi) == \\base_addr(pl)",40); + } + /*@ assert \base_addr(pl) ≡ \base_addr(&l); */ + { + void *__gen_e_acsl_base_addr_27; + void *__gen_e_acsl_base_addr_28; + __gen_e_acsl_base_addr_27 = __e_acsl_base_addr((void *)pl); + __gen_e_acsl_base_addr_28 = __e_acsl_base_addr((void *)(& l)); + __e_acsl_assert(__gen_e_acsl_base_addr_27 == __gen_e_acsl_base_addr_28, + (char *)"Assertion",(char *)"main", + (char *)"\\base_addr(pl) == \\base_addr(&l)",41); + } + char *p = malloc((unsigned long)12); + __e_acsl_store_block((void *)(& p),(size_t)8); + __e_acsl_full_init((void *)(& p)); + char *pd = p; + __e_acsl_store_block((void *)(& pd),(size_t)8); + __e_acsl_full_init((void *)(& pd)); + /*@ assert \base_addr(p) ≡ \base_addr(pd); */ + { + void *__gen_e_acsl_base_addr_29; + void *__gen_e_acsl_base_addr_30; + __gen_e_acsl_base_addr_29 = __e_acsl_base_addr((void *)p); + __gen_e_acsl_base_addr_30 = __e_acsl_base_addr((void *)pd); + __e_acsl_assert(__gen_e_acsl_base_addr_29 == __gen_e_acsl_base_addr_30, + (char *)"Assertion",(char *)"main", + (char *)"\\base_addr(p) == \\base_addr(pd)",46); + } + /*@ assert \base_addr(p + 1) ≡ \base_addr(pd + 5); */ + { + void *__gen_e_acsl_base_addr_31; + void *__gen_e_acsl_base_addr_32; + __gen_e_acsl_base_addr_31 = __e_acsl_base_addr((void *)(p + 1)); + __gen_e_acsl_base_addr_32 = __e_acsl_base_addr((void *)(pd + 5)); + __e_acsl_assert(__gen_e_acsl_base_addr_31 == __gen_e_acsl_base_addr_32, + (char *)"Assertion",(char *)"main", + (char *)"\\base_addr(p + 1) == \\base_addr(pd + 5)",47); + } + /*@ assert \base_addr(p + 11) ≡ \base_addr(pd + 1); */ + { + void *__gen_e_acsl_base_addr_33; + void *__gen_e_acsl_base_addr_34; + __gen_e_acsl_base_addr_33 = __e_acsl_base_addr((void *)(p + 11)); + __gen_e_acsl_base_addr_34 = __e_acsl_base_addr((void *)(pd + 1)); + __e_acsl_assert(__gen_e_acsl_base_addr_33 == __gen_e_acsl_base_addr_34, + (char *)"Assertion",(char *)"main", + (char *)"\\base_addr(p + 11) == \\base_addr(pd + 1)",48); + } + __e_acsl_full_init((void *)(& p)); + p += 5; + /*@ assert \base_addr(p + 5) ≡ \base_addr(pd); */ + { + void *__gen_e_acsl_base_addr_35; + void *__gen_e_acsl_base_addr_36; + __gen_e_acsl_base_addr_35 = __e_acsl_base_addr((void *)(p + 5)); + __gen_e_acsl_base_addr_36 = __e_acsl_base_addr((void *)pd); + __e_acsl_assert(__gen_e_acsl_base_addr_35 == __gen_e_acsl_base_addr_36, + (char *)"Assertion",(char *)"main", + (char *)"\\base_addr(p + 5) == \\base_addr(pd)",50); + } + /*@ assert \base_addr(p - 5) ≡ \base_addr(pd); */ + { + void *__gen_e_acsl_base_addr_37; + void *__gen_e_acsl_base_addr_38; + __gen_e_acsl_base_addr_37 = __e_acsl_base_addr((void *)(p - 5)); + __gen_e_acsl_base_addr_38 = __e_acsl_base_addr((void *)pd); + __e_acsl_assert(__gen_e_acsl_base_addr_37 == __gen_e_acsl_base_addr_38, + (char *)"Assertion",(char *)"main", + (char *)"\\base_addr(p - 5) == \\base_addr(pd)",51); + } + long *q = malloc((unsigned long)30 * sizeof(long)); + __e_acsl_store_block((void *)(& q),(size_t)8); + __e_acsl_full_init((void *)(& q)); + long *qd = q; + __e_acsl_store_block((void *)(& qd),(size_t)8); + __e_acsl_full_init((void *)(& qd)); + /*@ assert \base_addr(q) ≡ \base_addr(qd); */ + { + void *__gen_e_acsl_base_addr_39; + void *__gen_e_acsl_base_addr_40; + __gen_e_acsl_base_addr_39 = __e_acsl_base_addr((void *)q); + __gen_e_acsl_base_addr_40 = __e_acsl_base_addr((void *)qd); + __e_acsl_assert(__gen_e_acsl_base_addr_39 == __gen_e_acsl_base_addr_40, + (char *)"Assertion",(char *)"main", + (char *)"\\base_addr(q) == \\base_addr(qd)",57); + } + __e_acsl_full_init((void *)(& q)); + q ++; + /*@ assert \base_addr(q) ≡ \base_addr(qd); */ + { + void *__gen_e_acsl_base_addr_41; + void *__gen_e_acsl_base_addr_42; + __gen_e_acsl_base_addr_41 = __e_acsl_base_addr((void *)q); + __gen_e_acsl_base_addr_42 = __e_acsl_base_addr((void *)qd); + __e_acsl_assert(__gen_e_acsl_base_addr_41 == __gen_e_acsl_base_addr_42, + (char *)"Assertion",(char *)"main", + (char *)"\\base_addr(q) == \\base_addr(qd)",59); + } + __e_acsl_full_init((void *)(& q)); + q += 2; + /*@ assert \base_addr(q) ≡ \base_addr(qd); */ + { + void *__gen_e_acsl_base_addr_43; + void *__gen_e_acsl_base_addr_44; + __gen_e_acsl_base_addr_43 = __e_acsl_base_addr((void *)q); + __gen_e_acsl_base_addr_44 = __e_acsl_base_addr((void *)qd); + __e_acsl_assert(__gen_e_acsl_base_addr_43 == __gen_e_acsl_base_addr_44, + (char *)"Assertion",(char *)"main", + (char *)"\\base_addr(q) == \\base_addr(qd)",61); + } + __e_acsl_full_init((void *)(& q)); + q += 4; + /*@ assert \base_addr(q) ≡ \base_addr(qd); */ + { + void *__gen_e_acsl_base_addr_45; + void *__gen_e_acsl_base_addr_46; + __gen_e_acsl_base_addr_45 = __e_acsl_base_addr((void *)q); + __gen_e_acsl_base_addr_46 = __e_acsl_base_addr((void *)qd); + __e_acsl_assert(__gen_e_acsl_base_addr_45 == __gen_e_acsl_base_addr_46, + (char *)"Assertion",(char *)"main", + (char *)"\\base_addr(q) == \\base_addr(qd)",63); + } + __retres = 0; + __e_acsl_delete_block((void *)(& PA)); + __e_acsl_delete_block((void *)(A)); + __e_acsl_delete_block((void *)(& qd)); + __e_acsl_delete_block((void *)(& q)); + __e_acsl_delete_block((void *)(& pd)); + __e_acsl_delete_block((void *)(& p)); + __e_acsl_delete_block((void *)(& pi)); + __e_acsl_delete_block((void *)(& pl)); + __e_acsl_delete_block((void *)(& l)); + __e_acsl_delete_block((void *)(& pa)); + __e_acsl_delete_block((void *)(a)); + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/gen_block_length.c b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_block_length.c new file mode 100644 index 0000000000000000000000000000000000000000..c36db344dd5b7819c00db18a3a7313e553dcc726 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_block_length.c @@ -0,0 +1,249 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +struct Zero { + +}; +int A[4] = {1, 2, 3, 4}; +int *PA; +struct Zero ZERO; +void __e_acsl_globals_init(void) +{ + static char __e_acsl_already_run = 0; + if (! __e_acsl_already_run) { + __e_acsl_already_run = 1; + __e_acsl_store_block((void *)(& ZERO),(size_t)0); + __e_acsl_full_init((void *)(& ZERO)); + __e_acsl_store_block((void *)(& PA),(size_t)8); + __e_acsl_full_init((void *)(& PA)); + __e_acsl_store_block((void *)(A),(size_t)16); + __e_acsl_full_init((void *)(& A)); + } + return; +} + +int main(void) +{ + int __retres; + struct Zero zero; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + __e_acsl_globals_init(); + __e_acsl_store_block((void *)(& zero),(size_t)0); + /*@ assert \block_length(&ZERO) ≡ 0; */ + { + unsigned long __gen_e_acsl_block_length; + __gen_e_acsl_block_length = __e_acsl_block_length((void *)(& ZERO)); + __e_acsl_assert(__gen_e_acsl_block_length == 0UL,(char *)"Assertion", + (char *)"main",(char *)"\\block_length(&ZERO) == 0",15); + } + /*@ assert \block_length(&zero) ≡ 0; */ + { + unsigned long __gen_e_acsl_block_length_2; + __gen_e_acsl_block_length_2 = __e_acsl_block_length((void *)(& zero)); + __e_acsl_assert(__gen_e_acsl_block_length_2 == 0UL,(char *)"Assertion", + (char *)"main",(char *)"\\block_length(&zero) == 0",16); + } + PA = (int *)(& A); + /*@ assert \block_length((int *)A) ≡ sizeof(A); */ + { + unsigned long __gen_e_acsl_block_length_3; + __gen_e_acsl_block_length_3 = __e_acsl_block_length((void *)(A)); + __e_acsl_assert(__gen_e_acsl_block_length_3 == 16UL,(char *)"Assertion", + (char *)"main", + (char *)"\\block_length((int *)A) == sizeof(A)",20); + } + /*@ assert \block_length(&A[3]) ≡ sizeof(A); */ + { + unsigned long __gen_e_acsl_block_length_4; + __gen_e_acsl_block_length_4 = __e_acsl_block_length((void *)(& A[3])); + __e_acsl_assert(__gen_e_acsl_block_length_4 == 16UL,(char *)"Assertion", + (char *)"main", + (char *)"\\block_length(&A[3]) == sizeof(A)",21); + } + /*@ assert \block_length(PA) ≡ sizeof(A); */ + { + unsigned long __gen_e_acsl_block_length_5; + __gen_e_acsl_block_length_5 = __e_acsl_block_length((void *)PA); + __e_acsl_assert(__gen_e_acsl_block_length_5 == 16UL,(char *)"Assertion", + (char *)"main",(char *)"\\block_length(PA) == sizeof(A)", + 22); + } + PA ++; + /*@ assert \block_length(PA + 1) ≡ \block_length(&A[1]); */ + { + unsigned long __gen_e_acsl_block_length_6; + unsigned long __gen_e_acsl_block_length_7; + __gen_e_acsl_block_length_6 = __e_acsl_block_length((void *)(PA + 1)); + __gen_e_acsl_block_length_7 = __e_acsl_block_length((void *)(& A[1])); + __e_acsl_assert(__gen_e_acsl_block_length_6 == __gen_e_acsl_block_length_7, + (char *)"Assertion",(char *)"main", + (char *)"\\block_length(PA + 1) == \\block_length(&A[1])", + 24); + } + int a[4] = {1, 2, 3, 4}; + __e_acsl_store_block((void *)(a),(size_t)16); + __e_acsl_full_init((void *)(& a)); + int *pa = (int *)(& a); + __e_acsl_store_block((void *)(& pa),(size_t)8); + __e_acsl_full_init((void *)(& pa)); + /*@ assert \block_length((int *)a) ≡ sizeof(a); */ + { + unsigned long __gen_e_acsl_block_length_8; + __gen_e_acsl_block_length_8 = __e_acsl_block_length((void *)(a)); + __e_acsl_assert(__gen_e_acsl_block_length_8 == 16UL,(char *)"Assertion", + (char *)"main", + (char *)"\\block_length((int *)a) == sizeof(a)",29); + } + /*@ assert \block_length(&a[3]) ≡ sizeof(a); */ + { + unsigned long __gen_e_acsl_block_length_9; + __gen_e_acsl_block_length_9 = __e_acsl_block_length((void *)(& a[3])); + __e_acsl_assert(__gen_e_acsl_block_length_9 == 16UL,(char *)"Assertion", + (char *)"main", + (char *)"\\block_length(&a[3]) == sizeof(a)",30); + } + /*@ assert \block_length(pa) ≡ sizeof(a); */ + { + unsigned long __gen_e_acsl_block_length_10; + __gen_e_acsl_block_length_10 = __e_acsl_block_length((void *)pa); + __e_acsl_assert(__gen_e_acsl_block_length_10 == 16UL,(char *)"Assertion", + (char *)"main",(char *)"\\block_length(pa) == sizeof(a)", + 31); + } + __e_acsl_full_init((void *)(& pa)); + pa ++; + /*@ assert \block_length(pa + 1) ≡ \block_length(&a[1]); */ + { + unsigned long __gen_e_acsl_block_length_11; + unsigned long __gen_e_acsl_block_length_12; + __gen_e_acsl_block_length_11 = __e_acsl_block_length((void *)(pa + 1)); + __gen_e_acsl_block_length_12 = __e_acsl_block_length((void *)(& a[1])); + __e_acsl_assert(__gen_e_acsl_block_length_11 == __gen_e_acsl_block_length_12, + (char *)"Assertion",(char *)"main", + (char *)"\\block_length(pa + 1) == \\block_length(&a[1])", + 33); + } + long l = (long)4; + __e_acsl_store_block((void *)(& l),(size_t)8); + __e_acsl_full_init((void *)(& l)); + char *pl = (char *)(& l); + __e_acsl_store_block((void *)(& pl),(size_t)8); + __e_acsl_full_init((void *)(& pl)); + /*@ assert \block_length(&l) ≡ sizeof(long); */ + { + unsigned long __gen_e_acsl_block_length_13; + __gen_e_acsl_block_length_13 = __e_acsl_block_length((void *)(& l)); + __e_acsl_assert(__gen_e_acsl_block_length_13 == 8UL,(char *)"Assertion", + (char *)"main", + (char *)"\\block_length(&l) == sizeof(long)",39); + } + /*@ assert \block_length(pl) ≡ sizeof(long); */ + { + unsigned long __gen_e_acsl_block_length_14; + __gen_e_acsl_block_length_14 = __e_acsl_block_length((void *)pl); + __e_acsl_assert(__gen_e_acsl_block_length_14 == 8UL,(char *)"Assertion", + (char *)"main", + (char *)"\\block_length(pl) == sizeof(long)",40); + } + /*@ assert \block_length(pl + 7) ≡ sizeof(long); */ + { + unsigned long __gen_e_acsl_block_length_15; + __gen_e_acsl_block_length_15 = __e_acsl_block_length((void *)(pl + 7)); + __e_acsl_assert(__gen_e_acsl_block_length_15 == 8UL,(char *)"Assertion", + (char *)"main", + (char *)"\\block_length(pl + 7) == sizeof(long)",41); + } + int *pi = (int *)(& l); + __e_acsl_store_block((void *)(& pi),(size_t)8); + __e_acsl_full_init((void *)(& pi)); + /*@ assert \block_length(pi) ≡ \block_length(&l); */ + { + unsigned long __gen_e_acsl_block_length_16; + unsigned long __gen_e_acsl_block_length_17; + __gen_e_acsl_block_length_16 = __e_acsl_block_length((void *)pi); + __gen_e_acsl_block_length_17 = __e_acsl_block_length((void *)(& l)); + __e_acsl_assert(__gen_e_acsl_block_length_16 == __gen_e_acsl_block_length_17, + (char *)"Assertion",(char *)"main", + (char *)"\\block_length(pi) == \\block_length(&l)",43); + } + __e_acsl_full_init((void *)(& pi)); + pi ++; + /*@ assert \block_length(pi) ≡ \block_length(&l); */ + { + unsigned long __gen_e_acsl_block_length_18; + unsigned long __gen_e_acsl_block_length_19; + __gen_e_acsl_block_length_18 = __e_acsl_block_length((void *)pi); + __gen_e_acsl_block_length_19 = __e_acsl_block_length((void *)(& l)); + __e_acsl_assert(__gen_e_acsl_block_length_18 == __gen_e_acsl_block_length_19, + (char *)"Assertion",(char *)"main", + (char *)"\\block_length(pi) == \\block_length(&l)",45); + } + size_t size = (unsigned long)12; + char *p = malloc(size); + __e_acsl_store_block((void *)(& p),(size_t)8); + __e_acsl_full_init((void *)(& p)); + /*@ assert \block_length(p) ≡ size; */ + { + unsigned long __gen_e_acsl_block_length_20; + __gen_e_acsl_block_length_20 = __e_acsl_block_length((void *)p); + __e_acsl_assert(__gen_e_acsl_block_length_20 == size,(char *)"Assertion", + (char *)"main",(char *)"\\block_length(p) == size",50); + } + /*@ assert \block_length(p + 11) ≡ size; */ + { + unsigned long __gen_e_acsl_block_length_21; + __gen_e_acsl_block_length_21 = __e_acsl_block_length((void *)(p + 11)); + __e_acsl_assert(__gen_e_acsl_block_length_21 == size,(char *)"Assertion", + (char *)"main",(char *)"\\block_length(p + 11) == size", + 51); + } + __e_acsl_full_init((void *)(& p)); + p += 5; + /*@ assert \block_length(p + 5) ≡ \block_length(p - 5); */ + { + unsigned long __gen_e_acsl_block_length_22; + unsigned long __gen_e_acsl_block_length_23; + __gen_e_acsl_block_length_22 = __e_acsl_block_length((void *)(p + 5)); + __gen_e_acsl_block_length_23 = __e_acsl_block_length((void *)(p - 5)); + __e_acsl_assert(__gen_e_acsl_block_length_22 == __gen_e_acsl_block_length_23, + (char *)"Assertion",(char *)"main", + (char *)"\\block_length(p + 5) == \\block_length(p - 5)", + 53); + } + size = (unsigned long)30 * sizeof(long); + long *q = malloc(size); + __e_acsl_store_block((void *)(& q),(size_t)8); + __e_acsl_full_init((void *)(& q)); + /*@ assert \block_length(q) ≡ size; */ + { + unsigned long __gen_e_acsl_block_length_24; + __gen_e_acsl_block_length_24 = __e_acsl_block_length((void *)q); + __e_acsl_assert(__gen_e_acsl_block_length_24 == size,(char *)"Assertion", + (char *)"main",(char *)"\\block_length(q) == size",59); + } + __e_acsl_full_init((void *)(& q)); + q += 4; + /*@ assert \block_length(q) ≡ size; */ + { + unsigned long __gen_e_acsl_block_length_25; + __gen_e_acsl_block_length_25 = __e_acsl_block_length((void *)q); + __e_acsl_assert(__gen_e_acsl_block_length_25 == size,(char *)"Assertion", + (char *)"main",(char *)"\\block_length(q) == size",61); + } + __retres = 0; + __e_acsl_delete_block((void *)(& ZERO)); + __e_acsl_delete_block((void *)(& PA)); + __e_acsl_delete_block((void *)(A)); + __e_acsl_delete_block((void *)(& q)); + __e_acsl_delete_block((void *)(& p)); + __e_acsl_delete_block((void *)(& pi)); + __e_acsl_delete_block((void *)(& pl)); + __e_acsl_delete_block((void *)(& l)); + __e_acsl_delete_block((void *)(& pa)); + __e_acsl_delete_block((void *)(a)); + __e_acsl_delete_block((void *)(& zero)); + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/gen_block_valid.c b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_block_valid.c new file mode 100644 index 0000000000000000000000000000000000000000..c8beb84f9f767bf1199a38ec71dfad279ec2511c --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_block_valid.c @@ -0,0 +1,163 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +int A = 1; +int B = 2; +int C = 3; +void __e_acsl_globals_init(void) +{ + static char __e_acsl_already_run = 0; + if (! __e_acsl_already_run) { + __e_acsl_already_run = 1; + __e_acsl_store_block((void *)(& B),(size_t)4); + __e_acsl_full_init((void *)(& B)); + } + return; +} + +int main(int argc, char **argv) +{ + int __retres; + __e_acsl_memory_init(& argc,& argv,(size_t)8); + __e_acsl_globals_init(); + int *p = (int *)0; + __e_acsl_store_block((void *)(& p),(size_t)8); + __e_acsl_full_init((void *)(& p)); + int *q = (int *)0; + int a = 1; + int b = 2; + __e_acsl_store_block((void *)(& b),(size_t)4); + __e_acsl_full_init((void *)(& b)); + int c = 3; + __e_acsl_full_init((void *)(& p)); + p = & b; + /*@ assert \valid(p); */ + { + int __gen_e_acsl_initialized; + int __gen_e_acsl_and; + __gen_e_acsl_initialized = __e_acsl_initialized((void *)(& p), + sizeof(int *)); + if (__gen_e_acsl_initialized) { + int __gen_e_acsl_valid; + __gen_e_acsl_valid = __e_acsl_valid((void *)p,sizeof(int),(void *)p, + (void *)(& p)); + __gen_e_acsl_and = __gen_e_acsl_valid; + } + else __gen_e_acsl_and = 0; + __e_acsl_assert(__gen_e_acsl_and,(char *)"Assertion",(char *)"main", + (char *)"\\valid(p)",24); + } + /*@ assert ¬\valid(p + 1); */ + { + int __gen_e_acsl_valid_2; + __gen_e_acsl_valid_2 = __e_acsl_valid((void *)(p + 1),sizeof(int), + (void *)p,(void *)(& p)); + __e_acsl_assert(! __gen_e_acsl_valid_2,(char *)"Assertion", + (char *)"main",(char *)"!\\valid(p + 1)",26); + } + __e_acsl_full_init((void *)(& p)); + p = & B; + /*@ assert \valid(p); */ + { + int __gen_e_acsl_initialized_2; + int __gen_e_acsl_and_2; + __gen_e_acsl_initialized_2 = __e_acsl_initialized((void *)(& p), + sizeof(int *)); + if (__gen_e_acsl_initialized_2) { + int __gen_e_acsl_valid_3; + __gen_e_acsl_valid_3 = __e_acsl_valid((void *)p,sizeof(int),(void *)p, + (void *)(& p)); + __gen_e_acsl_and_2 = __gen_e_acsl_valid_3; + } + else __gen_e_acsl_and_2 = 0; + __e_acsl_assert(__gen_e_acsl_and_2,(char *)"Assertion",(char *)"main", + (char *)"\\valid(p)",29); + } + /*@ assert ¬\valid(p + 1); */ + { + int __gen_e_acsl_valid_4; + __gen_e_acsl_valid_4 = __e_acsl_valid((void *)(p + 1),sizeof(int), + (void *)p,(void *)(& p)); + __e_acsl_assert(! __gen_e_acsl_valid_4,(char *)"Assertion", + (char *)"main",(char *)"!\\valid(p + 1)",31); + } + char *pmin = malloc(sizeof(int)); + __e_acsl_store_block((void *)(& pmin),(size_t)8); + __e_acsl_full_init((void *)(& pmin)); + char *pmax = malloc(sizeof(int)); + __e_acsl_store_block((void *)(& pmax),(size_t)8); + __e_acsl_full_init((void *)(& pmax)); + if ((unsigned long)pmin > (unsigned long)pmax) { + char *t = pmin; + __e_acsl_store_block((void *)(& t),(size_t)8); + __e_acsl_full_init((void *)(& t)); + __e_acsl_full_init((void *)(& pmin)); + pmin = pmax; + __e_acsl_full_init((void *)(& pmax)); + pmax = t; + __e_acsl_delete_block((void *)(& t)); + } + __e_acsl_initialize((void *)pmin,sizeof(char)); + *pmin = (char)'P'; + __e_acsl_initialize((void *)pmax,sizeof(char)); + *pmax = (char)'L'; + int diff = (int)((unsigned long)pmax - (unsigned long)pmin); + /*@ assert \valid(pmin); */ + { + int __gen_e_acsl_initialized_3; + int __gen_e_acsl_and_3; + __gen_e_acsl_initialized_3 = __e_acsl_initialized((void *)(& pmin), + sizeof(char *)); + if (__gen_e_acsl_initialized_3) { + int __gen_e_acsl_valid_5; + __gen_e_acsl_valid_5 = __e_acsl_valid((void *)pmin,sizeof(char), + (void *)pmin,(void *)(& pmin)); + __gen_e_acsl_and_3 = __gen_e_acsl_valid_5; + } + else __gen_e_acsl_and_3 = 0; + __e_acsl_assert(__gen_e_acsl_and_3,(char *)"Assertion",(char *)"main", + (char *)"\\valid(pmin)",49); + } + /*@ assert \valid(pmax); */ + { + int __gen_e_acsl_initialized_4; + int __gen_e_acsl_and_4; + __gen_e_acsl_initialized_4 = __e_acsl_initialized((void *)(& pmax), + sizeof(char *)); + if (__gen_e_acsl_initialized_4) { + int __gen_e_acsl_valid_6; + __gen_e_acsl_valid_6 = __e_acsl_valid((void *)pmax,sizeof(char), + (void *)pmax,(void *)(& pmax)); + __gen_e_acsl_and_4 = __gen_e_acsl_valid_6; + } + else __gen_e_acsl_and_4 = 0; + __e_acsl_assert(__gen_e_acsl_and_4,(char *)"Assertion",(char *)"main", + (char *)"\\valid(pmax)",50); + } + /*@ assert ¬\valid(pmin + diff); */ + { + int __gen_e_acsl_valid_7; + __gen_e_acsl_valid_7 = __e_acsl_valid((void *)(pmin + diff),sizeof(char), + (void *)pmin,(void *)(& pmin)); + __e_acsl_assert(! __gen_e_acsl_valid_7,(char *)"Assertion", + (char *)"main",(char *)"!\\valid(pmin + diff)",52); + } + /*@ assert ¬\valid(pmax - diff); */ + { + int __gen_e_acsl_valid_8; + __gen_e_acsl_valid_8 = __e_acsl_valid((void *)(pmax - diff),sizeof(char), + (void *)pmax,(void *)(& pmax)); + __e_acsl_assert(! __gen_e_acsl_valid_8,(char *)"Assertion", + (char *)"main",(char *)"!\\valid(pmax - diff)",54); + } + __retres = 0; + __e_acsl_delete_block((void *)(& B)); + __e_acsl_delete_block((void *)(& pmax)); + __e_acsl_delete_block((void *)(& pmin)); + __e_acsl_delete_block((void *)(& b)); + __e_acsl_delete_block((void *)(& p)); + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/gen_bypassed_var.c b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_bypassed_var.c new file mode 100644 index 0000000000000000000000000000000000000000..a81553b33c8c62559cfc9736c2900f3908a385e6 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_bypassed_var.c @@ -0,0 +1,31 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +int main(int argc, char const **argv) +{ + int __retres; + __e_acsl_memory_init(& argc,(char ***)(& argv),(size_t)8); + goto L; + { + int *p; + __e_acsl_store_block((void *)(& p),(size_t)8); + L: __e_acsl_store_block_duplicate((void *)(& p),(size_t)8); + __e_acsl_full_init((void *)(& p)); + p = & argc; + /*@ assert \valid(&p); */ + { + int __gen_e_acsl_valid; + __gen_e_acsl_valid = __e_acsl_valid((void *)(& p),sizeof(int *), + (void *)(& p),(void *)0); + __e_acsl_assert(__gen_e_acsl_valid,(char *)"Assertion",(char *)"main", + (char *)"\\valid(&p)",13); + __e_acsl_delete_block((void *)(& p)); + } + } + __retres = 0; + __e_acsl_delete_block((void *)(& argc)); + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/gen_call.c b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_call.c new file mode 100644 index 0000000000000000000000000000000000000000..ac3c12211ae0a06975ebc353c91922da10dcc108 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_call.c @@ -0,0 +1,67 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +extern int __e_acsl_sound_verdict; + +/*@ ensures \valid(\result); */ +int *__gen_e_acsl_f(int *x, int *y); + +int *f(int *x, int *y) +{ + __e_acsl_store_block((void *)(& y),(size_t)8); + __e_acsl_store_block((void *)(& x),(size_t)8); + __e_acsl_initialize((void *)y,sizeof(int)); + *y = 1; + __e_acsl_delete_block((void *)(& y)); + __e_acsl_delete_block((void *)(& x)); + return x; +} + +int main(void) +{ + int __retres; + int *p; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + __e_acsl_store_block((void *)(& p),(size_t)8); + int x = 0; + __e_acsl_store_block((void *)(& x),(size_t)4); + __e_acsl_full_init((void *)(& x)); + int *q = malloc(sizeof(int)); + __e_acsl_store_block((void *)(& q),(size_t)8); + __e_acsl_full_init((void *)(& q)); + int *r = malloc(sizeof(int)); + __e_acsl_full_init((void *)(& p)); + p = __gen_e_acsl_f(& x,q); + __e_acsl_full_init((void *)(& q)); + q = __gen_e_acsl_f(& x,r); + __retres = 0; + __e_acsl_delete_block((void *)(& q)); + __e_acsl_delete_block((void *)(& p)); + __e_acsl_delete_block((void *)(& x)); + __e_acsl_memory_clean(); + return __retres; +} + +/*@ ensures \valid(\result); */ +int *__gen_e_acsl_f(int *x, int *y) +{ + int *__retres; + __e_acsl_store_block((void *)(& __retres),(size_t)8); + __e_acsl_store_block((void *)(& y),(size_t)8); + __e_acsl_store_block((void *)(& x),(size_t)8); + __retres = f(x,y); + { + int __gen_e_acsl_valid; + __gen_e_acsl_valid = __e_acsl_valid((void *)__retres,sizeof(int), + (void *)__retres, + (void *)(& __retres)); + __e_acsl_assert(__gen_e_acsl_valid,(char *)"Postcondition",(char *)"f", + (char *)"\\valid(\\result)",7); + __e_acsl_delete_block((void *)(& y)); + __e_acsl_delete_block((void *)(& x)); + __e_acsl_delete_block((void *)(& __retres)); + return __retres; + } +} + + diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/gen_compound_initializers.c b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_compound_initializers.c new file mode 100644 index 0000000000000000000000000000000000000000..87e6f24710d6a9f653093cd9e295d2bdf32362dc --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_compound_initializers.c @@ -0,0 +1,185 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +char *__gen_e_acsl_literal_string_3; +char *__gen_e_acsl_literal_string; +char *__gen_e_acsl_literal_string_2; +char *__gen_e_acsl_literal_string_4; +char *__gen_e_acsl_literal_string_5; +struct ST { + char *str ; + int num ; +}; +int _F; + +char *_A[2] = {(char *)"XX", (char *)"YY"}; +char *_B = (char *)"ZZ"; +char *_C; +int _D[2] = {44, 88}; +int _E = 44; +int _F = 9; +struct ST _G[2] = + {{.str = (char *)"First", .num = 99}, {.str = (char *)"Second", .num = 147}}; +void __e_acsl_globals_init(void) +{ + static char __e_acsl_already_run = 0; + if (! __e_acsl_already_run) { + __e_acsl_already_run = 1; + __gen_e_acsl_literal_string_3 = "ZZ"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_3,sizeof("ZZ")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_3); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_3); + __gen_e_acsl_literal_string = "YY"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string,sizeof("YY")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string); + __gen_e_acsl_literal_string_2 = "XX"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_2,sizeof("XX")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_2); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_2); + __gen_e_acsl_literal_string_4 = "Second"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_4, + sizeof("Second")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_4); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_4); + __gen_e_acsl_literal_string_5 = "First"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_5, + sizeof("First")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_5); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_5); + __e_acsl_store_block((void *)(_G),(size_t)32); + __e_acsl_full_init((void *)(& _G)); + __e_acsl_store_block((void *)(& _E),(size_t)4); + __e_acsl_full_init((void *)(& _E)); + __e_acsl_store_block((void *)(_D),(size_t)8); + __e_acsl_full_init((void *)(& _D)); + __e_acsl_store_block((void *)(& _C),(size_t)8); + __e_acsl_full_init((void *)(& _C)); + __e_acsl_store_block((void *)(& _B),(size_t)8); + __e_acsl_full_init((void *)(& _B)); + __e_acsl_store_block((void *)(_A),(size_t)16); + __e_acsl_full_init((void *)(& _A)); + __e_acsl_store_block((void *)(& _F),(size_t)4); + __e_acsl_full_init((void *)(& _F)); + } + return; +} + +int main(int argc, char **argv) +{ + int __retres; + __e_acsl_memory_init(& argc,& argv,(size_t)8); + __e_acsl_globals_init(); + /*@ assert \valid((char **)_A); */ + { + int __gen_e_acsl_valid; + __gen_e_acsl_valid = __e_acsl_valid((void *)(_A),sizeof(char *), + (void *)(_A),(void *)(_A)); + __e_acsl_assert(__gen_e_acsl_valid,(char *)"Assertion",(char *)"main", + (char *)"\\valid((char **)_A)",33); + } + /*@ assert \valid_read(_A[0]); */ + { + int __gen_e_acsl_initialized; + int __gen_e_acsl_and; + __gen_e_acsl_initialized = __e_acsl_initialized((void *)(_A), + sizeof(char *)); + if (__gen_e_acsl_initialized) { + int __gen_e_acsl_valid_read; + __gen_e_acsl_valid_read = __e_acsl_valid_read((void *)_A[0], + sizeof(char), + (void *)_A[0], + (void *)(_A)); + __gen_e_acsl_and = __gen_e_acsl_valid_read; + } + else __gen_e_acsl_and = 0; + __e_acsl_assert(__gen_e_acsl_and,(char *)"Assertion",(char *)"main", + (char *)"\\valid_read(_A[0])",34); + } + /*@ assert \valid_read(_A[1]); */ + { + int __gen_e_acsl_initialized_2; + int __gen_e_acsl_and_2; + __gen_e_acsl_initialized_2 = __e_acsl_initialized((void *)(& _A[1]), + sizeof(char *)); + if (__gen_e_acsl_initialized_2) { + int __gen_e_acsl_valid_read_2; + __gen_e_acsl_valid_read_2 = __e_acsl_valid_read((void *)_A[1], + sizeof(char), + (void *)_A[1], + (void *)(& _A[1])); + __gen_e_acsl_and_2 = __gen_e_acsl_valid_read_2; + } + else __gen_e_acsl_and_2 = 0; + __e_acsl_assert(__gen_e_acsl_and_2,(char *)"Assertion",(char *)"main", + (char *)"\\valid_read(_A[1])",35); + } + /*@ assert \valid_read(_B); */ + { + int __gen_e_acsl_valid_read_3; + __gen_e_acsl_valid_read_3 = __e_acsl_valid_read((void *)_B,sizeof(char), + (void *)_B, + (void *)(& _B)); + __e_acsl_assert(__gen_e_acsl_valid_read_3,(char *)"Assertion", + (char *)"main",(char *)"\\valid_read(_B)",36); + } + /*@ assert \valid(&_C); */ + { + int __gen_e_acsl_valid_2; + __gen_e_acsl_valid_2 = __e_acsl_valid((void *)(& _C),sizeof(char *), + (void *)(& _C),(void *)0); + __e_acsl_assert(__gen_e_acsl_valid_2,(char *)"Assertion",(char *)"main", + (char *)"\\valid(&_C)",37); + } + /*@ assert \valid((int *)_D); */ + { + int __gen_e_acsl_valid_3; + __gen_e_acsl_valid_3 = __e_acsl_valid((void *)(_D),sizeof(int), + (void *)(_D),(void *)(_D)); + __e_acsl_assert(__gen_e_acsl_valid_3,(char *)"Assertion",(char *)"main", + (char *)"\\valid((int *)_D)",38); + } + /*@ assert \valid(&_E); */ + { + int __gen_e_acsl_valid_4; + __gen_e_acsl_valid_4 = __e_acsl_valid((void *)(& _E),sizeof(int), + (void *)(& _E),(void *)0); + __e_acsl_assert(__gen_e_acsl_valid_4,(char *)"Assertion",(char *)"main", + (char *)"\\valid(&_E)",39); + } + /*@ assert \valid(&_F); */ + { + int __gen_e_acsl_valid_5; + __gen_e_acsl_valid_5 = __e_acsl_valid((void *)(& _F),sizeof(int), + (void *)(& _F),(void *)0); + __e_acsl_assert(__gen_e_acsl_valid_5,(char *)"Assertion",(char *)"main", + (char *)"\\valid(&_F)",40); + } + /*@ assert _E ≡ 44; */ + __e_acsl_assert(_E == 44,(char *)"Assertion",(char *)"main", + (char *)"_E == 44",41); + /*@ assert \valid(&_G); */ + { + int __gen_e_acsl_valid_6; + __gen_e_acsl_valid_6 = __e_acsl_valid((void *)(& _G), + sizeof(struct ST [2]), + (void *)(& _G),(void *)0); + __e_acsl_assert(__gen_e_acsl_valid_6,(char *)"Assertion",(char *)"main", + (char *)"\\valid(&_G)",42); + } + /*@ assert _G[0].num ≡ 99; */ + __e_acsl_assert(_G[0].num == 99,(char *)"Assertion",(char *)"main", + (char *)"_G[0].num == 99",43); + __retres = 0; + __e_acsl_delete_block((void *)(_G)); + __e_acsl_delete_block((void *)(& _E)); + __e_acsl_delete_block((void *)(_D)); + __e_acsl_delete_block((void *)(& _C)); + __e_acsl_delete_block((void *)(& _B)); + __e_acsl_delete_block((void *)(_A)); + __e_acsl_delete_block((void *)(& _F)); + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/gen_constructor.c b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_constructor.c new file mode 100644 index 0000000000000000000000000000000000000000..15a99b43c04dacb8866abecb8ce0ef28e7db4bbf --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_constructor.c @@ -0,0 +1,44 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +char *__gen_e_acsl_literal_string_2; +char *__gen_e_acsl_literal_string; +void f(void) __attribute__((__constructor__)); +void f(void) +{ + printf(__gen_e_acsl_literal_string); + char *buf = malloc((unsigned long)10 * sizeof(char)); + free((void *)buf); + return; +} + +void __e_acsl_globals_init(void) +{ + static char __e_acsl_already_run = 0; + if (! __e_acsl_already_run) { + __e_acsl_already_run = 1; + __gen_e_acsl_literal_string_2 = "main\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_2, + sizeof("main\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_2); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_2); + __gen_e_acsl_literal_string = "f\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string,sizeof("f\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string); + } + return; +} + +int main(void) +{ + int __retres; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + __e_acsl_globals_init(); + printf(__gen_e_acsl_literal_string_2); + __retres = 0; + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/gen_ctype_macros.c b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_ctype_macros.c new file mode 100644 index 0000000000000000000000000000000000000000..61c4ee241f00e0f38f0f4c0ebfcefdb38451f089 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_ctype_macros.c @@ -0,0 +1,42 @@ +/* Generated by Frama-C */ +#include "ctype.h" +#include "stdio.h" +#include "stdlib.h" +extern int __e_acsl_sound_verdict; + +int main(int argc, char const **argv) +{ + int __retres; + int tmp; + __e_acsl_memory_init(& argc,(char ***)(& argv),(size_t)8); + tmp = __gen_e_acsl_isupper(argc); + char c = (char)tmp; + __e_acsl_store_block((void *)(& c),(size_t)1); + __e_acsl_full_init((void *)(& c)); + char *d = & c; + __e_acsl_store_block((void *)(& d),(size_t)8); + __e_acsl_full_init((void *)(& d)); + /*@ assert \valid(d); */ + { + int __gen_e_acsl_initialized; + int __gen_e_acsl_and; + __gen_e_acsl_initialized = __e_acsl_initialized((void *)(& d), + sizeof(char *)); + if (__gen_e_acsl_initialized) { + int __gen_e_acsl_valid; + __gen_e_acsl_valid = __e_acsl_valid((void *)d,sizeof(char),(void *)d, + (void *)(& d)); + __gen_e_acsl_and = __gen_e_acsl_valid; + } + else __gen_e_acsl_and = 0; + __e_acsl_assert(__gen_e_acsl_and,(char *)"Assertion",(char *)"main", + (char *)"\\valid(d)",39); + } + __retres = 0; + __e_acsl_delete_block((void *)(& d)); + __e_acsl_delete_block((void *)(& c)); + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/gen_decl_in_switch.c b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_decl_in_switch.c new file mode 100644 index 0000000000000000000000000000000000000000..44c5d1497e4120146834c9da6a048d63af4800c6 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_decl_in_switch.c @@ -0,0 +1,146 @@ +/* Generated by Frama-C */ +typedef unsigned long size_t; +struct __e_acsl_mpz_struct { + int _mp_alloc ; + int _mp_size ; + unsigned long *_mp_d ; +}; +typedef struct __e_acsl_mpz_struct __e_acsl_mpz_struct; +typedef __e_acsl_mpz_struct ( __attribute__((__FC_BUILTIN__)) __e_acsl_mpz_t)[1]; +struct __e_acsl_mpq_struct { + __e_acsl_mpz_struct _mp_num ; + __e_acsl_mpz_struct _mp_den ; +}; +typedef struct __e_acsl_mpq_struct __e_acsl_mpq_struct; +typedef __e_acsl_mpq_struct ( __attribute__((__FC_BUILTIN__)) __e_acsl_mpq_t)[1]; +typedef struct _IO_FILE FILE; +/*@ ghost extern int __e_acsl_init; */ + +extern size_t __e_acsl_heap_allocation_size; + +typedef unsigned short __uint16_t; +typedef unsigned int __uint32_t; +typedef unsigned long __uint64_t; +typedef long __off_t; +typedef long __off64_t; +struct _IO_FILE; +typedef void _IO_lock_t; +struct _IO_marker { + struct _IO_marker *_next ; + struct _IO_FILE *_sbuf ; + int _pos ; +}; +struct _IO_FILE { + int _flags ; + char *_IO_read_ptr ; + char *_IO_read_end ; + char *_IO_read_base ; + char *_IO_write_base ; + char *_IO_write_ptr ; + char *_IO_write_end ; + char *_IO_buf_base ; + char *_IO_buf_end ; + char *_IO_save_base ; + char *_IO_backup_base ; + char *_IO_save_end ; + struct _IO_marker *_markers ; + struct _IO_FILE *_chain ; + int _fileno ; + int _flags2 ; + __off_t _old_offset ; + unsigned short _cur_column ; + signed char _vtable_offset ; + char _shortbuf[1] ; + _IO_lock_t *_lock ; + __off64_t _offset ; + void *__pad1 ; + void *__pad2 ; + void *__pad3 ; + void *__pad4 ; + size_t __pad5 ; + int _mode ; + char _unused2[((unsigned long)15 * sizeof(int) - (unsigned long)4 * sizeof(void *)) - sizeof(size_t)] ; +}; +/* compiler builtin: + unsigned int __builtin_bswap32(unsigned int); */ +/* compiler builtin: + unsigned long __builtin_bswap64(unsigned long); */ +__inline static unsigned int __bswap_32(unsigned int __bsx) +{ + unsigned int tmp; + tmp = __builtin_bswap32(__bsx); + return tmp; +} + +__inline static __uint64_t __bswap_64(__uint64_t __bsx) +{ + __uint64_t tmp; + tmp = __builtin_bswap64(__bsx); + return tmp; +} + +__inline static __uint16_t __uint16_identity(__uint16_t __x) +{ + return __x; +} + +__inline static __uint32_t __uint32_identity(__uint32_t __x) +{ + return __x; +} + +__inline static __uint64_t __uint64_identity(__uint64_t __x) +{ + return __x; +} + +/*@ +predicate diffSize{L1, L2}(ℤ i) = + \at(__e_acsl_heap_allocation_size,L1) - + \at(__e_acsl_heap_allocation_size,L2) ≡ i; + +*/ +extern __attribute__((__FC_BUILTIN__)) int ( /* missing proto */ __e_acsl_memory_init)( +int *x_0, char ***x_1, unsigned long x_2); + +extern __attribute__((__FC_BUILTIN__)) int ( /* missing proto */ __e_acsl_store_block)( +void *x_0, unsigned long x_1); + +extern __attribute__((__FC_BUILTIN__)) int ( /* missing proto */ __e_acsl_full_init)( +void *x_0); + +extern __attribute__((__FC_BUILTIN__)) int ( /* missing proto */ __e_acsl_delete_block)( +void *x_0); + +extern __attribute__((__FC_BUILTIN__)) int ( /* missing proto */ __e_acsl_memory_clean)( +void); + +int main(int argc, char **argv) +{ + int __retres; + __e_acsl_memory_init(& argc,& argv,8UL); + __e_acsl_memory_init(& argc,& argv,8UL); + __e_acsl_store_block((void *)(& argc),4UL); + { + int *p; + __e_acsl_store_block((void *)(& p),8UL); + __e_acsl_store_block((void *)(& p),8UL); + switch (argc) { + default: ; + __e_acsl_full_init((void *)(& p)); + __e_acsl_full_init((void *)(& p)); + p = & argc; + break; + } + __e_acsl_delete_block((void *)(& p)); + __e_acsl_delete_block((void *)(& p)); + } + __retres = 0; + __e_acsl_delete_block((void *)(& argc)); + __e_acsl_memory_clean(); + __e_acsl_delete_block((void *)(& argc)); + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/gen_early_exit.c b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_early_exit.c new file mode 100644 index 0000000000000000000000000000000000000000..9283676c3db0d7fb6ca941b96724f48062ea56e4 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_early_exit.c @@ -0,0 +1,690 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +int goto_bts(void) +{ + int __retres; + int *p; + __e_acsl_store_block((void *)(& p),(size_t)8); + { + int a = 0; + __e_acsl_store_block((void *)(& a),(size_t)4); + __e_acsl_full_init((void *)(& a)); + __e_acsl_full_init((void *)(& p)); + p = & a; + /*@ assert \valid(p); */ + { + int __gen_e_acsl_initialized; + int __gen_e_acsl_and; + __gen_e_acsl_initialized = __e_acsl_initialized((void *)(& p), + sizeof(int *)); + if (__gen_e_acsl_initialized) { + int __gen_e_acsl_valid; + __gen_e_acsl_valid = __e_acsl_valid((void *)p,sizeof(int),(void *)p, + (void *)(& p)); + __gen_e_acsl_and = __gen_e_acsl_valid; + } + else __gen_e_acsl_and = 0; + __e_acsl_assert(__gen_e_acsl_and,(char *)"Assertion", + (char *)"goto_bts",(char *)"\\valid(p)",13); + } + __e_acsl_delete_block((void *)(& a)); + goto L; + __e_acsl_delete_block((void *)(& a)); + } + L: + /*@ assert ¬\valid(p); */ + { + int __gen_e_acsl_initialized_2; + int __gen_e_acsl_and_2; + __gen_e_acsl_initialized_2 = __e_acsl_initialized((void *)(& p), + sizeof(int *)); + if (__gen_e_acsl_initialized_2) { + int __gen_e_acsl_valid_2; + /*@ assert Eva: dangling_pointer: ¬\dangling(&p); */ + __gen_e_acsl_valid_2 = __e_acsl_valid((void *)p,sizeof(int),(void *)p, + (void *)(& p)); + __gen_e_acsl_and_2 = __gen_e_acsl_valid_2; + } + else __gen_e_acsl_and_2 = 0; + __e_acsl_assert(! __gen_e_acsl_and_2,(char *)"Assertion", + (char *)"goto_bts",(char *)"!\\valid(p)",18); + } + __retres = 0; + __e_acsl_delete_block((void *)(& p)); + return __retres; +} + +int goto_valid(void) +{ + int __retres; + int *p; + int *q; + int *r; + __e_acsl_store_block((void *)(& r),(size_t)8); + __e_acsl_store_block((void *)(& q),(size_t)8); + __e_acsl_store_block((void *)(& p),(size_t)8); + int a = 9; + { + int a1 = 0; + __e_acsl_store_block((void *)(& a1),(size_t)4); + __e_acsl_full_init((void *)(& a1)); + __e_acsl_full_init((void *)(& p)); + p = & a1; + { + int a2 = 0; + __e_acsl_store_block((void *)(& a2),(size_t)4); + __e_acsl_full_init((void *)(& a2)); + __e_acsl_full_init((void *)(& q)); + q = & a2; + { + int a3 = 0; + __e_acsl_store_block((void *)(& a3),(size_t)4); + __e_acsl_full_init((void *)(& a3)); + __e_acsl_full_init((void *)(& r)); + r = & a3; + __e_acsl_delete_block((void *)(& a2)); + __e_acsl_delete_block((void *)(& a3)); + goto FIRST; + __e_acsl_full_init((void *)(& p)); + p = (int *)0; + __e_acsl_full_init((void *)(& q)); + q = & a; + __e_acsl_full_init((void *)(& r)); + r = q; + __e_acsl_delete_block((void *)(& a3)); + __e_acsl_delete_block((void *)(& a2)); + } + } + FIRST: + /*@ assert \valid(p); */ + { + int __gen_e_acsl_initialized; + int __gen_e_acsl_and; + __gen_e_acsl_initialized = __e_acsl_initialized((void *)(& p), + sizeof(int *)); + if (__gen_e_acsl_initialized) { + int __gen_e_acsl_valid; + __gen_e_acsl_valid = __e_acsl_valid((void *)p,sizeof(int),(void *)p, + (void *)(& p)); + __gen_e_acsl_and = __gen_e_acsl_valid; + } + else __gen_e_acsl_and = 0; + __e_acsl_assert(__gen_e_acsl_and,(char *)"Assertion", + (char *)"goto_valid",(char *)"\\valid(p)",46); + } + /*@ assert ¬\valid(q); */ + { + int __gen_e_acsl_initialized_2; + int __gen_e_acsl_and_2; + __gen_e_acsl_initialized_2 = __e_acsl_initialized((void *)(& q), + sizeof(int *)); + if (__gen_e_acsl_initialized_2) { + int __gen_e_acsl_valid_2; + __gen_e_acsl_valid_2 = __e_acsl_valid((void *)q,sizeof(int), + (void *)q,(void *)(& q)); + __gen_e_acsl_and_2 = __gen_e_acsl_valid_2; + } + else __gen_e_acsl_and_2 = 0; + __e_acsl_assert(! __gen_e_acsl_and_2,(char *)"Assertion", + (char *)"goto_valid",(char *)"!\\valid(q)",47); + } + /*@ assert ¬\valid(r); */ + { + int __gen_e_acsl_initialized_3; + int __gen_e_acsl_and_3; + __gen_e_acsl_initialized_3 = __e_acsl_initialized((void *)(& r), + sizeof(int *)); + if (__gen_e_acsl_initialized_3) { + int __gen_e_acsl_valid_3; + __gen_e_acsl_valid_3 = __e_acsl_valid((void *)r,sizeof(int), + (void *)r,(void *)(& r)); + __gen_e_acsl_and_3 = __gen_e_acsl_valid_3; + } + else __gen_e_acsl_and_3 = 0; + __e_acsl_assert(! __gen_e_acsl_and_3,(char *)"Assertion", + (char *)"goto_valid",(char *)"!\\valid(r)",48); + } + __e_acsl_delete_block((void *)(& a1)); + goto SECOND; + __e_acsl_full_init((void *)(& q)); + q = & a; + __e_acsl_full_init((void *)(& r)); + r = q; + __e_acsl_full_init((void *)(& p)); + p = r; + __e_acsl_delete_block((void *)(& a1)); + } + SECOND: + /*@ assert ¬\valid(p); */ + { + int __gen_e_acsl_initialized_4; + int __gen_e_acsl_and_4; + __gen_e_acsl_initialized_4 = __e_acsl_initialized((void *)(& p), + sizeof(int *)); + if (__gen_e_acsl_initialized_4) { + int __gen_e_acsl_valid_4; + __gen_e_acsl_valid_4 = __e_acsl_valid((void *)p,sizeof(int),(void *)p, + (void *)(& p)); + __gen_e_acsl_and_4 = __gen_e_acsl_valid_4; + } + else __gen_e_acsl_and_4 = 0; + __e_acsl_assert(! __gen_e_acsl_and_4,(char *)"Assertion", + (char *)"goto_valid",(char *)"!\\valid(p)",56); + } + /*@ assert ¬\valid(q); */ + { + int __gen_e_acsl_initialized_5; + int __gen_e_acsl_and_5; + __gen_e_acsl_initialized_5 = __e_acsl_initialized((void *)(& q), + sizeof(int *)); + if (__gen_e_acsl_initialized_5) { + int __gen_e_acsl_valid_5; + __gen_e_acsl_valid_5 = __e_acsl_valid((void *)q,sizeof(int),(void *)q, + (void *)(& q)); + __gen_e_acsl_and_5 = __gen_e_acsl_valid_5; + } + else __gen_e_acsl_and_5 = 0; + __e_acsl_assert(! __gen_e_acsl_and_5,(char *)"Assertion", + (char *)"goto_valid",(char *)"!\\valid(q)",57); + } + /*@ assert ¬\valid(r); */ + { + int __gen_e_acsl_initialized_6; + int __gen_e_acsl_and_6; + __gen_e_acsl_initialized_6 = __e_acsl_initialized((void *)(& r), + sizeof(int *)); + if (__gen_e_acsl_initialized_6) { + int __gen_e_acsl_valid_6; + __gen_e_acsl_valid_6 = __e_acsl_valid((void *)r,sizeof(int),(void *)r, + (void *)(& r)); + __gen_e_acsl_and_6 = __gen_e_acsl_valid_6; + } + else __gen_e_acsl_and_6 = 0; + __e_acsl_assert(! __gen_e_acsl_and_6,(char *)"Assertion", + (char *)"goto_valid",(char *)"!\\valid(r)",58); + } + __retres = 0; + __e_acsl_delete_block((void *)(& r)); + __e_acsl_delete_block((void *)(& q)); + __e_acsl_delete_block((void *)(& p)); + return __retres; +} + +int switch_valid(void) +{ + int __retres; + int *p; + int *q; + int *s; + __e_acsl_store_block((void *)(& s),(size_t)8); + __e_acsl_store_block((void *)(& q),(size_t)8); + __e_acsl_store_block((void *)(& p),(size_t)8); + int i = 1; + __e_acsl_store_block((void *)(& i),(size_t)4); + __e_acsl_full_init((void *)(& i)); + __e_acsl_full_init((void *)(& s)); + s = & i; + switch (i) { + default: + { + int a1 = 0; + __e_acsl_store_block((void *)(& a1),(size_t)4); + __e_acsl_full_init((void *)(& a1)); + __e_acsl_full_init((void *)(& p)); + p = & a1; + { + int a2 = 0; + __e_acsl_store_block((void *)(& a2),(size_t)4); + __e_acsl_full_init((void *)(& a2)); + __e_acsl_full_init((void *)(& q)); + q = & a2; + /*@ assert \valid(p); */ + { + int __gen_e_acsl_initialized; + int __gen_e_acsl_and; + __gen_e_acsl_initialized = __e_acsl_initialized((void *)(& p), + sizeof(int *)); + if (__gen_e_acsl_initialized) { + int __gen_e_acsl_valid; + __gen_e_acsl_valid = __e_acsl_valid((void *)p,sizeof(int), + (void *)p,(void *)(& p)); + __gen_e_acsl_and = __gen_e_acsl_valid; + } + else __gen_e_acsl_and = 0; + __e_acsl_assert(__gen_e_acsl_and,(char *)"Assertion", + (char *)"switch_valid",(char *)"\\valid(p)",76); + } + /*@ assert \valid(q); */ + { + int __gen_e_acsl_initialized_2; + int __gen_e_acsl_and_2; + __gen_e_acsl_initialized_2 = __e_acsl_initialized((void *)(& q), + sizeof(int *)); + if (__gen_e_acsl_initialized_2) { + int __gen_e_acsl_valid_2; + __gen_e_acsl_valid_2 = __e_acsl_valid((void *)q,sizeof(int), + (void *)q,(void *)(& q)); + __gen_e_acsl_and_2 = __gen_e_acsl_valid_2; + } + else __gen_e_acsl_and_2 = 0; + __e_acsl_assert(__gen_e_acsl_and_2,(char *)"Assertion", + (char *)"switch_valid",(char *)"\\valid(q)",77); + } + /*@ assert \valid(s); */ + { + int __gen_e_acsl_initialized_3; + int __gen_e_acsl_and_3; + __gen_e_acsl_initialized_3 = __e_acsl_initialized((void *)(& s), + sizeof(int *)); + if (__gen_e_acsl_initialized_3) { + int __gen_e_acsl_valid_3; + __gen_e_acsl_valid_3 = __e_acsl_valid((void *)s,sizeof(int), + (void *)s,(void *)(& s)); + __gen_e_acsl_and_3 = __gen_e_acsl_valid_3; + } + else __gen_e_acsl_and_3 = 0; + __e_acsl_assert(__gen_e_acsl_and_3,(char *)"Assertion", + (char *)"switch_valid",(char *)"\\valid(s)",78); + } + __e_acsl_delete_block((void *)(& a1)); + __e_acsl_delete_block((void *)(& a2)); + break; + __e_acsl_delete_block((void *)(& a2)); + } + __e_acsl_full_init((void *)(& q)); + q = & i; + __e_acsl_full_init((void *)(& p)); + p = q; + __e_acsl_full_init((void *)(& s)); + s = (int *)0; + __e_acsl_delete_block((void *)(& a1)); + } + } + /*@ assert ¬\valid(q); */ + { + int __gen_e_acsl_initialized_4; + int __gen_e_acsl_and_4; + __gen_e_acsl_initialized_4 = __e_acsl_initialized((void *)(& q), + sizeof(int *)); + if (__gen_e_acsl_initialized_4) { + int __gen_e_acsl_valid_4; + __gen_e_acsl_valid_4 = __e_acsl_valid((void *)q,sizeof(int),(void *)q, + (void *)(& q)); + __gen_e_acsl_and_4 = __gen_e_acsl_valid_4; + } + else __gen_e_acsl_and_4 = 0; + __e_acsl_assert(! __gen_e_acsl_and_4,(char *)"Assertion", + (char *)"switch_valid",(char *)"!\\valid(q)",87); + } + /*@ assert ¬\valid(p); */ + { + int __gen_e_acsl_initialized_5; + int __gen_e_acsl_and_5; + __gen_e_acsl_initialized_5 = __e_acsl_initialized((void *)(& p), + sizeof(int *)); + if (__gen_e_acsl_initialized_5) { + int __gen_e_acsl_valid_5; + __gen_e_acsl_valid_5 = __e_acsl_valid((void *)p,sizeof(int),(void *)p, + (void *)(& p)); + __gen_e_acsl_and_5 = __gen_e_acsl_valid_5; + } + else __gen_e_acsl_and_5 = 0; + __e_acsl_assert(! __gen_e_acsl_and_5,(char *)"Assertion", + (char *)"switch_valid",(char *)"!\\valid(p)",88); + } + /*@ assert \valid(s); */ + { + int __gen_e_acsl_initialized_6; + int __gen_e_acsl_and_6; + __gen_e_acsl_initialized_6 = __e_acsl_initialized((void *)(& s), + sizeof(int *)); + if (__gen_e_acsl_initialized_6) { + int __gen_e_acsl_valid_6; + __gen_e_acsl_valid_6 = __e_acsl_valid((void *)s,sizeof(int),(void *)s, + (void *)(& s)); + __gen_e_acsl_and_6 = __gen_e_acsl_valid_6; + } + else __gen_e_acsl_and_6 = 0; + __e_acsl_assert(__gen_e_acsl_and_6,(char *)"Assertion", + (char *)"switch_valid",(char *)"\\valid(s)",89); + } + __retres = 0; + __e_acsl_delete_block((void *)(& s)); + __e_acsl_delete_block((void *)(& q)); + __e_acsl_delete_block((void *)(& p)); + __e_acsl_delete_block((void *)(& i)); + return __retres; +} + +int while_valid(void) +{ + int __retres; + int *p; + int *q; + int *r; + __e_acsl_store_block((void *)(& r),(size_t)8); + __e_acsl_store_block((void *)(& q),(size_t)8); + __e_acsl_store_block((void *)(& p),(size_t)8); + int i = 5; + { + int a0 = 0; + __e_acsl_store_block((void *)(& a0),(size_t)4); + __e_acsl_full_init((void *)(& a0)); + __e_acsl_full_init((void *)(& r)); + r = & a0; + while (1) { + i --; + if (! i) break; + { + int a1 = 0; + __e_acsl_store_block((void *)(& a1),(size_t)4); + __e_acsl_full_init((void *)(& a1)); + __e_acsl_full_init((void *)(& p)); + p = & a1; + { + int a2 = 0; + __e_acsl_store_block((void *)(& a2),(size_t)4); + __e_acsl_full_init((void *)(& a2)); + __e_acsl_full_init((void *)(& q)); + q = & a2; + /*@ assert \valid(p); */ + { + int __gen_e_acsl_initialized; + int __gen_e_acsl_and; + __gen_e_acsl_initialized = __e_acsl_initialized((void *)(& p), + sizeof(int *)); + if (__gen_e_acsl_initialized) { + int __gen_e_acsl_valid; + __gen_e_acsl_valid = __e_acsl_valid((void *)p,sizeof(int), + (void *)p,(void *)(& p)); + __gen_e_acsl_and = __gen_e_acsl_valid; + } + else __gen_e_acsl_and = 0; + __e_acsl_assert(__gen_e_acsl_and,(char *)"Assertion", + (char *)"while_valid",(char *)"\\valid(p)",108); + } + /*@ assert \valid(q); */ + { + int __gen_e_acsl_initialized_2; + int __gen_e_acsl_and_2; + __gen_e_acsl_initialized_2 = __e_acsl_initialized((void *)(& q), + sizeof(int *)); + if (__gen_e_acsl_initialized_2) { + int __gen_e_acsl_valid_2; + __gen_e_acsl_valid_2 = __e_acsl_valid((void *)q,sizeof(int), + (void *)q,(void *)(& q)); + __gen_e_acsl_and_2 = __gen_e_acsl_valid_2; + } + else __gen_e_acsl_and_2 = 0; + __e_acsl_assert(__gen_e_acsl_and_2,(char *)"Assertion", + (char *)"while_valid",(char *)"\\valid(q)",109); + } + /*@ assert \valid(r); */ + { + int __gen_e_acsl_initialized_3; + int __gen_e_acsl_and_3; + __gen_e_acsl_initialized_3 = __e_acsl_initialized((void *)(& r), + sizeof(int *)); + if (__gen_e_acsl_initialized_3) { + int __gen_e_acsl_valid_3; + __gen_e_acsl_valid_3 = __e_acsl_valid((void *)r,sizeof(int), + (void *)r,(void *)(& r)); + __gen_e_acsl_and_3 = __gen_e_acsl_valid_3; + } + else __gen_e_acsl_and_3 = 0; + __e_acsl_assert(__gen_e_acsl_and_3,(char *)"Assertion", + (char *)"while_valid",(char *)"\\valid(r)",110); + } + if (! i) { + __e_acsl_delete_block((void *)(& a1)); + __e_acsl_delete_block((void *)(& a2)); + break; + } + __e_acsl_delete_block((void *)(& a2)); + __e_acsl_delete_block((void *)(& a1)); + } + } + } + /*@ assert ¬\valid(p); */ + { + int __gen_e_acsl_initialized_4; + int __gen_e_acsl_and_4; + __gen_e_acsl_initialized_4 = __e_acsl_initialized((void *)(& p), + sizeof(int *)); + if (__gen_e_acsl_initialized_4) { + int __gen_e_acsl_valid_4; + __gen_e_acsl_valid_4 = __e_acsl_valid((void *)p,sizeof(int), + (void *)p,(void *)(& p)); + __gen_e_acsl_and_4 = __gen_e_acsl_valid_4; + } + else __gen_e_acsl_and_4 = 0; + __e_acsl_assert(! __gen_e_acsl_and_4,(char *)"Assertion", + (char *)"while_valid",(char *)"!\\valid(p)",116); + } + /*@ assert ¬\valid(q); */ + { + int __gen_e_acsl_initialized_5; + int __gen_e_acsl_and_5; + __gen_e_acsl_initialized_5 = __e_acsl_initialized((void *)(& q), + sizeof(int *)); + if (__gen_e_acsl_initialized_5) { + int __gen_e_acsl_valid_5; + __gen_e_acsl_valid_5 = __e_acsl_valid((void *)q,sizeof(int), + (void *)q,(void *)(& q)); + __gen_e_acsl_and_5 = __gen_e_acsl_valid_5; + } + else __gen_e_acsl_and_5 = 0; + __e_acsl_assert(! __gen_e_acsl_and_5,(char *)"Assertion", + (char *)"while_valid",(char *)"!\\valid(q)",117); + } + /*@ assert \valid(r); */ + { + int __gen_e_acsl_initialized_6; + int __gen_e_acsl_and_6; + __gen_e_acsl_initialized_6 = __e_acsl_initialized((void *)(& r), + sizeof(int *)); + if (__gen_e_acsl_initialized_6) { + int __gen_e_acsl_valid_6; + __gen_e_acsl_valid_6 = __e_acsl_valid((void *)r,sizeof(int), + (void *)r,(void *)(& r)); + __gen_e_acsl_and_6 = __gen_e_acsl_valid_6; + } + else __gen_e_acsl_and_6 = 0; + __e_acsl_assert(__gen_e_acsl_and_6,(char *)"Assertion", + (char *)"while_valid",(char *)"\\valid(r)",118); + __e_acsl_delete_block((void *)(& a0)); + } + } + __retres = 0; + __e_acsl_delete_block((void *)(& r)); + __e_acsl_delete_block((void *)(& q)); + __e_acsl_delete_block((void *)(& p)); + return __retres; +} + +void continue_valid(void) +{ + int *p; + int *q; + __e_acsl_store_block((void *)(& q),(size_t)8); + __e_acsl_store_block((void *)(& p),(size_t)8); + int i = 0; + while (1) { + int tmp; + tmp = i; + i ++; + ; + if (! tmp) break; + { + /*@ assert ¬\valid(p); */ + { + int __gen_e_acsl_initialized; + int __gen_e_acsl_and; + __gen_e_acsl_initialized = __e_acsl_initialized((void *)(& p), + sizeof(int *)); + if (__gen_e_acsl_initialized) { + int __gen_e_acsl_valid; + __gen_e_acsl_valid = __e_acsl_valid((void *)p,sizeof(int), + (void *)p,(void *)(& p)); + __gen_e_acsl_and = __gen_e_acsl_valid; + } + else __gen_e_acsl_and = 0; + __e_acsl_assert(! __gen_e_acsl_and,(char *)"Assertion", + (char *)"continue_valid",(char *)"!\\valid(p)",130); + } + /*@ assert ¬\valid(q); */ + { + int __gen_e_acsl_initialized_2; + int __gen_e_acsl_and_2; + __gen_e_acsl_initialized_2 = __e_acsl_initialized((void *)(& q), + sizeof(int *)); + if (__gen_e_acsl_initialized_2) { + int __gen_e_acsl_valid_2; + __gen_e_acsl_valid_2 = __e_acsl_valid((void *)q,sizeof(int), + (void *)q,(void *)(& q)); + __gen_e_acsl_and_2 = __gen_e_acsl_valid_2; + } + else __gen_e_acsl_and_2 = 0; + __e_acsl_assert(! __gen_e_acsl_and_2,(char *)"Assertion", + (char *)"continue_valid",(char *)"!\\valid(q)",131); + } + int a1 = 1; + __e_acsl_store_block((void *)(& a1),(size_t)4); + __e_acsl_full_init((void *)(& a1)); + __e_acsl_full_init((void *)(& p)); + p = & a1; + /*@ assert \valid(p); */ + { + int __gen_e_acsl_initialized_3; + int __gen_e_acsl_and_3; + __gen_e_acsl_initialized_3 = __e_acsl_initialized((void *)(& p), + sizeof(int *)); + if (__gen_e_acsl_initialized_3) { + int __gen_e_acsl_valid_3; + __gen_e_acsl_valid_3 = __e_acsl_valid((void *)p,sizeof(int), + (void *)p,(void *)(& p)); + __gen_e_acsl_and_3 = __gen_e_acsl_valid_3; + } + else __gen_e_acsl_and_3 = 0; + __e_acsl_assert(__gen_e_acsl_and_3,(char *)"Assertion", + (char *)"continue_valid",(char *)"\\valid(p)",135); + } + /*@ assert ¬\valid(q); */ + { + int __gen_e_acsl_initialized_4; + int __gen_e_acsl_and_4; + __gen_e_acsl_initialized_4 = __e_acsl_initialized((void *)(& q), + sizeof(int *)); + if (__gen_e_acsl_initialized_4) { + int __gen_e_acsl_valid_4; + __gen_e_acsl_valid_4 = __e_acsl_valid((void *)q,sizeof(int), + (void *)q,(void *)(& q)); + __gen_e_acsl_and_4 = __gen_e_acsl_valid_4; + } + else __gen_e_acsl_and_4 = 0; + __e_acsl_assert(! __gen_e_acsl_and_4,(char *)"Assertion", + (char *)"continue_valid",(char *)"!\\valid(q)",136); + } + { + int a2 = 1; + __e_acsl_store_block((void *)(& a2),(size_t)4); + __e_acsl_full_init((void *)(& a2)); + __e_acsl_full_init((void *)(& q)); + q = & a2; + /*@ assert \valid(p); */ + { + int __gen_e_acsl_initialized_5; + int __gen_e_acsl_and_5; + __gen_e_acsl_initialized_5 = __e_acsl_initialized((void *)(& p), + sizeof(int *)); + if (__gen_e_acsl_initialized_5) { + int __gen_e_acsl_valid_5; + __gen_e_acsl_valid_5 = __e_acsl_valid((void *)p,sizeof(int), + (void *)p,(void *)(& p)); + __gen_e_acsl_and_5 = __gen_e_acsl_valid_5; + } + else __gen_e_acsl_and_5 = 0; + __e_acsl_assert(__gen_e_acsl_and_5,(char *)"Assertion", + (char *)"continue_valid",(char *)"\\valid(p)",141); + } + /*@ assert \valid(q); */ + { + int __gen_e_acsl_initialized_6; + int __gen_e_acsl_and_6; + __gen_e_acsl_initialized_6 = __e_acsl_initialized((void *)(& q), + sizeof(int *)); + if (__gen_e_acsl_initialized_6) { + int __gen_e_acsl_valid_6; + __gen_e_acsl_valid_6 = __e_acsl_valid((void *)q,sizeof(int), + (void *)q,(void *)(& q)); + __gen_e_acsl_and_6 = __gen_e_acsl_valid_6; + } + else __gen_e_acsl_and_6 = 0; + __e_acsl_assert(__gen_e_acsl_and_6,(char *)"Assertion", + (char *)"continue_valid",(char *)"\\valid(q)",142); + } + __e_acsl_delete_block((void *)(& a1)); + __e_acsl_delete_block((void *)(& a2)); + continue; + __e_acsl_delete_block((void *)(& a2)); + } + if (i == 5) { + __e_acsl_delete_block((void *)(& a1)); + break; + } + __e_acsl_delete_block((void *)(& a1)); + } + } + /*@ assert ¬\valid(p); */ + { + int __gen_e_acsl_initialized_7; + int __gen_e_acsl_and_7; + __gen_e_acsl_initialized_7 = __e_acsl_initialized((void *)(& p), + sizeof(int *)); + if (__gen_e_acsl_initialized_7) { + int __gen_e_acsl_valid_7; + __gen_e_acsl_valid_7 = __e_acsl_valid((void *)p,sizeof(int),(void *)p, + (void *)(& p)); + __gen_e_acsl_and_7 = __gen_e_acsl_valid_7; + } + else __gen_e_acsl_and_7 = 0; + __e_acsl_assert(! __gen_e_acsl_and_7,(char *)"Assertion", + (char *)"continue_valid",(char *)"!\\valid(p)",150); + } + /*@ assert ¬\valid(q); */ + { + int __gen_e_acsl_initialized_8; + int __gen_e_acsl_and_8; + __gen_e_acsl_initialized_8 = __e_acsl_initialized((void *)(& q), + sizeof(int *)); + if (__gen_e_acsl_initialized_8) { + int __gen_e_acsl_valid_8; + __gen_e_acsl_valid_8 = __e_acsl_valid((void *)q,sizeof(int),(void *)q, + (void *)(& q)); + __gen_e_acsl_and_8 = __gen_e_acsl_valid_8; + } + else __gen_e_acsl_and_8 = 0; + __e_acsl_assert(! __gen_e_acsl_and_8,(char *)"Assertion", + (char *)"continue_valid",(char *)"!\\valid(q)",151); + } + __e_acsl_delete_block((void *)(& q)); + __e_acsl_delete_block((void *)(& p)); + return; +} + +int main(int argc, char const **argv) +{ + int __retres; + __e_acsl_memory_init(& argc,(char ***)(& argv),(size_t)8); + goto_bts(); + goto_valid(); + switch_valid(); + while_valid(); + continue_valid(); + __retres = 0; + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/gen_errno.c b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_errno.c new file mode 100644 index 0000000000000000000000000000000000000000..aa5c051fb3a7d54d3fcdf1f806ac8ab2c383ff18 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_errno.c @@ -0,0 +1,47 @@ +/* Generated by Frama-C */ +#include "errno.h" +#include "stdio.h" +#include "stdlib.h" +void __e_acsl_globals_init(void) +{ + static char __e_acsl_already_run = 0; + if (! __e_acsl_already_run) { + __e_acsl_already_run = 1; + __e_acsl_store_block((void *)(& errno),(size_t)4); + __e_acsl_full_init((void *)(& errno)); + } + return; +} + +int main(int argc, char const **argv) +{ + int __retres; + __e_acsl_memory_init(& argc,(char ***)(& argv),(size_t)8); + __e_acsl_globals_init(); + int *p = & errno; + __e_acsl_store_block((void *)(& p),(size_t)8); + __e_acsl_full_init((void *)(& p)); + /*@ assert \valid(p); */ + { + int __gen_e_acsl_initialized; + int __gen_e_acsl_and; + __gen_e_acsl_initialized = __e_acsl_initialized((void *)(& p), + sizeof(int *)); + if (__gen_e_acsl_initialized) { + int __gen_e_acsl_valid; + __gen_e_acsl_valid = __e_acsl_valid((void *)p,sizeof(int),(void *)p, + (void *)(& p)); + __gen_e_acsl_and = __gen_e_acsl_valid; + } + else __gen_e_acsl_and = 0; + __e_acsl_assert(__gen_e_acsl_and,(char *)"Assertion",(char *)"main", + (char *)"\\valid(p)",11); + } + __retres = 0; + __e_acsl_delete_block((void *)(& errno)); + __e_acsl_delete_block((void *)(& p)); + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/gen_freeable.c b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_freeable.c new file mode 100644 index 0000000000000000000000000000000000000000..2dd9560ae9b96d3996d9ce396d83a3f9cbd79a98 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_freeable.c @@ -0,0 +1,83 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +char array[1024]; +void __e_acsl_globals_init(void) +{ + static char __e_acsl_already_run = 0; + if (! __e_acsl_already_run) { + __e_acsl_already_run = 1; + __e_acsl_store_block((void *)(array),(size_t)1024); + __e_acsl_full_init((void *)(& array)); + } + return; +} + +int main(void) +{ + int __retres; + int *p; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + __e_acsl_globals_init(); + __e_acsl_store_block((void *)(& p),(size_t)8); + /*@ assert ¬\freeable(p); */ + { + int __gen_e_acsl_freeable; + /*@ assert Eva: initialization: \initialized(&p); */ + __gen_e_acsl_freeable = __e_acsl_freeable((void *)p); + __e_acsl_assert(! __gen_e_acsl_freeable,(char *)"Assertion", + (char *)"main",(char *)"!\\freeable(p)",14); + } + /*@ assert ¬\freeable((void *)0); */ + { + int __gen_e_acsl_freeable_2; + __gen_e_acsl_freeable_2 = __e_acsl_freeable((void *)0); + __e_acsl_assert(! __gen_e_acsl_freeable_2,(char *)"Assertion", + (char *)"main",(char *)"!\\freeable((void *)0)",15); + } + __e_acsl_full_init((void *)(& p)); + p = (int *)malloc((unsigned long)4 * sizeof(int)); + /*@ assert ¬\freeable(p + 1); */ + { + int __gen_e_acsl_freeable_3; + __gen_e_acsl_freeable_3 = __e_acsl_freeable((void *)(p + 1)); + __e_acsl_assert(! __gen_e_acsl_freeable_3,(char *)"Assertion", + (char *)"main",(char *)"!\\freeable(p + 1)",17); + } + /*@ assert \freeable(p); */ + { + int __gen_e_acsl_freeable_4; + __gen_e_acsl_freeable_4 = __e_acsl_freeable((void *)p); + __e_acsl_assert(__gen_e_acsl_freeable_4,(char *)"Assertion", + (char *)"main",(char *)"\\freeable(p)",18); + } + free((void *)p); + /*@ assert ¬\freeable(p); */ + { + int __gen_e_acsl_freeable_5; + __gen_e_acsl_freeable_5 = __e_acsl_freeable((void *)p); + __e_acsl_assert(! __gen_e_acsl_freeable_5,(char *)"Assertion", + (char *)"main",(char *)"!\\freeable(p)",20); + } + /*@ assert ¬\freeable((char *)array); */ + { + int __gen_e_acsl_freeable_6; + __gen_e_acsl_freeable_6 = __e_acsl_freeable((void *)(array)); + __e_acsl_assert(! __gen_e_acsl_freeable_6,(char *)"Assertion", + (char *)"main",(char *)"!\\freeable((char *)array)",23); + } + /*@ assert ¬\freeable(&array[5]); */ + { + int __gen_e_acsl_freeable_7; + __gen_e_acsl_freeable_7 = __e_acsl_freeable((void *)(& array[5])); + __e_acsl_assert(! __gen_e_acsl_freeable_7,(char *)"Assertion", + (char *)"main",(char *)"!\\freeable(&array[5])",24); + } + __retres = 0; + __e_acsl_delete_block((void *)(array)); + __e_acsl_delete_block((void *)(& p)); + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/gen_goto.c b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_goto.c new file mode 100644 index 0000000000000000000000000000000000000000..3e168764507dd82f191a9cbeed88f6d438463a7a --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_goto.c @@ -0,0 +1,43 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +char a; +void __e_acsl_globals_init(void) +{ + static char __e_acsl_already_run = 0; + if (! __e_acsl_already_run) { + __e_acsl_already_run = 1; + __e_acsl_store_block((void *)(& a),(size_t)1); + __e_acsl_full_init((void *)(& a)); + } + return; +} + +int main(void) +{ + int __retres; + char *b; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + __e_acsl_globals_init(); + __e_acsl_store_block((void *)(& b),(size_t)8); + goto _LOR; + _LOR: { + __e_acsl_full_init((void *)(& b)); + b = & a; + } + if (a) goto _LOR; + /*@ assert \initialized(b); */ + { + int __gen_e_acsl_initialized; + __gen_e_acsl_initialized = __e_acsl_initialized((void *)b,sizeof(char)); + __e_acsl_assert(__gen_e_acsl_initialized,(char *)"Assertion", + (char *)"main",(char *)"\\initialized(b)",15); + } + __retres = 0; + __e_acsl_delete_block((void *)(& a)); + __e_acsl_delete_block((void *)(& b)); + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/gen_hidden_malloc.c b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_hidden_malloc.c new file mode 100644 index 0000000000000000000000000000000000000000..8fa1b3c59f46195dd83f0d4c9cc6d343b32cb12a --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_hidden_malloc.c @@ -0,0 +1,38 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +char *__gen_e_acsl_literal_string; +/*@ assigns \result, *((char *)x_1 + (0 ..)); + assigns \result \from *(x_0 + (0 ..)), *((char *)x_1 + (0 ..)); + assigns *((char *)x_1 + (0 ..)) + \from *(x_0 + (0 ..)), *((char *)x_1 + (0 ..)); + */ +extern int ( /* missing proto */ realpath)(char const *x_0, void *x_1); + +void __e_acsl_globals_init(void) +{ + static char __e_acsl_already_run = 0; + if (! __e_acsl_already_run) { + __e_acsl_already_run = 1; + __gen_e_acsl_literal_string = "."; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string,sizeof(".")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string); + } + return; +} + +int main(int argc, char const **argv) +{ + int __retres; + int tmp; + __e_acsl_memory_init(& argc,(char ***)(& argv),(size_t)8); + __e_acsl_globals_init(); + tmp = realpath(__gen_e_acsl_literal_string,(void *)0); + char *cwd = (char *)tmp; + __retres = 0; + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/gen_init.c b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_init.c new file mode 100644 index 0000000000000000000000000000000000000000..12ab5490df63ada25ceb6168684072698c68c3b3 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_init.c @@ -0,0 +1,56 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +int a = 0; +int b; +void __e_acsl_globals_init(void) +{ + static char __e_acsl_already_run = 0; + if (! __e_acsl_already_run) { + __e_acsl_already_run = 1; + __e_acsl_store_block((void *)(& b),(size_t)4); + __e_acsl_full_init((void *)(& b)); + __e_acsl_store_block((void *)(& a),(size_t)4); + __e_acsl_full_init((void *)(& a)); + } + return; +} + +int main(void) +{ + int __retres; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + __e_acsl_globals_init(); + int *p = & a; + __e_acsl_store_block((void *)(& p),(size_t)8); + __e_acsl_full_init((void *)(& p)); + int *q = & b; + __e_acsl_store_block((void *)(& q),(size_t)8); + __e_acsl_full_init((void *)(& q)); + /*@ assert \initialized(&b); */ + __e_acsl_assert(1,(char *)"Assertion",(char *)"main", + (char *)"\\initialized(&b)",9); + /*@ assert \initialized(q); */ + { + int __gen_e_acsl_initialized; + __gen_e_acsl_initialized = __e_acsl_initialized((void *)q,sizeof(int)); + __e_acsl_assert(__gen_e_acsl_initialized,(char *)"Assertion", + (char *)"main",(char *)"\\initialized(q)",10); + } + /*@ assert \initialized(p); */ + { + int __gen_e_acsl_initialized_2; + __gen_e_acsl_initialized_2 = __e_acsl_initialized((void *)p,sizeof(int)); + __e_acsl_assert(__gen_e_acsl_initialized_2,(char *)"Assertion", + (char *)"main",(char *)"\\initialized(p)",11); + } + __retres = 0; + __e_acsl_delete_block((void *)(& b)); + __e_acsl_delete_block((void *)(& a)); + __e_acsl_delete_block((void *)(& q)); + __e_acsl_delete_block((void *)(& p)); + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/gen_init_function.c b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_init_function.c new file mode 100644 index 0000000000000000000000000000000000000000..0233781eddc1f5da18be1c0812a3727ad744420a --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_init_function.c @@ -0,0 +1,14 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +int main(void) +{ + int __retres; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + char *a = malloc((unsigned long)7); + __retres = 0; + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/gen_initialized.c b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_initialized.c new file mode 100644 index 0000000000000000000000000000000000000000..421fbafa4439701746401a554e04f43757905854 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_initialized.c @@ -0,0 +1,365 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +int A = 0; +int B; +void __e_acsl_globals_init(void) +{ + static char __e_acsl_already_run = 0; + if (! __e_acsl_already_run) { + __e_acsl_already_run = 1; + __e_acsl_store_block((void *)(& B),(size_t)4); + __e_acsl_full_init((void *)(& B)); + __e_acsl_store_block((void *)(& A),(size_t)4); + __e_acsl_full_init((void *)(& A)); + } + return; +} + +int main(void) +{ + int __retres; + int b; + long *r; + long d[2]; + int dup[2]; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + __e_acsl_globals_init(); + __e_acsl_store_block((void *)(d),(size_t)16); + __e_acsl_store_block((void *)(& r),(size_t)8); + __e_acsl_store_block((void *)(& b),(size_t)4); + int *p = & A; + __e_acsl_store_block((void *)(& p),(size_t)8); + __e_acsl_full_init((void *)(& p)); + int *q = & B; + __e_acsl_store_block((void *)(& q),(size_t)8); + __e_acsl_full_init((void *)(& q)); + /*@ assert \initialized(&A); */ + __e_acsl_assert(1,(char *)"Assertion",(char *)"main", + (char *)"\\initialized(&A)",16); + /*@ assert \initialized(&B); */ + __e_acsl_assert(1,(char *)"Assertion",(char *)"main", + (char *)"\\initialized(&B)",17); + /*@ assert \initialized(p); */ + { + int __gen_e_acsl_initialized; + __gen_e_acsl_initialized = __e_acsl_initialized((void *)p,sizeof(int)); + __e_acsl_assert(__gen_e_acsl_initialized,(char *)"Assertion", + (char *)"main",(char *)"\\initialized(p)",18); + } + /*@ assert \initialized(q); */ + { + int __gen_e_acsl_initialized_2; + __gen_e_acsl_initialized_2 = __e_acsl_initialized((void *)q,sizeof(int)); + __e_acsl_assert(__gen_e_acsl_initialized_2,(char *)"Assertion", + (char *)"main",(char *)"\\initialized(q)",19); + } + int a = 0; + __e_acsl_store_block((void *)(& a),(size_t)4); + __e_acsl_full_init((void *)(& a)); + long c[2] = {(long)1, (long)1}; + __e_acsl_store_block((void *)(c),(size_t)16); + __e_acsl_full_init((void *)(& c)); + __e_acsl_full_init((void *)(& p)); + p = & a; + __e_acsl_full_init((void *)(& q)); + q = & b; + /*@ assert \initialized(&a); */ + { + int __gen_e_acsl_initialized_3; + __gen_e_acsl_initialized_3 = __e_acsl_initialized((void *)(& a), + sizeof(int)); + __e_acsl_assert(__gen_e_acsl_initialized_3,(char *)"Assertion", + (char *)"main",(char *)"\\initialized(&a)",30); + } + /*@ assert ¬\initialized(&b); */ + { + int __gen_e_acsl_initialized_4; + __gen_e_acsl_initialized_4 = __e_acsl_initialized((void *)(& b), + sizeof(int)); + __e_acsl_assert(! __gen_e_acsl_initialized_4,(char *)"Assertion", + (char *)"main",(char *)"!\\initialized(&b)",31); + } + /*@ assert \initialized(p); */ + { + int __gen_e_acsl_initialized_5; + __gen_e_acsl_initialized_5 = __e_acsl_initialized((void *)p,sizeof(int)); + __e_acsl_assert(__gen_e_acsl_initialized_5,(char *)"Assertion", + (char *)"main",(char *)"\\initialized(p)",32); + } + /*@ assert ¬\initialized(q); */ + { + int __gen_e_acsl_initialized_6; + __gen_e_acsl_initialized_6 = __e_acsl_initialized((void *)q,sizeof(int)); + __e_acsl_assert(! __gen_e_acsl_initialized_6,(char *)"Assertion", + (char *)"main",(char *)"!\\initialized(q)",33); + } + /*@ assert \initialized(&c); */ + { + int __gen_e_acsl_initialized_7; + __gen_e_acsl_initialized_7 = __e_acsl_initialized((void *)(& c), + sizeof(long [2])); + __e_acsl_assert(__gen_e_acsl_initialized_7,(char *)"Assertion", + (char *)"main",(char *)"\\initialized(&c)",34); + } + /*@ assert ¬\initialized(&d); */ + { + int __gen_e_acsl_initialized_8; + __gen_e_acsl_initialized_8 = __e_acsl_initialized((void *)(& d), + sizeof(long [2])); + __e_acsl_assert(! __gen_e_acsl_initialized_8,(char *)"Assertion", + (char *)"main",(char *)"!\\initialized(&d)",35); + } + __e_acsl_full_init((void *)(& b)); + b = 0; + /*@ assert \initialized(q); */ + { + int __gen_e_acsl_initialized_9; + __gen_e_acsl_initialized_9 = __e_acsl_initialized((void *)q,sizeof(int)); + __e_acsl_assert(__gen_e_acsl_initialized_9,(char *)"Assertion", + (char *)"main",(char *)"\\initialized(q)",39); + } + /*@ assert \initialized(&b); */ + { + int __gen_e_acsl_initialized_10; + __gen_e_acsl_initialized_10 = __e_acsl_initialized((void *)(& b), + sizeof(int)); + __e_acsl_assert(__gen_e_acsl_initialized_10,(char *)"Assertion", + (char *)"main",(char *)"\\initialized(&b)",40); + } + __e_acsl_full_init((void *)(& r)); + r = d; + /*@ assert ¬\initialized((long *)d); */ + { + int __gen_e_acsl_initialized_11; + __gen_e_acsl_initialized_11 = __e_acsl_initialized((void *)(d), + sizeof(long)); + __e_acsl_assert(! __gen_e_acsl_initialized_11,(char *)"Assertion", + (char *)"main",(char *)"!\\initialized((long *)d)",43); + } + /*@ assert ¬\initialized(&d[1]); */ + { + int __gen_e_acsl_initialized_12; + __gen_e_acsl_initialized_12 = __e_acsl_initialized((void *)(& d[1]), + sizeof(long)); + __e_acsl_assert(! __gen_e_acsl_initialized_12,(char *)"Assertion", + (char *)"main",(char *)"!\\initialized(&d[1])",44); + } + /*@ assert ¬\initialized(&d); */ + { + int __gen_e_acsl_initialized_13; + __gen_e_acsl_initialized_13 = __e_acsl_initialized((void *)(& d), + sizeof(long [2])); + __e_acsl_assert(! __gen_e_acsl_initialized_13,(char *)"Assertion", + (char *)"main",(char *)"!\\initialized(&d)",45); + } + /*@ assert ¬\initialized(r); */ + { + int __gen_e_acsl_initialized_14; + __gen_e_acsl_initialized_14 = __e_acsl_initialized((void *)r, + sizeof(long)); + __e_acsl_assert(! __gen_e_acsl_initialized_14,(char *)"Assertion", + (char *)"main",(char *)"!\\initialized(r)",46); + } + /*@ assert ¬\initialized(r + 1); */ + { + int __gen_e_acsl_initialized_15; + __gen_e_acsl_initialized_15 = __e_acsl_initialized((void *)(r + 1), + sizeof(long)); + __e_acsl_assert(! __gen_e_acsl_initialized_15,(char *)"Assertion", + (char *)"main",(char *)"!\\initialized(r + 1)",47); + } + __e_acsl_initialize((void *)(d),sizeof(long)); + d[0] = (long)1; + /*@ assert \initialized((long *)d); */ + { + int __gen_e_acsl_initialized_16; + __gen_e_acsl_initialized_16 = __e_acsl_initialized((void *)(d), + sizeof(long)); + __e_acsl_assert(__gen_e_acsl_initialized_16,(char *)"Assertion", + (char *)"main",(char *)"\\initialized((long *)d)",50); + } + /*@ assert ¬\initialized(&d[1]); */ + { + int __gen_e_acsl_initialized_17; + __gen_e_acsl_initialized_17 = __e_acsl_initialized((void *)(& d[1]), + sizeof(long)); + __e_acsl_assert(! __gen_e_acsl_initialized_17,(char *)"Assertion", + (char *)"main",(char *)"!\\initialized(&d[1])",51); + } + /*@ assert ¬\initialized(&d); */ + { + int __gen_e_acsl_initialized_18; + __gen_e_acsl_initialized_18 = __e_acsl_initialized((void *)(& d), + sizeof(long [2])); + __e_acsl_assert(! __gen_e_acsl_initialized_18,(char *)"Assertion", + (char *)"main",(char *)"!\\initialized(&d)",52); + } + /*@ assert \initialized(r); */ + { + int __gen_e_acsl_initialized_19; + __gen_e_acsl_initialized_19 = __e_acsl_initialized((void *)r, + sizeof(long)); + __e_acsl_assert(__gen_e_acsl_initialized_19,(char *)"Assertion", + (char *)"main",(char *)"\\initialized(r)",53); + } + /*@ assert ¬\initialized(r + 1); */ + { + int __gen_e_acsl_initialized_20; + __gen_e_acsl_initialized_20 = __e_acsl_initialized((void *)(r + 1), + sizeof(long)); + __e_acsl_assert(! __gen_e_acsl_initialized_20,(char *)"Assertion", + (char *)"main",(char *)"!\\initialized(r + 1)",54); + } + __e_acsl_initialize((void *)(& d[1]),sizeof(long)); + d[1] = (long)1; + /*@ assert \initialized((long *)d); */ + { + int __gen_e_acsl_initialized_21; + __gen_e_acsl_initialized_21 = __e_acsl_initialized((void *)(d), + sizeof(long)); + __e_acsl_assert(__gen_e_acsl_initialized_21,(char *)"Assertion", + (char *)"main",(char *)"\\initialized((long *)d)",57); + } + /*@ assert \initialized(&d[1]); */ + { + int __gen_e_acsl_initialized_22; + __gen_e_acsl_initialized_22 = __e_acsl_initialized((void *)(& d[1]), + sizeof(long)); + __e_acsl_assert(__gen_e_acsl_initialized_22,(char *)"Assertion", + (char *)"main",(char *)"\\initialized(&d[1])",58); + } + /*@ assert \initialized(&d); */ + { + int __gen_e_acsl_initialized_23; + __gen_e_acsl_initialized_23 = __e_acsl_initialized((void *)(& d), + sizeof(long [2])); + __e_acsl_assert(__gen_e_acsl_initialized_23,(char *)"Assertion", + (char *)"main",(char *)"\\initialized(&d)",59); + } + /*@ assert \initialized(r); */ + { + int __gen_e_acsl_initialized_24; + __gen_e_acsl_initialized_24 = __e_acsl_initialized((void *)r, + sizeof(long)); + __e_acsl_assert(__gen_e_acsl_initialized_24,(char *)"Assertion", + (char *)"main",(char *)"\\initialized(r)",60); + } + /*@ assert \initialized(r + 1); */ + { + int __gen_e_acsl_initialized_25; + __gen_e_acsl_initialized_25 = __e_acsl_initialized((void *)(r + 1), + sizeof(long)); + __e_acsl_assert(__gen_e_acsl_initialized_25,(char *)"Assertion", + (char *)"main",(char *)"\\initialized(r + 1)",61); + } + __e_acsl_full_init((void *)(& p)); + p = (int *)malloc(sizeof(int *)); + /*@ assert ¬\initialized(p); */ + { + int __gen_e_acsl_initialized_26; + __gen_e_acsl_initialized_26 = __e_acsl_initialized((void *)p,sizeof(int)); + __e_acsl_assert(! __gen_e_acsl_initialized_26,(char *)"Assertion", + (char *)"main",(char *)"!\\initialized(p)",65); + } + __e_acsl_full_init((void *)(& q)); + q = (int *)calloc((unsigned long)1,sizeof(int)); + /*@ assert \initialized(q); */ + { + int __gen_e_acsl_initialized_27; + __gen_e_acsl_initialized_27 = __e_acsl_initialized((void *)q,sizeof(int)); + __e_acsl_assert(__gen_e_acsl_initialized_27,(char *)"Assertion", + (char *)"main",(char *)"\\initialized(q)",69); + } + __e_acsl_full_init((void *)(& q)); + q = (int *)realloc((void *)q,(unsigned long)2 * sizeof(int)); + /*@ assert \initialized(q); */ + { + int __gen_e_acsl_initialized_28; + __gen_e_acsl_initialized_28 = __e_acsl_initialized((void *)q,sizeof(int)); + __e_acsl_assert(__gen_e_acsl_initialized_28,(char *)"Assertion", + (char *)"main",(char *)"\\initialized(q)",74); + } + __e_acsl_full_init((void *)(& q)); + q ++; + /*@ assert ¬\initialized(q); */ + { + int __gen_e_acsl_initialized_29; + __gen_e_acsl_initialized_29 = __e_acsl_initialized((void *)q,sizeof(int)); + __e_acsl_assert(! __gen_e_acsl_initialized_29,(char *)"Assertion", + (char *)"main",(char *)"!\\initialized(q)",76); + } + __e_acsl_full_init((void *)(& q)); + q --; + free((void *)p); + free((void *)q); + /*@ assert ¬\initialized(p); */ + { + int __gen_e_acsl_initialized_30; + /*@ assert Eva: dangling_pointer: ¬\dangling(&p); */ + __gen_e_acsl_initialized_30 = __e_acsl_initialized((void *)p,sizeof(int)); + __e_acsl_assert(! __gen_e_acsl_initialized_30,(char *)"Assertion", + (char *)"main",(char *)"!\\initialized(p)",84); + } + /*@ assert ¬\initialized(q); */ + { + int __gen_e_acsl_initialized_31; + __gen_e_acsl_initialized_31 = __e_acsl_initialized((void *)q,sizeof(int)); + __e_acsl_assert(! __gen_e_acsl_initialized_31,(char *)"Assertion", + (char *)"main",(char *)"!\\initialized(q)",85); + } + __e_acsl_full_init((void *)(& q)); + q = (int *)(& q - 1024 * 5); + __e_acsl_full_init((void *)(& q)); + q = (int *)128; + /*@ assert ¬\initialized(q); */ + { + int __gen_e_acsl_initialized_32; + __gen_e_acsl_initialized_32 = __e_acsl_initialized((void *)q,sizeof(int)); + __e_acsl_assert(! __gen_e_acsl_initialized_32,(char *)"Assertion", + (char *)"main",(char *)"!\\initialized(q)",93); + } + __e_acsl_full_init((void *)(& p)); + p = (int *)0; + /*@ assert ¬\initialized(p); */ + { + int __gen_e_acsl_initialized_33; + __gen_e_acsl_initialized_33 = __e_acsl_initialized((void *)p,sizeof(int)); + __e_acsl_assert(! __gen_e_acsl_initialized_33,(char *)"Assertion", + (char *)"main",(char *)"!\\initialized(p)",96); + } + int size = 100; + char *partsc = malloc((unsigned long)size * sizeof(char)); + char *partsi = malloc((unsigned long)size * sizeof(int)); + { + int i = 0; + while (i < size) { + if (i % 2 != 0) *(partsc + i) = (char)'0'; + else *(partsi + i) = (char)0; + i ++; + } + } + { + int i_0 = 0; + while (i_0 < size) { + if (i_0 % 2 != 0) ; + i_0 ++; + } + } + dup[0] = 1; + dup[0] = 1; + __retres = 0; + __e_acsl_delete_block((void *)(& B)); + __e_acsl_delete_block((void *)(& A)); + __e_acsl_delete_block((void *)(d)); + __e_acsl_delete_block((void *)(c)); + __e_acsl_delete_block((void *)(& r)); + __e_acsl_delete_block((void *)(& b)); + __e_acsl_delete_block((void *)(& a)); + __e_acsl_delete_block((void *)(& q)); + __e_acsl_delete_block((void *)(& p)); + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/gen_literal_string.c b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_literal_string.c new file mode 100644 index 0000000000000000000000000000000000000000..beec3bd8adf2c55638b4d6cebe6d7a9d8036ad24 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_literal_string.c @@ -0,0 +1,149 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +char *__gen_e_acsl_literal_string_6; +char *__gen_e_acsl_literal_string_5; +char *__gen_e_acsl_literal_string; +char *__gen_e_acsl_literal_string_4; +char *__gen_e_acsl_literal_string_3; +char *__gen_e_acsl_literal_string_2; +int main(void); + +char *T = (char *)"bar"; +int G = 0; +void f(void) +{ + /*@ assert *(T + G) ≡ 'b'; */ + { + int __gen_e_acsl_valid_read; + __gen_e_acsl_valid_read = __e_acsl_valid_read((void *)(T + G), + sizeof(char),(void *)T, + (void *)(& T)); + __e_acsl_assert(__gen_e_acsl_valid_read,(char *)"RTE",(char *)"f", + (char *)"mem_access: \\valid_read(T + G)",11); + __e_acsl_assert((int)*(T + G) == 98,(char *)"Assertion",(char *)"f", + (char *)"*(T + G) == \'b\'",11); + } + G ++; + return; +} + +char *S = (char *)"foo"; +char *S2 = (char *)"foo2"; +int IDX = 1; +int G2 = 2; +char const *s_str = "the cat"; +char const *l_str = "the dog and the cat"; +char *U = (char *)"baz"; +void __e_acsl_globals_init(void) +{ + static char __e_acsl_already_run = 0; + if (! __e_acsl_already_run) { + __e_acsl_already_run = 1; + __gen_e_acsl_literal_string_6 = "the dog and the cat"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_6, + sizeof("the dog and the cat")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_6); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_6); + __gen_e_acsl_literal_string_5 = "the cat"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_5, + sizeof("the cat")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_5); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_5); + __gen_e_acsl_literal_string = "ss"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string,sizeof("ss")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string); + __gen_e_acsl_literal_string_4 = "foo2"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_4, + sizeof("foo2")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_4); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_4); + __gen_e_acsl_literal_string_3 = "foo"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_3,sizeof("foo")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_3); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_3); + __gen_e_acsl_literal_string_2 = "bar"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_2,sizeof("bar")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_2); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_2); + __e_acsl_store_block((void *)(& l_str),(size_t)8); + __e_acsl_full_init((void *)(& l_str)); + __e_acsl_store_block((void *)(& s_str),(size_t)8); + __e_acsl_full_init((void *)(& s_str)); + __e_acsl_store_block((void *)(& S2),(size_t)8); + __e_acsl_full_init((void *)(& S2)); + __e_acsl_store_block((void *)(& S),(size_t)8); + __e_acsl_full_init((void *)(& S)); + __e_acsl_store_block((void *)(& T),(size_t)8); + __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 *SS = (char *)__gen_e_acsl_literal_string; + __e_acsl_store_block((void *)(& SS),(size_t)8); + __e_acsl_full_init((void *)(& SS)); + /*@ assert *(S + G2) ≡ 'o'; */ + { + int __gen_e_acsl_valid_read; + __gen_e_acsl_valid_read = __e_acsl_valid_read((void *)(S + G2), + sizeof(char),(void *)S, + (void *)(& S)); + __e_acsl_assert(__gen_e_acsl_valid_read,(char *)"RTE",(char *)"main", + (char *)"mem_access: \\valid_read(S + G2)",25); + __e_acsl_assert((int)*(S + G2) == 111,(char *)"Assertion",(char *)"main", + (char *)"*(S + G2) == \'o\'",25); + } + /*@ assert \initialized(S); */ + { + int __gen_e_acsl_initialized; + __gen_e_acsl_initialized = __e_acsl_initialized((void *)S,sizeof(char)); + __e_acsl_assert(__gen_e_acsl_initialized,(char *)"Assertion", + (char *)"main",(char *)"\\initialized(S)",26); + } + /*@ assert \valid_read(S2); */ + { + int __gen_e_acsl_valid_read_2; + __gen_e_acsl_valid_read_2 = __e_acsl_valid_read((void *)S2,sizeof(char), + (void *)S2, + (void *)(& S2)); + __e_acsl_assert(__gen_e_acsl_valid_read_2,(char *)"Assertion", + (char *)"main",(char *)"\\valid_read(S2)",27); + } + /*@ assert ¬\valid(SS); */ + { + int __gen_e_acsl_initialized_2; + int __gen_e_acsl_and; + __gen_e_acsl_initialized_2 = __e_acsl_initialized((void *)(& SS), + sizeof(char *)); + if (__gen_e_acsl_initialized_2) { + int __gen_e_acsl_valid; + __gen_e_acsl_valid = __e_acsl_valid((void *)SS,sizeof(char),(void *)SS, + (void *)(& SS)); + __gen_e_acsl_and = __gen_e_acsl_valid; + } + else __gen_e_acsl_and = 0; + __e_acsl_assert(! __gen_e_acsl_and,(char *)"Assertion",(char *)"main", + (char *)"!\\valid(SS)",28); + } + f(); + s_str ++; + l_str ++; + __retres = 0; + __e_acsl_delete_block((void *)(& l_str)); + __e_acsl_delete_block((void *)(& s_str)); + __e_acsl_delete_block((void *)(& S2)); + __e_acsl_delete_block((void *)(& S)); + __e_acsl_delete_block((void *)(& T)); + __e_acsl_delete_block((void *)(& SS)); + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/gen_local_goto.c b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_local_goto.c new file mode 100644 index 0000000000000000000000000000000000000000..18ceafe4d81e54118ac386239051e8e12a7b9969 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_local_goto.c @@ -0,0 +1,89 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +char *__gen_e_acsl_literal_string; +char *__gen_e_acsl_literal_string_3; +char *__gen_e_acsl_literal_string_2; +char *__gen_e_acsl_literal_string_4; +void __e_acsl_globals_init(void) +{ + static char __e_acsl_already_run = 0; + if (! __e_acsl_already_run) { + __e_acsl_already_run = 1; + __gen_e_acsl_literal_string = "t is %d, going to %s\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string, + sizeof("t is %d, going to %s\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string); + __gen_e_acsl_literal_string_3 = "UP"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_3,sizeof("UP")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_3); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_3); + __gen_e_acsl_literal_string_2 = "RET"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_2,sizeof("RET")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_2); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_2); + __gen_e_acsl_literal_string_4 = "AGAIN"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_4, + sizeof("AGAIN")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_4); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_4); + } + return; +} + +int main(int argc, char const **argv) +{ + int __retres; + __e_acsl_memory_init(& argc,(char ***)(& argv),(size_t)8); + __e_acsl_globals_init(); + int t = 0; + UP: ; + if (t == 2) { + printf(__gen_e_acsl_literal_string,t,__gen_e_acsl_literal_string_2); + goto RET; + } + AGAIN: + { + int a; + __e_acsl_store_block((void *)(& a),(size_t)4); + __e_acsl_full_init((void *)(& a)); + a = 1; + /*@ assert \valid(&a); */ + { + int __gen_e_acsl_valid; + __gen_e_acsl_valid = __e_acsl_valid((void *)(& a),sizeof(int), + (void *)(& a),(void *)0); + __e_acsl_assert(__gen_e_acsl_valid,(char *)"Assertion",(char *)"main", + (char *)"\\valid(&a)",25); + } + if (t == 2) { + printf(__gen_e_acsl_literal_string,t,__gen_e_acsl_literal_string_3); + __e_acsl_delete_block((void *)(& a)); + goto UP; + } + else t ++; + int b = 15; + __e_acsl_store_block((void *)(& b),(size_t)4); + __e_acsl_full_init((void *)(& b)); + /*@ assert \valid(&b); */ + { + int __gen_e_acsl_valid_2; + __gen_e_acsl_valid_2 = __e_acsl_valid((void *)(& b),sizeof(int), + (void *)(& b),(void *)0); + __e_acsl_assert(__gen_e_acsl_valid_2,(char *)"Assertion", + (char *)"main",(char *)"\\valid(&b)",36); + } + printf(__gen_e_acsl_literal_string,t,__gen_e_acsl_literal_string_4); + __e_acsl_delete_block((void *)(& a)); + __e_acsl_delete_block((void *)(& b)); + goto AGAIN; + __e_acsl_delete_block((void *)(& b)); + __e_acsl_delete_block((void *)(& a)); + } + RET: __retres = 0; + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/gen_local_init.c b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_local_init.c new file mode 100644 index 0000000000000000000000000000000000000000..2556be7d0248ecfe121130a372fa8be4fa7cbe03 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_local_init.c @@ -0,0 +1,38 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +int X = 0; +int *p = & X; +int f(void) +{ + int x = *p; + return x; +} + +void __e_acsl_globals_init(void) +{ + static char __e_acsl_already_run = 0; + if (! __e_acsl_already_run) { + __e_acsl_already_run = 1; + __e_acsl_store_block((void *)(& p),(size_t)8); + __e_acsl_full_init((void *)(& p)); + __e_acsl_store_block((void *)(& X),(size_t)4); + __e_acsl_full_init((void *)(& X)); + } + return; +} + +int main(void) +{ + int __retres; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + __e_acsl_globals_init(); + f(); + __retres = 0; + __e_acsl_delete_block((void *)(& p)); + __e_acsl_delete_block((void *)(& X)); + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/gen_local_var.c b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_local_var.c new file mode 100644 index 0000000000000000000000000000000000000000..567bf6af14098fa88e2cddad5c728118b6a34066 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_local_var.c @@ -0,0 +1,57 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +struct list { + int element ; + struct list *next ; +}; +struct list *add(struct list *l, int i) +{ + struct list *new; + __e_acsl_store_block((void *)(& new),(size_t)8); + __e_acsl_store_block((void *)(& l),(size_t)8); + __e_acsl_full_init((void *)(& new)); + new = (struct list *)malloc(sizeof(struct list)); + /*@ assert \valid(new); */ + { + int __gen_e_acsl_initialized; + int __gen_e_acsl_and; + __gen_e_acsl_initialized = __e_acsl_initialized((void *)(& new), + sizeof(struct list *)); + if (__gen_e_acsl_initialized) { + int __gen_e_acsl_valid; + __gen_e_acsl_valid = __e_acsl_valid((void *)new,sizeof(struct list), + (void *)new,(void *)(& new)); + __gen_e_acsl_and = __gen_e_acsl_valid; + } + else __gen_e_acsl_and = 0; + __e_acsl_assert(__gen_e_acsl_and,(char *)"Assertion",(char *)"add", + (char *)"\\valid(new)",15); + } + __e_acsl_initialize((void *)(& new->element),sizeof(int)); + new->element = i; + __e_acsl_initialize((void *)(& new->next),sizeof(struct list *)); + new->next = l; + __e_acsl_delete_block((void *)(& l)); + __e_acsl_delete_block((void *)(& new)); + return new; +} + +int main(void) +{ + int __retres; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + struct list *l = (struct list *)0; + __e_acsl_store_block((void *)(& l),(size_t)8); + __e_acsl_full_init((void *)(& l)); + __e_acsl_full_init((void *)(& l)); + l = add(l,4); + __e_acsl_full_init((void *)(& l)); + l = add(l,7); + __retres = 0; + __e_acsl_delete_block((void *)(& l)); + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/gen_mainargs.c b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_mainargs.c new file mode 100644 index 0000000000000000000000000000000000000000..e444d49960dae56dcaaf5e007d4007281ce98df3 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_mainargs.c @@ -0,0 +1,199 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +#include "string.h" +extern int __e_acsl_sound_verdict; + +/*@ requires \valid(&argc); + requires \valid(&argv); */ +int main(int argc, char **argv); + +int __gen_e_acsl_main(int argc, char **argv) +{ + int __retres; + int i; + /*@ assert ∀ int k; 0 ≤ k < argc ⇒ \valid(argv + k); */ + { + int __gen_e_acsl_forall; + int __gen_e_acsl_k; + __e_acsl_store_block((void *)(& argv),(size_t)8); + __gen_e_acsl_forall = 1; + __gen_e_acsl_k = 0; + while (1) { + if (__gen_e_acsl_k < argc) ; else break; + { + int __gen_e_acsl_valid; + __gen_e_acsl_valid = __e_acsl_valid((void *)(argv + __gen_e_acsl_k), + sizeof(char *),(void *)argv, + (void *)(& argv)); + if (__gen_e_acsl_valid) ; + else { + __gen_e_acsl_forall = 0; + goto e_acsl_end_loop1; + } + } + __gen_e_acsl_k ++; + } + e_acsl_end_loop1: ; + __e_acsl_assert(__gen_e_acsl_forall,(char *)"Assertion",(char *)"main", + (char *)"\\forall int k; 0 <= k < argc ==> \\valid(argv + k)", + 12); + } + /*@ assert \block_length(argv) ≡ (argc + 1) * sizeof(char *); */ + { + unsigned long __gen_e_acsl_block_length; + __e_acsl_mpz_t __gen_e_acsl_block_length_2; + __e_acsl_mpz_t __gen_e_acsl_; + int __gen_e_acsl_eq; + __gen_e_acsl_block_length = __e_acsl_block_length((void *)argv); + __gmpz_init_set_ui(__gen_e_acsl_block_length_2,__gen_e_acsl_block_length); + __gmpz_init_set_si(__gen_e_acsl_,(argc + 1L) * 8); + __gen_e_acsl_eq = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_block_length_2), + (__e_acsl_mpz_struct const *)(__gen_e_acsl_)); + __e_acsl_assert(__gen_e_acsl_eq == 0,(char *)"Assertion",(char *)"main", + (char *)"\\block_length(argv) == (argc + 1) * sizeof(char *)", + 13); + __gmpz_clear(__gen_e_acsl_block_length_2); + __gmpz_clear(__gen_e_acsl_); + } + /*@ assert *(argv + argc) ≡ \null; */ + { + int __gen_e_acsl_valid_read; + __gen_e_acsl_valid_read = __e_acsl_valid_read((void *)(argv + argc), + sizeof(char *), + (void *)argv, + (void *)(& argv)); + __e_acsl_assert(__gen_e_acsl_valid_read,(char *)"RTE",(char *)"main", + (char *)"mem_access: \\valid_read(argv + argc)",15); + /*@ assert Eva: mem_access: \valid_read(argv + argc); */ + __e_acsl_assert(*(argv + argc) == (char *)0,(char *)"Assertion", + (char *)"main",(char *)"*(argv + argc) == \\null",15); + } + /*@ assert ¬\valid(*(argv + argc)); */ + { + int __gen_e_acsl_initialized; + int __gen_e_acsl_and; + __gen_e_acsl_initialized = __e_acsl_initialized((void *)(argv + argc), + sizeof(char *)); + if (__gen_e_acsl_initialized) { + int __gen_e_acsl_valid_read_2; + int __gen_e_acsl_valid_2; + __gen_e_acsl_valid_read_2 = __e_acsl_valid_read((void *)(argv + argc), + sizeof(char *), + (void *)argv, + (void *)(& argv)); + __e_acsl_assert(__gen_e_acsl_valid_read_2,(char *)"RTE",(char *)"main", + (char *)"mem_access: \\valid_read(argv + argc)",16); + /*@ assert Eva: mem_access: \valid_read(argv + argc); */ + __gen_e_acsl_valid_2 = __e_acsl_valid((void *)*(argv + argc), + sizeof(char), + (void *)*(argv + argc), + (void *)(argv + argc)); + __gen_e_acsl_and = __gen_e_acsl_valid_2; + } + else __gen_e_acsl_and = 0; + __e_acsl_assert(! __gen_e_acsl_and,(char *)"Assertion",(char *)"main", + (char *)"!\\valid(*(argv + argc))",16); + } + i = 0; + while (i < argc) { + { + size_t tmp; + tmp = __gen_e_acsl_strlen((char const *)*(argv + i)); + int len = (int)tmp; + /*@ assert \valid(*(argv + i)); */ + { + int __gen_e_acsl_initialized_2; + int __gen_e_acsl_and_2; + __gen_e_acsl_initialized_2 = __e_acsl_initialized((void *)(argv + i), + sizeof(char *)); + if (__gen_e_acsl_initialized_2) { + int __gen_e_acsl_valid_read_3; + int __gen_e_acsl_valid_3; + __gen_e_acsl_valid_read_3 = __e_acsl_valid_read((void *)(argv + i), + sizeof(char *), + (void *)argv, + (void *)(& argv)); + __e_acsl_assert(__gen_e_acsl_valid_read_3,(char *)"RTE", + (char *)"main", + (char *)"mem_access: \\valid_read(argv + i)",19); + __gen_e_acsl_valid_3 = __e_acsl_valid((void *)*(argv + i), + sizeof(char), + (void *)*(argv + i), + (void *)(argv + i)); + __gen_e_acsl_and_2 = __gen_e_acsl_valid_3; + } + else __gen_e_acsl_and_2 = 0; + __e_acsl_assert(__gen_e_acsl_and_2,(char *)"Assertion", + (char *)"main",(char *)"\\valid(*(argv + i))",19); + } + /*@ assert ∀ int k; 0 ≤ k ≤ len ⇒ \valid(*(argv + i) + k); */ + { + int __gen_e_acsl_forall_2; + long __gen_e_acsl_k_2; + __gen_e_acsl_forall_2 = 1; + __gen_e_acsl_k_2 = 0; + while (1) { + if (__gen_e_acsl_k_2 <= (long)len) ; else break; + { + int __gen_e_acsl_valid_read_4; + int __gen_e_acsl_valid_4; + __gen_e_acsl_valid_read_4 = __e_acsl_valid_read((void *)( + argv + i), + sizeof(char *), + (void *)argv, + (void *)(& argv)); + __e_acsl_assert(__gen_e_acsl_valid_read_4,(char *)"RTE", + (char *)"main", + (char *)"mem_access: \\valid_read(argv + i)",20); + __gen_e_acsl_valid_4 = __e_acsl_valid((void *)(*(argv + i) + __gen_e_acsl_k_2), + sizeof(char), + (void *)*(argv + i), + (void *)(argv + i)); + if (__gen_e_acsl_valid_4) ; + else { + __gen_e_acsl_forall_2 = 0; + goto e_acsl_end_loop2; + } + } + __gen_e_acsl_k_2 ++; + } + e_acsl_end_loop2: ; + __e_acsl_assert(__gen_e_acsl_forall_2,(char *)"Assertion", + (char *)"main", + (char *)"\\forall int k; 0 <= k <= len ==> \\valid(*(argv + i) + k)", + 20); + } + } + i ++; + } + __retres = 0; + __e_acsl_delete_block((void *)(& argv)); + return __retres; +} + +/*@ requires \valid(&argc); + requires \valid(&argv); */ +int main(int argc, char **argv) +{ + int __retres; + __e_acsl_memory_init(& argc,& argv,(size_t)8); + { + int __gen_e_acsl_valid; + int __gen_e_acsl_valid_2; + __gen_e_acsl_valid = __e_acsl_valid((void *)(& argc),sizeof(int), + (void *)(& argc),(void *)0); + __e_acsl_assert(__gen_e_acsl_valid,(char *)"Precondition",(char *)"main", + (char *)"\\valid(&argc)",7); + __gen_e_acsl_valid_2 = __e_acsl_valid((void *)(& argv),sizeof(char **), + (void *)(& argv),(void *)0); + __e_acsl_assert(__gen_e_acsl_valid_2,(char *)"Precondition", + (char *)"main",(char *)"\\valid(&argv)",8); + } + __retres = __gen_e_acsl_main(argc,argv); + __e_acsl_delete_block((void *)(& argv)); + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/gen_memalign.c b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_memalign.c new file mode 100644 index 0000000000000000000000000000000000000000..c5c2d6a44fbea7812e73a0b96024fb4ebcf7f89d --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_memalign.c @@ -0,0 +1,141 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +int main(int argc, char const **argv) +{ + int __retres; + char *a; + __e_acsl_memory_init(& argc,(char ***)(& argv),(size_t)8); + __e_acsl_store_block((void *)(& a),(size_t)8); + char **memptr = malloc(sizeof(void *)); + __e_acsl_store_block((void *)(& memptr),(size_t)8); + __e_acsl_full_init((void *)(& memptr)); + int res2 = + posix_memalign((void **)memptr,(unsigned long)256,(unsigned long)15); + /*@ assert Eva: initialization: \initialized(memptr); */ + char *p = *memptr; + __e_acsl_store_block((void *)(& p),(size_t)8); + __e_acsl_full_init((void *)(& p)); + /*@ assert \valid(p); */ + { + int __gen_e_acsl_initialized; + int __gen_e_acsl_and; + __gen_e_acsl_initialized = __e_acsl_initialized((void *)(& p), + sizeof(char *)); + if (__gen_e_acsl_initialized) { + int __gen_e_acsl_valid; + __gen_e_acsl_valid = __e_acsl_valid((void *)p,sizeof(char),(void *)p, + (void *)(& p)); + __gen_e_acsl_and = __gen_e_acsl_valid; + } + else __gen_e_acsl_and = 0; + __e_acsl_assert(__gen_e_acsl_and,(char *)"Assertion",(char *)"main", + (char *)"\\valid(p)",15); + } + /*@ assert \block_length(p) ≡ 15; */ + { + unsigned long __gen_e_acsl_block_length; + __gen_e_acsl_block_length = __e_acsl_block_length((void *)p); + __e_acsl_assert(__gen_e_acsl_block_length == 15UL,(char *)"Assertion", + (char *)"main",(char *)"\\block_length(p) == 15",16); + } + /*@ assert \freeable(p); */ + { + int __gen_e_acsl_freeable; + __gen_e_acsl_freeable = __e_acsl_freeable((void *)p); + __e_acsl_assert(__gen_e_acsl_freeable,(char *)"Assertion",(char *)"main", + (char *)"\\freeable(p)",17); + } + free((void *)p); + /*@ assert ¬\valid(p); */ + { + int __gen_e_acsl_initialized_2; + int __gen_e_acsl_and_2; + __gen_e_acsl_initialized_2 = __e_acsl_initialized((void *)(& p), + sizeof(char *)); + if (__gen_e_acsl_initialized_2) { + int __gen_e_acsl_valid_2; + __gen_e_acsl_valid_2 = __e_acsl_valid((void *)p,sizeof(char),(void *)p, + (void *)(& p)); + __gen_e_acsl_and_2 = __gen_e_acsl_valid_2; + } + else __gen_e_acsl_and_2 = 0; + __e_acsl_assert(! __gen_e_acsl_and_2,(char *)"Assertion",(char *)"main", + (char *)"!\\valid(p)",19); + } + __e_acsl_full_init((void *)(& a)); + a = (char *)aligned_alloc((unsigned long)256,(unsigned long)12); + /*@ assert a ≡ \null; */ + __e_acsl_assert(a == (char *)0,(char *)"Assertion",(char *)"main", + (char *)"a == \\null",23); + __e_acsl_full_init((void *)(& a)); + a = (char *)aligned_alloc((unsigned long)255,(unsigned long)512); + /*@ assert a ≡ \null; */ + __e_acsl_assert(a == (char *)0,(char *)"Assertion",(char *)"main", + (char *)"a == \\null",26); + __e_acsl_full_init((void *)(& a)); + a = (char *)aligned_alloc((unsigned long)0,(unsigned long)512); + /*@ assert a ≡ \null; */ + __e_acsl_assert(a == (char *)0,(char *)"Assertion",(char *)"main", + (char *)"a == \\null",29); + __e_acsl_full_init((void *)(& a)); + a = (char *)aligned_alloc((unsigned long)256,(unsigned long)512); + /*@ assert a ≢ \null; */ + __e_acsl_assert(a != (char *)0,(char *)"Assertion",(char *)"main", + (char *)"a != \\null",32); + /*@ assert \valid(a); */ + { + int __gen_e_acsl_initialized_3; + int __gen_e_acsl_and_3; + __gen_e_acsl_initialized_3 = __e_acsl_initialized((void *)(& a), + sizeof(char *)); + if (__gen_e_acsl_initialized_3) { + int __gen_e_acsl_valid_3; + __gen_e_acsl_valid_3 = __e_acsl_valid((void *)a,sizeof(char),(void *)a, + (void *)(& a)); + __gen_e_acsl_and_3 = __gen_e_acsl_valid_3; + } + else __gen_e_acsl_and_3 = 0; + __e_acsl_assert(__gen_e_acsl_and_3,(char *)"Assertion",(char *)"main", + (char *)"\\valid(a)",33); + } + /*@ assert \block_length(a) ≡ 512; */ + { + unsigned long __gen_e_acsl_block_length_2; + __gen_e_acsl_block_length_2 = __e_acsl_block_length((void *)a); + __e_acsl_assert(__gen_e_acsl_block_length_2 == 512UL,(char *)"Assertion", + (char *)"main",(char *)"\\block_length(a) == 512",34); + } + /*@ assert \freeable(a); */ + { + int __gen_e_acsl_freeable_2; + __gen_e_acsl_freeable_2 = __e_acsl_freeable((void *)a); + __e_acsl_assert(__gen_e_acsl_freeable_2,(char *)"Assertion", + (char *)"main",(char *)"\\freeable(a)",35); + } + free((void *)a); + /*@ assert ¬\valid(a); */ + { + int __gen_e_acsl_initialized_4; + int __gen_e_acsl_and_4; + __gen_e_acsl_initialized_4 = __e_acsl_initialized((void *)(& a), + sizeof(char *)); + if (__gen_e_acsl_initialized_4) { + int __gen_e_acsl_valid_4; + __gen_e_acsl_valid_4 = __e_acsl_valid((void *)a,sizeof(char),(void *)a, + (void *)(& a)); + __gen_e_acsl_and_4 = __gen_e_acsl_valid_4; + } + else __gen_e_acsl_and_4 = 0; + __e_acsl_assert(! __gen_e_acsl_and_4,(char *)"Assertion",(char *)"main", + (char *)"!\\valid(a)",38); + } + __retres = 0; + __e_acsl_delete_block((void *)(& a)); + __e_acsl_delete_block((void *)(& p)); + __e_acsl_delete_block((void *)(& memptr)); + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/gen_memsize.c b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_memsize.c new file mode 100644 index 0000000000000000000000000000000000000000..87889137a8e49ae588b3b55d1cc7111622db74f5 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_memsize.c @@ -0,0 +1,84 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +int main(int argc, char **argv) +{ + int __retres; + __e_acsl_memory_init(& argc,& argv,(size_t)8); + char *a = malloc((unsigned long)7); + /*@ assert __e_acsl_heap_allocation_size ≡ 7; */ + __e_acsl_assert(__e_acsl_heap_allocation_size == 7UL,(char *)"Assertion", + (char *)"main", + (char *)"__e_acsl_heap_allocation_size == 7",14); + char *b = malloc((unsigned long)14); + /*@ assert __e_acsl_heap_allocation_size ≡ 21; */ + __e_acsl_assert(__e_acsl_heap_allocation_size == 21UL,(char *)"Assertion", + (char *)"main", + (char *)"__e_acsl_heap_allocation_size == 21",16); + free((void *)a); + /*@ assert __e_acsl_heap_allocation_size ≡ 14; */ + __e_acsl_assert(__e_acsl_heap_allocation_size == 14UL,(char *)"Assertion", + (char *)"main", + (char *)"__e_acsl_heap_allocation_size == 14",20); + a = (char *)0; + free((void *)a); + /*@ assert __e_acsl_heap_allocation_size ≡ 14; */ + __e_acsl_assert(__e_acsl_heap_allocation_size == 14UL,(char *)"Assertion", + (char *)"main", + (char *)"__e_acsl_heap_allocation_size == 14",25); + b = (char *)realloc((void *)b,(unsigned long)9); + /*@ assert __e_acsl_heap_allocation_size ≡ 9; */ + __e_acsl_assert(__e_acsl_heap_allocation_size == 9UL,(char *)"Assertion", + (char *)"main", + (char *)"__e_acsl_heap_allocation_size == 9",29); + b = (char *)realloc((void *)b,(unsigned long)18); + /*@ assert __e_acsl_heap_allocation_size ≡ 18; */ + __e_acsl_assert(__e_acsl_heap_allocation_size == 18UL,(char *)"Assertion", + (char *)"main", + (char *)"__e_acsl_heap_allocation_size == 18",33); + b = (char *)realloc((void *)b,(unsigned long)0); + b = (char *)0; + /*@ assert __e_acsl_heap_allocation_size ≡ 0; */ + __e_acsl_assert(__e_acsl_heap_allocation_size == 0UL,(char *)"Assertion", + (char *)"main", + (char *)"__e_acsl_heap_allocation_size == 0",38); + b = (char *)realloc((void *)b,(unsigned long)8); + /*@ assert __e_acsl_heap_allocation_size ≡ 8; */ + __e_acsl_assert(__e_acsl_heap_allocation_size == 8UL,(char *)"Assertion", + (char *)"main", + (char *)"__e_acsl_heap_allocation_size == 8",42); + b = (char *)realloc((void *)0,(unsigned long)8); + /*@ assert __e_acsl_heap_allocation_size ≡ 16; */ + __e_acsl_assert(__e_acsl_heap_allocation_size == 16UL,(char *)"Assertion", + (char *)"main", + (char *)"__e_acsl_heap_allocation_size == 16",46); + b = (char *)realloc((void *)0,18446744073709551615UL); + /*@ assert __e_acsl_heap_allocation_size ≡ 16; */ + __e_acsl_assert(__e_acsl_heap_allocation_size == 16UL,(char *)"Assertion", + (char *)"main", + (char *)"__e_acsl_heap_allocation_size == 16",50); + /*@ assert b ≡ (char *)((void *)0); */ + __e_acsl_assert(b == (char *)0,(char *)"Assertion",(char *)"main", + (char *)"b == (char *)((void *)0)",51); + b = (char *)calloc(18446744073709551615UL,18446744073709551615UL); + /*@ assert __e_acsl_heap_allocation_size ≡ 16; */ + __e_acsl_assert(__e_acsl_heap_allocation_size == 16UL,(char *)"Assertion", + (char *)"main", + (char *)"__e_acsl_heap_allocation_size == 16",55); + /*@ assert b ≡ (char *)((void *)0); */ + __e_acsl_assert(b == (char *)0,(char *)"Assertion",(char *)"main", + (char *)"b == (char *)((void *)0)",56); + b = (char *)malloc(18446744073709551615UL); + /*@ assert __e_acsl_heap_allocation_size ≡ 16; */ + __e_acsl_assert(__e_acsl_heap_allocation_size == 16UL,(char *)"Assertion", + (char *)"main", + (char *)"__e_acsl_heap_allocation_size == 16",60); + /*@ assert b ≡ (char *)((void *)0); */ + __e_acsl_assert(b == (char *)0,(char *)"Assertion",(char *)"main", + (char *)"b == (char *)((void *)0)",61); + __retres = 0; + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/gen_null.c b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_null.c new file mode 100644 index 0000000000000000000000000000000000000000..cc3c98c0c935784d4aaca40bbfa92d870f45f683 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_null.c @@ -0,0 +1,15 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +int main(void) +{ + int __retres; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + /*@ assert \null ≡ (void *)0; */ + __e_acsl_assert((void *)0 == (void *)0,(char *)"Assertion",(char *)"main", + (char *)"\\null == (void *)0",6); + __retres = 0; + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/gen_offset.c b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_offset.c new file mode 100644 index 0000000000000000000000000000000000000000..6902b7e3f3f8c168f3c92c8a480a5c9164af7fa4 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_offset.c @@ -0,0 +1,223 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +int A[4] = {1, 2, 3, 4}; +int *PA; +void __e_acsl_globals_init(void) +{ + static char __e_acsl_already_run = 0; + if (! __e_acsl_already_run) { + __e_acsl_already_run = 1; + __e_acsl_store_block((void *)(& PA),(size_t)8); + __e_acsl_full_init((void *)(& PA)); + __e_acsl_store_block((void *)(A),(size_t)16); + __e_acsl_full_init((void *)(& A)); + } + return; +} + +int main(void) +{ + int __retres; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + __e_acsl_globals_init(); + PA = (int *)(& A); + /*@ assert \offset((int *)A) ≡ 0; */ + { + unsigned long __gen_e_acsl_offset; + __gen_e_acsl_offset = __e_acsl_offset((void *)(A)); + __e_acsl_assert(__gen_e_acsl_offset == 0UL,(char *)"Assertion", + (char *)"main",(char *)"\\offset((int *)A) == 0",13); + } + /*@ assert \offset(&A[3]) ≡ 12; */ + { + unsigned long __gen_e_acsl_offset_2; + __gen_e_acsl_offset_2 = __e_acsl_offset((void *)(& A[3])); + __e_acsl_assert(__gen_e_acsl_offset_2 == 12UL,(char *)"Assertion", + (char *)"main",(char *)"\\offset(&A[3]) == 12",14); + } + /*@ assert \offset(PA) ≡ 0; */ + { + unsigned long __gen_e_acsl_offset_3; + __gen_e_acsl_offset_3 = __e_acsl_offset((void *)PA); + __e_acsl_assert(__gen_e_acsl_offset_3 == 0UL,(char *)"Assertion", + (char *)"main",(char *)"\\offset(PA) == 0",15); + } + PA ++; + /*@ assert \offset(PA + 1) ≡ 8; */ + { + unsigned long __gen_e_acsl_offset_4; + __gen_e_acsl_offset_4 = __e_acsl_offset((void *)(PA + 1)); + __e_acsl_assert(__gen_e_acsl_offset_4 == 8UL,(char *)"Assertion", + (char *)"main",(char *)"\\offset(PA + 1) == 8",17); + } + int a[4] = {1, 2, 3, 4}; + __e_acsl_store_block((void *)(a),(size_t)16); + __e_acsl_full_init((void *)(& a)); + /*@ assert \offset((int *)a) ≡ 0; */ + { + unsigned long __gen_e_acsl_offset_5; + __gen_e_acsl_offset_5 = __e_acsl_offset((void *)(a)); + __e_acsl_assert(__gen_e_acsl_offset_5 == 0UL,(char *)"Assertion", + (char *)"main",(char *)"\\offset((int *)a) == 0",21); + } + /*@ assert \offset(&a[1]) ≡ 4; */ + { + unsigned long __gen_e_acsl_offset_6; + __gen_e_acsl_offset_6 = __e_acsl_offset((void *)(& a[1])); + __e_acsl_assert(__gen_e_acsl_offset_6 == 4UL,(char *)"Assertion", + (char *)"main",(char *)"\\offset(&a[1]) == 4",22); + } + /*@ assert \offset(&a[3]) ≡ 12; */ + { + unsigned long __gen_e_acsl_offset_7; + __gen_e_acsl_offset_7 = __e_acsl_offset((void *)(& a[3])); + __e_acsl_assert(__gen_e_acsl_offset_7 == 12UL,(char *)"Assertion", + (char *)"main",(char *)"\\offset(&a[3]) == 12",23); + } + long l = (long)4; + __e_acsl_store_block((void *)(& l),(size_t)8); + __e_acsl_full_init((void *)(& l)); + char *pl = (char *)(& l); + __e_acsl_store_block((void *)(& pl),(size_t)8); + __e_acsl_full_init((void *)(& pl)); + /*@ assert \offset(&l) ≡ 0; */ + { + unsigned long __gen_e_acsl_offset_8; + __gen_e_acsl_offset_8 = __e_acsl_offset((void *)(& l)); + __e_acsl_assert(__gen_e_acsl_offset_8 == 0UL,(char *)"Assertion", + (char *)"main",(char *)"\\offset(&l) == 0",28); + } + /*@ assert \offset(pl) ≡ 0; */ + { + unsigned long __gen_e_acsl_offset_9; + __gen_e_acsl_offset_9 = __e_acsl_offset((void *)pl); + __e_acsl_assert(__gen_e_acsl_offset_9 == 0UL,(char *)"Assertion", + (char *)"main",(char *)"\\offset(pl) == 0",29); + } + /*@ assert \offset(pl + 1) ≡ 1; */ + { + unsigned long __gen_e_acsl_offset_10; + __gen_e_acsl_offset_10 = __e_acsl_offset((void *)(pl + 1)); + __e_acsl_assert(__gen_e_acsl_offset_10 == 1UL,(char *)"Assertion", + (char *)"main",(char *)"\\offset(pl + 1) == 1",30); + } + /*@ assert \offset(pl + 7) ≡ 7; */ + { + unsigned long __gen_e_acsl_offset_11; + __gen_e_acsl_offset_11 = __e_acsl_offset((void *)(pl + 7)); + __e_acsl_assert(__gen_e_acsl_offset_11 == 7UL,(char *)"Assertion", + (char *)"main",(char *)"\\offset(pl + 7) == 7",31); + } + int *pi = (int *)(& l); + __e_acsl_store_block((void *)(& pi),(size_t)8); + __e_acsl_full_init((void *)(& pi)); + /*@ assert \offset(pi) ≡ 0; */ + { + unsigned long __gen_e_acsl_offset_12; + __gen_e_acsl_offset_12 = __e_acsl_offset((void *)pi); + __e_acsl_assert(__gen_e_acsl_offset_12 == 0UL,(char *)"Assertion", + (char *)"main",(char *)"\\offset(pi) == 0",33); + } + __e_acsl_full_init((void *)(& pi)); + pi ++; + /*@ assert \offset(pi) ≡ 4; */ + { + unsigned long __gen_e_acsl_offset_13; + __gen_e_acsl_offset_13 = __e_acsl_offset((void *)pi); + __e_acsl_assert(__gen_e_acsl_offset_13 == 4UL,(char *)"Assertion", + (char *)"main",(char *)"\\offset(pi) == 4",35); + } + char *p = malloc((unsigned long)12); + __e_acsl_store_block((void *)(& p),(size_t)8); + __e_acsl_full_init((void *)(& p)); + /*@ assert \offset(p) ≡ 0; */ + { + unsigned long __gen_e_acsl_offset_14; + __gen_e_acsl_offset_14 = __e_acsl_offset((void *)p); + __e_acsl_assert(__gen_e_acsl_offset_14 == 0UL,(char *)"Assertion", + (char *)"main",(char *)"\\offset(p) == 0",39); + } + /*@ assert \offset(p + 1) ≡ 1; */ + { + unsigned long __gen_e_acsl_offset_15; + __gen_e_acsl_offset_15 = __e_acsl_offset((void *)(p + 1)); + __e_acsl_assert(__gen_e_acsl_offset_15 == 1UL,(char *)"Assertion", + (char *)"main",(char *)"\\offset(p + 1) == 1",40); + } + /*@ assert \offset(p + 11) ≡ 11; */ + { + unsigned long __gen_e_acsl_offset_16; + __gen_e_acsl_offset_16 = __e_acsl_offset((void *)(p + 11)); + __e_acsl_assert(__gen_e_acsl_offset_16 == 11UL,(char *)"Assertion", + (char *)"main",(char *)"\\offset(p + 11) == 11",41); + } + __e_acsl_full_init((void *)(& p)); + p += 5; + /*@ assert \offset(p + 5) ≡ 10; */ + { + unsigned long __gen_e_acsl_offset_17; + __gen_e_acsl_offset_17 = __e_acsl_offset((void *)(p + 5)); + __e_acsl_assert(__gen_e_acsl_offset_17 == 10UL,(char *)"Assertion", + (char *)"main",(char *)"\\offset(p + 5) == 10",43); + } + /*@ assert \offset(p - 5) ≡ 0; */ + { + unsigned long __gen_e_acsl_offset_18; + __gen_e_acsl_offset_18 = __e_acsl_offset((void *)(p - 5)); + __e_acsl_assert(__gen_e_acsl_offset_18 == 0UL,(char *)"Assertion", + (char *)"main",(char *)"\\offset(p - 5) == 0",44); + } + long *q = malloc((unsigned long)30 * sizeof(long)); + __e_acsl_store_block((void *)(& q),(size_t)8); + __e_acsl_full_init((void *)(& q)); + /*@ assert \offset(q) ≡ 0; */ + { + unsigned long __gen_e_acsl_offset_19; + __gen_e_acsl_offset_19 = __e_acsl_offset((void *)q); + __e_acsl_assert(__gen_e_acsl_offset_19 == 0UL,(char *)"Assertion", + (char *)"main",(char *)"\\offset(q) == 0",49); + } + __e_acsl_full_init((void *)(& q)); + q ++; + /*@ assert \offset(q) ≡ sizeof(long); */ + { + unsigned long __gen_e_acsl_offset_20; + __gen_e_acsl_offset_20 = __e_acsl_offset((void *)q); + __e_acsl_assert(__gen_e_acsl_offset_20 == 8UL,(char *)"Assertion", + (char *)"main",(char *)"\\offset(q) == sizeof(long)",51); + } + __e_acsl_full_init((void *)(& q)); + q += 2; + /*@ assert \offset(q) ≡ sizeof(long) * 3; */ + { + unsigned long __gen_e_acsl_offset_21; + __gen_e_acsl_offset_21 = __e_acsl_offset((void *)q); + __e_acsl_assert(__gen_e_acsl_offset_21 == 24UL,(char *)"Assertion", + (char *)"main",(char *)"\\offset(q) == sizeof(long) * 3", + 53); + } + __e_acsl_full_init((void *)(& q)); + q += 4; + /*@ assert \offset(q) ≡ sizeof(long) * 7; */ + { + unsigned long __gen_e_acsl_offset_22; + __gen_e_acsl_offset_22 = __e_acsl_offset((void *)q); + __e_acsl_assert(__gen_e_acsl_offset_22 == 56UL,(char *)"Assertion", + (char *)"main",(char *)"\\offset(q) == sizeof(long) * 7", + 55); + } + __retres = 0; + __e_acsl_delete_block((void *)(& PA)); + __e_acsl_delete_block((void *)(A)); + __e_acsl_delete_block((void *)(& q)); + __e_acsl_delete_block((void *)(& p)); + __e_acsl_delete_block((void *)(& pi)); + __e_acsl_delete_block((void *)(& pl)); + __e_acsl_delete_block((void *)(& l)); + __e_acsl_delete_block((void *)(a)); + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/gen_other_constants.c b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_other_constants.c new file mode 100644 index 0000000000000000000000000000000000000000..04ef8ac7086642aa29dbe64d56a8d11c377e98b4 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_other_constants.c @@ -0,0 +1,22 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +enum bool { + false = 0, + true = 1 +}; +int main(void) +{ + int __retres; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + /*@ assert 'c' ≡ 'c'; */ + __e_acsl_assert(1,(char *)"Assertion",(char *)"main", + (char *)"\'c\' == \'c\'",10); + /*@ assert false ≢ true; */ + __e_acsl_assert(1,(char *)"Assertion",(char *)"main", + (char *)"false != true",11); + __retres = 0; + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/gen_ptr.c b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_ptr.c new file mode 100644 index 0000000000000000000000000000000000000000..17ad50e1329c8952f61b1b47a84f952280219876 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_ptr.c @@ -0,0 +1,124 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +int main(void) +{ + int __retres; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + int x = 1; + __e_acsl_store_block((void *)(& x),(size_t)4); + __e_acsl_full_init((void *)(& x)); + int t[3] = {2, 3, 4}; + __e_acsl_store_block((void *)(t),(size_t)12); + __e_acsl_full_init((void *)(& t)); + int *p = & x; + __e_acsl_store_block((void *)(& p),(size_t)8); + __e_acsl_full_init((void *)(& p)); + /*@ assert *p ≡ 1; */ + { + int __gen_e_acsl_initialized; + int __gen_e_acsl_and; + __gen_e_acsl_initialized = __e_acsl_initialized((void *)(& p), + sizeof(int *)); + if (__gen_e_acsl_initialized) { + int __gen_e_acsl_valid_read; + __gen_e_acsl_valid_read = __e_acsl_valid_read((void *)p,sizeof(int), + (void *)p,(void *)(& p)); + __gen_e_acsl_and = __gen_e_acsl_valid_read; + } + else __gen_e_acsl_and = 0; + __e_acsl_assert(__gen_e_acsl_and,(char *)"RTE",(char *)"main", + (char *)"mem_access: \\valid_read(p)",11); + __e_acsl_assert(*p == 1,(char *)"Assertion",(char *)"main", + (char *)"*p == 1",11); + } + /*@ assert t[0] ≡ 2; */ + __e_acsl_assert(t[0] == 2,(char *)"Assertion",(char *)"main", + (char *)"t[0] == 2",12); + /*@ assert t[2] ≡ 4; */ + __e_acsl_assert(t[2] == 4,(char *)"Assertion",(char *)"main", + (char *)"t[2] == 4",13); + /*@ assert t[(2 * sizeof(int)) / sizeof((int)0x0)] ≡ 4; */ + __e_acsl_assert(t[2] == 4,(char *)"Assertion",(char *)"main", + (char *)"t[(2 * sizeof(int)) / sizeof((int)0x0)] == 4",14); + { + int i = 0; + while (i < 2) { + /*@ assert t[i] ≡ i + 2; */ + { + __e_acsl_assert(i < 3,(char *)"RTE",(char *)"main", + (char *)"index_bound: i < 3",17); + __e_acsl_assert(0 <= i,(char *)"RTE",(char *)"main", + (char *)"index_bound: 0 <= i",17); + __e_acsl_assert((long)t[i] == i + 2L,(char *)"Assertion", + (char *)"main",(char *)"t[i] == i + 2",17); + } + /*@ assert t[2 - i] ≡ 4 - i; */ + { + __e_acsl_assert(2L - i < 3L,(char *)"RTE",(char *)"main", + (char *)"index_bound: (long)(2 - i) < 3",18); + __e_acsl_assert(0L <= 2L - i,(char *)"RTE",(char *)"main", + (char *)"index_bound: 0 <= (long)(2 - i)",18); + __e_acsl_assert((long)t[2L - i] == 4L - i,(char *)"Assertion", + (char *)"main",(char *)"t[2 - i] == 4 - i",18); + } + /*@ assert *(&t[2] - i) ≡ 4 - i; */ + { + int __gen_e_acsl_valid_read_2; + __gen_e_acsl_valid_read_2 = __e_acsl_valid_read((void *)(& t[2] - i), + sizeof(int), + (void *)(& t[2]), + (void *)0); + __e_acsl_assert(__gen_e_acsl_valid_read_2,(char *)"RTE", + (char *)"main", + (char *)"mem_access: \\valid_read(&t[2] - i)",19); + __e_acsl_assert((long)*(& t[2] - i) == 4L - i,(char *)"Assertion", + (char *)"main",(char *)"*(&t[2] - i) == 4 - i",19); + } + i ++; + } + } + __e_acsl_full_init((void *)(& p)); + p = & t[2]; + __e_acsl_initialize((void *)(& t[2]),sizeof(int)); + t[2] = 5; + /*@ assert *p ≡ 5; */ + { + int __gen_e_acsl_initialized_2; + int __gen_e_acsl_and_2; + __gen_e_acsl_initialized_2 = __e_acsl_initialized((void *)(& p), + sizeof(int *)); + if (__gen_e_acsl_initialized_2) { + int __gen_e_acsl_valid_read_3; + __gen_e_acsl_valid_read_3 = __e_acsl_valid_read((void *)p,sizeof(int), + (void *)p, + (void *)(& p)); + __gen_e_acsl_and_2 = __gen_e_acsl_valid_read_3; + } + else __gen_e_acsl_and_2 = 0; + __e_acsl_assert(__gen_e_acsl_and_2,(char *)"RTE",(char *)"main", + (char *)"mem_access: \\valid_read(p)",25); + __e_acsl_assert(*p == 5,(char *)"Assertion",(char *)"main", + (char *)"*p == 5",25); + } + int k = -1; + /*@ assert *(p + k) ≡ 3; */ + { + int __gen_e_acsl_valid_read_4; + __gen_e_acsl_valid_read_4 = __e_acsl_valid_read((void *)(p + k), + sizeof(int),(void *)p, + (void *)(& p)); + __e_acsl_assert(__gen_e_acsl_valid_read_4,(char *)"RTE",(char *)"main", + (char *)"mem_access: \\valid_read(p + k)",27); + __e_acsl_assert(*(p + k) == 3,(char *)"Assertion",(char *)"main", + (char *)"*(p + k) == 3",27); + } + __retres = 0; + __e_acsl_delete_block((void *)(& p)); + __e_acsl_delete_block((void *)(t)); + __e_acsl_delete_block((void *)(& x)); + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/gen_ptr_init.c b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_ptr_init.c new file mode 100644 index 0000000000000000000000000000000000000000..657cc0beb821266115ea1b8a3b82b55e24f24da6 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_ptr_init.c @@ -0,0 +1,73 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +int *A; +int *B; +void f(void) +{ + A = B; + return; +} + +void g(int *C, int *D) +{ + /*@ assert \initialized(&C); */ + { + __e_acsl_store_block((void *)(& C),(size_t)8); + __e_acsl_assert(1,(char *)"Assertion",(char *)"g", + (char *)"\\initialized(&C)",16); + } + __e_acsl_delete_block((void *)(& C)); + return; +} + +void __e_acsl_globals_init(void) +{ + static char __e_acsl_already_run = 0; + if (! __e_acsl_already_run) { + __e_acsl_already_run = 1; + __e_acsl_store_block((void *)(& B),(size_t)8); + __e_acsl_full_init((void *)(& B)); + __e_acsl_store_block((void *)(& A),(size_t)8); + __e_acsl_full_init((void *)(& A)); + } + return; +} + +int main(void) +{ + int __retres; + int *x; + int *y; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + __e_acsl_globals_init(); + __e_acsl_store_block((void *)(& y),(size_t)8); + __e_acsl_store_block((void *)(& x),(size_t)8); + B = (int *)malloc(sizeof(int)); + __e_acsl_full_init((void *)(& y)); + y = (int *)malloc(sizeof(int)); + __e_acsl_full_init((void *)(& x)); + x = y; + f(); + /*@ assert \initialized(&A); */ + __e_acsl_assert(1,(char *)"Assertion",(char *)"main", + (char *)"\\initialized(&A)",25); + /*@ assert \initialized(&x); */ + { + int __gen_e_acsl_initialized; + __gen_e_acsl_initialized = __e_acsl_initialized((void *)(& x), + sizeof(int *)); + __e_acsl_assert(__gen_e_acsl_initialized,(char *)"Assertion", + (char *)"main",(char *)"\\initialized(&x)",26); + } + g(x,y); + __retres = 0; + __e_acsl_delete_block((void *)(& B)); + __e_acsl_delete_block((void *)(& A)); + __e_acsl_delete_block((void *)(& y)); + __e_acsl_delete_block((void *)(& x)); + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/gen_ranges_in_builtins.c b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_ranges_in_builtins.c new file mode 100644 index 0000000000000000000000000000000000000000..f3f30617bd5875b6ed483e4e9befc9dd3082bcf9 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_ranges_in_builtins.c @@ -0,0 +1,606 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +extern int __e_acsl_sound_verdict; + +struct S { + int a[2] ; + float *b ; + float *c ; +}; +/*@ requires ¬\valid(s + (3 .. n + 1000)); */ +void __gen_e_acsl_f(char *s, long n); + +void f(char *s, long n) +{ + return; +} + +/*@ requires \valid(ptr + (0 .. size - 1)); + ensures ¬\valid(\old(ptr) + (0 .. \old(size) + 1)); + */ +void __gen_e_acsl_g(long *ptr, size_t size); + +void g(long *ptr, size_t size) +{ + __e_acsl_store_block((void *)(& ptr),(size_t)8); + __e_acsl_delete_block((void *)(& ptr)); + return; +} + +int main(void) +{ + int __retres; + int *a; + char *b; + double t2[4]; + float t3[7][2][4]; + struct S s; + int **multi_dynamic; + int i; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + __e_acsl_store_block((void *)(& multi_dynamic),(size_t)8); + __e_acsl_store_block((void *)(& s),(size_t)24); + __e_acsl_store_block((void *)(t3),(size_t)224); + __e_acsl_store_block((void *)(t2),(size_t)32); + __e_acsl_store_block((void *)(& b),(size_t)8); + __e_acsl_store_block((void *)(& a),(size_t)8); + __e_acsl_full_init((void *)(& a)); + a = (int *)malloc((unsigned long)10 * sizeof(int)); + /*@ assert \valid(a + (0 .. 4)); */ + { + int __gen_e_acsl_valid; + __gen_e_acsl_valid = __e_acsl_valid((void *)((char *)a + 4 * 0), + (size_t)16,(void *)a,(void *)(& a)); + __e_acsl_assert(__gen_e_acsl_valid,(char *)"Assertion",(char *)"main", + (char *)"\\valid(a + (0 .. 4))",19); + } + int j = 2; + /*@ assert \valid(a + (4 .. 8 + j)); */ + { + int __gen_e_acsl_valid_2; + __gen_e_acsl_valid_2 = __e_acsl_valid((void *)((char *)a + 4 * 4), + (size_t)(4L * ((8L + j) - 4L)), + (void *)a,(void *)(& a)); + __e_acsl_assert(__gen_e_acsl_valid_2,(char *)"Assertion",(char *)"main", + (char *)"\\valid(a + (4 .. 8 + j))",21); + } + /*@ assert ¬\valid(a + (10 .. 11)); */ + { + int __gen_e_acsl_valid_3; + __gen_e_acsl_valid_3 = __e_acsl_valid((void *)((char *)a + 4 * 10), + (size_t)4,(void *)a,(void *)(& a)); + __e_acsl_assert(! __gen_e_acsl_valid_3,(char *)"Assertion", + (char *)"main",(char *)"!\\valid(a + (10 .. 11))",22); + } + free((void *)a); + __e_acsl_full_init((void *)(& b)); + b = (char *)malloc((unsigned long)10 * sizeof(char)); + /*@ assert \valid(b + (0 .. 10)); */ + { + int __gen_e_acsl_valid_4; + __gen_e_acsl_valid_4 = __e_acsl_valid((void *)(b + 1 * 0),(size_t)10, + (void *)b,(void *)(& b)); + __e_acsl_assert(__gen_e_acsl_valid_4,(char *)"Assertion",(char *)"main", + (char *)"\\valid(b + (0 .. 10))",27); + } + /*@ assert ¬\valid(b + (11 .. 15)); */ + { + int __gen_e_acsl_valid_5; + __gen_e_acsl_valid_5 = __e_acsl_valid((void *)(b + 1 * 11),(size_t)4, + (void *)b,(void *)(& b)); + __e_acsl_assert(! __gen_e_acsl_valid_5,(char *)"Assertion", + (char *)"main",(char *)"!\\valid(b + (11 .. 15))",28); + } + long t[3] = {7l, 8l, 9l}; + __e_acsl_store_block((void *)(t),(size_t)24); + __e_acsl_full_init((void *)(& t)); + /*@ assert \valid(&t[0 .. 2]); */ + { + int __gen_e_acsl_valid_6; + __gen_e_acsl_valid_6 = __e_acsl_valid((void *)((char *)(& t) + 8 * 0), + (size_t)16,(void *)(& t),(void *)0); + __e_acsl_assert(__gen_e_acsl_valid_6,(char *)"Assertion",(char *)"main", + (char *)"\\valid(&t[0 .. 2])",31); + } + /*@ assert ¬\valid(&t[3 .. 5]); */ + { + int __gen_e_acsl_valid_7; + __gen_e_acsl_valid_7 = __e_acsl_valid((void *)((char *)(& t) + 8 * 3), + (size_t)16,(void *)(& t),(void *)0); + __e_acsl_assert(! __gen_e_acsl_valid_7,(char *)"Assertion", + (char *)"main",(char *)"!\\valid(&t[3 .. 5])",32); + } + __gen_e_acsl_g(t,(unsigned long)3); + __e_acsl_initialize((void *)(t2),sizeof(double)); + t2[0] = 0.5; + __e_acsl_initialize((void *)(& t2[1]),sizeof(double)); + t2[1] = 1.5; + /*@ assert \initialized(&t2[0 .. 1]); */ + { + int __gen_e_acsl_initialized; + __gen_e_acsl_initialized = __e_acsl_initialized((void *)((char *)(& t2) + + 8 * 0), + (size_t)8); + __e_acsl_assert(__gen_e_acsl_initialized,(char *)"Assertion", + (char *)"main",(char *)"\\initialized(&t2[0 .. 1])",38); + } + /*@ assert ¬\initialized(&t2[2 .. 3]); */ + { + int __gen_e_acsl_initialized_2; + __gen_e_acsl_initialized_2 = __e_acsl_initialized((void *)((char *)(& t2) + + 8 * 2), + (size_t)8); + __e_acsl_assert(! __gen_e_acsl_initialized_2,(char *)"Assertion", + (char *)"main",(char *)"!\\initialized(&t2[2 .. 3])",39); + } + /*@ assert ¬\initialized(b + (0 .. 10)); */ + { + int __gen_e_acsl_initialized_3; + __gen_e_acsl_initialized_3 = __e_acsl_initialized((void *)(b + 1 * 0), + (size_t)10); + __e_acsl_assert(! __gen_e_acsl_initialized_3,(char *)"Assertion", + (char *)"main",(char *)"!\\initialized(b + (0 .. 10))", + 41); + } + free((void *)b); + int n = 2; + /*@ assert ¬\initialized(&t3[n - 1 .. n + 2][1][0 .. 1]); */ + { + int __gen_e_acsl_forall; + int __gen_e_acsl_range_2; + __gen_e_acsl_forall = 1; + __gen_e_acsl_range_2 = 0; + while (1) { + if (__gen_e_acsl_range_2 <= 1) ; else break; + { + int __gen_e_acsl_forall_2; + long __gen_e_acsl_range; + __gen_e_acsl_forall_2 = 1; + __gen_e_acsl_range = n - 1L; + while (1) { + if (__gen_e_acsl_range <= n + 2L) ; else break; + { + int __gen_e_acsl_initialized_4; + __gen_e_acsl_initialized_4 = __e_acsl_initialized((void *)(& t3[__gen_e_acsl_range][1][__gen_e_acsl_range_2]), + sizeof(float)); + if (__gen_e_acsl_initialized_4) ; + else { + __gen_e_acsl_forall_2 = 0; + goto e_acsl_end_loop1; + } + } + __gen_e_acsl_range ++; + } + e_acsl_end_loop1: ; + if (__gen_e_acsl_forall_2) ; + else { + __gen_e_acsl_forall = 0; + goto e_acsl_end_loop2; + } + } + __gen_e_acsl_range_2 ++; + } + e_acsl_end_loop2: ; + __e_acsl_assert(! __gen_e_acsl_forall,(char *)"Assertion",(char *)"main", + (char *)"!\\initialized(&t3[n - 1 .. n + 2][1][0 .. 1])", + 46); + } + /*@ assert ¬\valid_read(&t3[6][1][0] + (2 .. 10)); */ + { + int __gen_e_acsl_valid_read; + __gen_e_acsl_valid_read = __e_acsl_valid_read((void *)((char *)(& t3[6][1][0]) + + 4 * 2),(size_t)32, + (void *)(& t3[6][1][0]), + (void *)0); + __e_acsl_assert(! __gen_e_acsl_valid_read,(char *)"Assertion", + (char *)"main", + (char *)"!\\valid_read(&t3[6][1][0] + (2 .. 10))",48); + } + /*@ assert \valid_read(&t3[n - 1 .. n + 2][1]); */ + { + int __gen_e_acsl_forall_3; + long __gen_e_acsl_range_3; + __gen_e_acsl_forall_3 = 1; + __gen_e_acsl_range_3 = n - 1L; + while (1) { + if (__gen_e_acsl_range_3 <= n + 2L) ; else break; + { + int __gen_e_acsl_valid_read_2; + __gen_e_acsl_valid_read_2 = __e_acsl_valid_read((void *)(& t3[__gen_e_acsl_range_3][1]), + sizeof(float [4]), + (void *)(& t3[__gen_e_acsl_range_3][1]), + (void *)0); + if (__gen_e_acsl_valid_read_2) ; + else { + __gen_e_acsl_forall_3 = 0; + goto e_acsl_end_loop3; + } + } + __gen_e_acsl_range_3 ++; + } + e_acsl_end_loop3: ; + __e_acsl_assert(__gen_e_acsl_forall_3,(char *)"Assertion",(char *)"main", + (char *)"\\valid_read(&t3[n - 1 .. n + 2][1])",49); + } + __e_acsl_initialize((void *)(& s.a[0]),sizeof(int)); + s.a[0] = 7; + __e_acsl_initialize((void *)(& s.a[1]),sizeof(int)); + s.a[1] = 8; + /*@ assert \initialized(&s.a[0] + (1 .. 2)); */ + { + int __gen_e_acsl_initialized_5; + __gen_e_acsl_initialized_5 = __e_acsl_initialized((void *)((char *)(& s.a[0]) + + 4 * 1), + (size_t)4); + __e_acsl_assert(__gen_e_acsl_initialized_5,(char *)"Assertion", + (char *)"main", + (char *)"\\initialized(&s.a[0] + (1 .. 2))",53); + } + /*@ assert ¬\initialized(s.b + (0 .. 1)); */ + { + int __gen_e_acsl_initialized_6; + __gen_e_acsl_initialized_6 = __e_acsl_initialized((void *)((char *)s.b + + 4 * 0), + (size_t)4); + __e_acsl_assert(! __gen_e_acsl_initialized_6,(char *)"Assertion", + (char *)"main",(char *)"!\\initialized(s.b + (0 .. 1))", + 54); + } + int size1 = 5; + int size2 = 9; + __e_acsl_full_init((void *)(& multi_dynamic)); + multi_dynamic = (int **)malloc((unsigned long)size1 * sizeof(*multi_dynamic)); + i = 0; + while (i < size1) { + __e_acsl_initialize((void *)(multi_dynamic + i),sizeof(int *)); + *(multi_dynamic + i) = (int *)malloc((unsigned long)size2 * sizeof(*(*( + multi_dynamic + i)))); + i ++; + } + /*@ assert \valid(*(multi_dynamic + 4) + (1 .. 7)); */ + { + int __gen_e_acsl_valid_read_3; + int __gen_e_acsl_valid_8; + __gen_e_acsl_valid_read_3 = __e_acsl_valid_read((void *)(multi_dynamic + 4), + sizeof(int *), + (void *)multi_dynamic, + (void *)(& multi_dynamic)); + __e_acsl_assert(__gen_e_acsl_valid_read_3,(char *)"RTE",(char *)"main", + (char *)"mem_access: \\valid_read(multi_dynamic + 4)",63); + __gen_e_acsl_valid_8 = __e_acsl_valid((void *)((char *)*(multi_dynamic + 4) + + 4 * 1),(size_t)24, + (void *)*(multi_dynamic + 4), + (void *)(multi_dynamic + 4)); + __e_acsl_assert(__gen_e_acsl_valid_8,(char *)"Assertion",(char *)"main", + (char *)"\\valid(*(multi_dynamic + 4) + (1 .. 7))",63); + } + /*@ assert \valid(*(multi_dynamic + (2 .. 4)) + (1 .. 7)); */ ; + i --; + while (i >= 0) { + free((void *)*(multi_dynamic + i)); + i --; + } + free((void *)multi_dynamic); + char c = (char)'w'; + __e_acsl_store_block((void *)(& c),(size_t)1); + __e_acsl_full_init((void *)(& c)); + __gen_e_acsl_f(& c,(long)5); + __retres = 0; + __e_acsl_delete_block((void *)(& c)); + __e_acsl_delete_block((void *)(& multi_dynamic)); + __e_acsl_delete_block((void *)(& s)); + __e_acsl_delete_block((void *)(t3)); + __e_acsl_delete_block((void *)(t2)); + __e_acsl_delete_block((void *)(t)); + __e_acsl_delete_block((void *)(& b)); + __e_acsl_delete_block((void *)(& a)); + __e_acsl_memory_clean(); + return __retres; +} + +/*@ requires \valid(ptr + (0 .. size - 1)); + ensures ¬\valid(\old(ptr) + (0 .. \old(size) + 1)); + */ +void __gen_e_acsl_g(long *ptr, size_t size) +{ + __e_acsl_mpz_t __gen_e_acsl_at_2; + long *__gen_e_acsl_at; + { + __e_acsl_mpz_t __gen_e_acsl_size_6; + __gmpz_init_set_ui(__gen_e_acsl_size_6,size); + __gmpz_init_set(__gen_e_acsl_at_2, + (__e_acsl_mpz_struct const *)(__gen_e_acsl_size_6)); + __gmpz_clear(__gen_e_acsl_size_6); + } + { + __e_acsl_mpz_t __gen_e_acsl_size_5; + __gmpz_init_set_ui(__gen_e_acsl_size_5,size); + __gmpz_init_set(__gen_e_acsl_at_2, + (__e_acsl_mpz_struct const *)(__gen_e_acsl_size_5)); + __gmpz_clear(__gen_e_acsl_size_5); + } + { + __e_acsl_mpz_t __gen_e_acsl_size_4; + __gmpz_init_set_ui(__gen_e_acsl_size_4,size); + __gmpz_init_set(__gen_e_acsl_at_2, + (__e_acsl_mpz_struct const *)(__gen_e_acsl_size_4)); + __gmpz_clear(__gen_e_acsl_size_4); + } + __gen_e_acsl_at = ptr; + { + __e_acsl_mpz_t __gen_e_acsl_; + __e_acsl_mpz_t __gen_e_acsl_sizeof; + __e_acsl_mpz_t __gen_e_acsl_size; + __e_acsl_mpz_t __gen_e_acsl__2; + __e_acsl_mpz_t __gen_e_acsl_sub; + __e_acsl_mpz_t __gen_e_acsl_sub_2; + __e_acsl_mpz_t __gen_e_acsl_mul; + int __gen_e_acsl_le; + int __gen_e_acsl_and; + unsigned long __gen_e_acsl_size_3; + int __gen_e_acsl_valid; + __e_acsl_store_block((void *)(& ptr),(size_t)8); + __gmpz_init_set_si(__gen_e_acsl_,0L); + __gmpz_init_set_si(__gen_e_acsl_sizeof,8L); + __gmpz_init_set_ui(__gen_e_acsl_size,size); + __gmpz_init_set_si(__gen_e_acsl__2,1L); + __gmpz_init(__gen_e_acsl_sub); + __gmpz_sub(__gen_e_acsl_sub, + (__e_acsl_mpz_struct const *)(__gen_e_acsl_size), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__2)); + __gmpz_init(__gen_e_acsl_sub_2); + __gmpz_sub(__gen_e_acsl_sub_2, + (__e_acsl_mpz_struct const *)(__gen_e_acsl_sub), + (__e_acsl_mpz_struct const *)(__gen_e_acsl_)); + __gmpz_init(__gen_e_acsl_mul); + __gmpz_mul(__gen_e_acsl_mul, + (__e_acsl_mpz_struct const *)(__gen_e_acsl_sizeof), + (__e_acsl_mpz_struct const *)(__gen_e_acsl_sub_2)); + __gen_e_acsl_le = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_), + (__e_acsl_mpz_struct const *)(__gen_e_acsl_mul)); + if (__gen_e_acsl_le <= 0) { + __e_acsl_mpz_t __gen_e_acsl_sizeof_2; + __e_acsl_mpz_t __gen_e_acsl_size_2; + __e_acsl_mpz_t __gen_e_acsl__3; + __e_acsl_mpz_t __gen_e_acsl_sub_3; + __e_acsl_mpz_t __gen_e_acsl__4; + __e_acsl_mpz_t __gen_e_acsl_sub_4; + __e_acsl_mpz_t __gen_e_acsl_mul_2; + __e_acsl_mpz_t __gen_e_acsl__5; + int __gen_e_acsl_lt; + __gmpz_init_set_si(__gen_e_acsl_sizeof_2,8L); + __gmpz_init_set_ui(__gen_e_acsl_size_2,size); + __gmpz_init_set_si(__gen_e_acsl__3,1L); + __gmpz_init(__gen_e_acsl_sub_3); + __gmpz_sub(__gen_e_acsl_sub_3, + (__e_acsl_mpz_struct const *)(__gen_e_acsl_size_2), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__3)); + __gmpz_init_set_si(__gen_e_acsl__4,0L); + __gmpz_init(__gen_e_acsl_sub_4); + __gmpz_sub(__gen_e_acsl_sub_4, + (__e_acsl_mpz_struct const *)(__gen_e_acsl_sub_3), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__4)); + __gmpz_init(__gen_e_acsl_mul_2); + __gmpz_mul(__gen_e_acsl_mul_2, + (__e_acsl_mpz_struct const *)(__gen_e_acsl_sizeof_2), + (__e_acsl_mpz_struct const *)(__gen_e_acsl_sub_4)); + __gmpz_init_set_ui(__gen_e_acsl__5,18446744073709551615UL); + __gen_e_acsl_lt = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_mul_2), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__5)); + __gen_e_acsl_and = __gen_e_acsl_lt < 0; + __gmpz_clear(__gen_e_acsl_sizeof_2); + __gmpz_clear(__gen_e_acsl_size_2); + __gmpz_clear(__gen_e_acsl__3); + __gmpz_clear(__gen_e_acsl_sub_3); + __gmpz_clear(__gen_e_acsl__4); + __gmpz_clear(__gen_e_acsl_sub_4); + __gmpz_clear(__gen_e_acsl_mul_2); + __gmpz_clear(__gen_e_acsl__5); + } + else __gen_e_acsl_and = 0; + __e_acsl_assert(__gen_e_acsl_and,(char *)"RTE",(char *)"g", + (char *)"\\valid(ptr + (0 .. size - 1))",7); + __gen_e_acsl_size_3 = __gmpz_get_ui((__e_acsl_mpz_struct const *)(__gen_e_acsl_mul)); + __gen_e_acsl_valid = __e_acsl_valid((void *)((char *)ptr + 8 * 0), + __gen_e_acsl_size_3,(void *)ptr, + (void *)(& ptr)); + __e_acsl_assert(__gen_e_acsl_valid,(char *)"Precondition",(char *)"g", + (char *)"\\valid(ptr + (0 .. size - 1))",7); + __gmpz_clear(__gen_e_acsl_); + __gmpz_clear(__gen_e_acsl_sizeof); + __gmpz_clear(__gen_e_acsl_size); + __gmpz_clear(__gen_e_acsl__2); + __gmpz_clear(__gen_e_acsl_sub); + __gmpz_clear(__gen_e_acsl_sub_2); + __gmpz_clear(__gen_e_acsl_mul); + } + g(ptr,size); + { + __e_acsl_mpz_t __gen_e_acsl__6; + __e_acsl_mpz_t __gen_e_acsl_sizeof_3; + __e_acsl_mpz_t __gen_e_acsl__7; + __e_acsl_mpz_t __gen_e_acsl_add; + __e_acsl_mpz_t __gen_e_acsl_sub_5; + __e_acsl_mpz_t __gen_e_acsl_mul_3; + int __gen_e_acsl_le_2; + int __gen_e_acsl_and_2; + unsigned long __gen_e_acsl_size_7; + int __gen_e_acsl_valid_2; + __gmpz_init_set_si(__gen_e_acsl__6,0L); + __gmpz_init_set_si(__gen_e_acsl_sizeof_3,8L); + __gmpz_init_set_si(__gen_e_acsl__7,1L); + __gmpz_init(__gen_e_acsl_add); + __gmpz_add(__gen_e_acsl_add, + (__e_acsl_mpz_struct const *)(__gen_e_acsl_at_2), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__7)); + __gmpz_init(__gen_e_acsl_sub_5); + __gmpz_sub(__gen_e_acsl_sub_5, + (__e_acsl_mpz_struct const *)(__gen_e_acsl_add), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__6)); + __gmpz_init(__gen_e_acsl_mul_3); + __gmpz_mul(__gen_e_acsl_mul_3, + (__e_acsl_mpz_struct const *)(__gen_e_acsl_sizeof_3), + (__e_acsl_mpz_struct const *)(__gen_e_acsl_sub_5)); + __gen_e_acsl_le_2 = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl__6), + (__e_acsl_mpz_struct const *)(__gen_e_acsl_mul_3)); + if (__gen_e_acsl_le_2 <= 0) { + __e_acsl_mpz_t __gen_e_acsl_sizeof_4; + __e_acsl_mpz_t __gen_e_acsl__8; + __e_acsl_mpz_t __gen_e_acsl_add_2; + __e_acsl_mpz_t __gen_e_acsl__9; + __e_acsl_mpz_t __gen_e_acsl_sub_6; + __e_acsl_mpz_t __gen_e_acsl_mul_4; + __e_acsl_mpz_t __gen_e_acsl__10; + int __gen_e_acsl_lt_2; + __gmpz_init_set_si(__gen_e_acsl_sizeof_4,8L); + __gmpz_init_set_si(__gen_e_acsl__8,1L); + __gmpz_init(__gen_e_acsl_add_2); + __gmpz_add(__gen_e_acsl_add_2, + (__e_acsl_mpz_struct const *)(__gen_e_acsl_at_2), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__8)); + __gmpz_init_set_si(__gen_e_acsl__9,0L); + __gmpz_init(__gen_e_acsl_sub_6); + __gmpz_sub(__gen_e_acsl_sub_6, + (__e_acsl_mpz_struct const *)(__gen_e_acsl_add_2), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__9)); + __gmpz_init(__gen_e_acsl_mul_4); + __gmpz_mul(__gen_e_acsl_mul_4, + (__e_acsl_mpz_struct const *)(__gen_e_acsl_sizeof_4), + (__e_acsl_mpz_struct const *)(__gen_e_acsl_sub_6)); + __gmpz_init_set_ui(__gen_e_acsl__10,18446744073709551615UL); + __gen_e_acsl_lt_2 = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_mul_4), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__10)); + __gen_e_acsl_and_2 = __gen_e_acsl_lt_2 < 0; + __gmpz_clear(__gen_e_acsl_sizeof_4); + __gmpz_clear(__gen_e_acsl__8); + __gmpz_clear(__gen_e_acsl_add_2); + __gmpz_clear(__gen_e_acsl__9); + __gmpz_clear(__gen_e_acsl_sub_6); + __gmpz_clear(__gen_e_acsl_mul_4); + __gmpz_clear(__gen_e_acsl__10); + } + else __gen_e_acsl_and_2 = 0; + __e_acsl_assert(__gen_e_acsl_and_2,(char *)"RTE",(char *)"g", + (char *)"\\valid(\\old(ptr) + (0 .. \\old(size) + 1))",8); + __gen_e_acsl_size_7 = __gmpz_get_ui((__e_acsl_mpz_struct const *)(__gen_e_acsl_mul_3)); + __gen_e_acsl_valid_2 = __e_acsl_valid((void *)((char *)__gen_e_acsl_at + + 8 * 0), + __gen_e_acsl_size_7, + (void *)__gen_e_acsl_at, + (void *)(& __gen_e_acsl_at)); + __e_acsl_assert(! __gen_e_acsl_valid_2,(char *)"Postcondition", + (char *)"g", + (char *)"!\\valid(\\old(ptr) + (0 .. \\old(size) + 1))", + 8); + __e_acsl_delete_block((void *)(& ptr)); + __gmpz_clear(__gen_e_acsl__6); + __gmpz_clear(__gen_e_acsl_sizeof_3); + __gmpz_clear(__gen_e_acsl__7); + __gmpz_clear(__gen_e_acsl_add); + __gmpz_clear(__gen_e_acsl_sub_5); + __gmpz_clear(__gen_e_acsl_mul_3); + __gmpz_clear(__gen_e_acsl_at_2); + return; + } +} + +/*@ requires ¬\valid(s + (3 .. n + 1000)); */ +void __gen_e_acsl_f(char *s, long n) +{ + { + __e_acsl_mpz_t __gen_e_acsl_; + __e_acsl_mpz_t __gen_e_acsl_sizeof; + __e_acsl_mpz_t __gen_e_acsl_n; + __e_acsl_mpz_t __gen_e_acsl__2; + __e_acsl_mpz_t __gen_e_acsl_add; + __e_acsl_mpz_t __gen_e_acsl__3; + __e_acsl_mpz_t __gen_e_acsl_sub; + __e_acsl_mpz_t __gen_e_acsl_mul; + int __gen_e_acsl_le; + int __gen_e_acsl_and; + unsigned long __gen_e_acsl_size; + int __gen_e_acsl_valid; + __e_acsl_store_block((void *)(& s),(size_t)8); + __gmpz_init_set_si(__gen_e_acsl_,0L); + __gmpz_init_set_si(__gen_e_acsl_sizeof,1L); + __gmpz_init_set_si(__gen_e_acsl_n,n); + __gmpz_init_set_si(__gen_e_acsl__2,1000L); + __gmpz_init(__gen_e_acsl_add); + __gmpz_add(__gen_e_acsl_add, + (__e_acsl_mpz_struct const *)(__gen_e_acsl_n), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__2)); + __gmpz_init_set_si(__gen_e_acsl__3,3L); + __gmpz_init(__gen_e_acsl_sub); + __gmpz_sub(__gen_e_acsl_sub, + (__e_acsl_mpz_struct const *)(__gen_e_acsl_add), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__3)); + __gmpz_init(__gen_e_acsl_mul); + __gmpz_mul(__gen_e_acsl_mul, + (__e_acsl_mpz_struct const *)(__gen_e_acsl_sizeof), + (__e_acsl_mpz_struct const *)(__gen_e_acsl_sub)); + __gen_e_acsl_le = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_), + (__e_acsl_mpz_struct const *)(__gen_e_acsl_mul)); + if (__gen_e_acsl_le <= 0) { + __e_acsl_mpz_t __gen_e_acsl_sizeof_2; + __e_acsl_mpz_t __gen_e_acsl_n_2; + __e_acsl_mpz_t __gen_e_acsl__4; + __e_acsl_mpz_t __gen_e_acsl_add_2; + __e_acsl_mpz_t __gen_e_acsl__5; + __e_acsl_mpz_t __gen_e_acsl_sub_2; + __e_acsl_mpz_t __gen_e_acsl_mul_2; + __e_acsl_mpz_t __gen_e_acsl__6; + int __gen_e_acsl_lt; + __gmpz_init_set_si(__gen_e_acsl_sizeof_2,1L); + __gmpz_init_set_si(__gen_e_acsl_n_2,n); + __gmpz_init_set_si(__gen_e_acsl__4,1000L); + __gmpz_init(__gen_e_acsl_add_2); + __gmpz_add(__gen_e_acsl_add_2, + (__e_acsl_mpz_struct const *)(__gen_e_acsl_n_2), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__4)); + __gmpz_init_set_si(__gen_e_acsl__5,3L); + __gmpz_init(__gen_e_acsl_sub_2); + __gmpz_sub(__gen_e_acsl_sub_2, + (__e_acsl_mpz_struct const *)(__gen_e_acsl_add_2), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__5)); + __gmpz_init(__gen_e_acsl_mul_2); + __gmpz_mul(__gen_e_acsl_mul_2, + (__e_acsl_mpz_struct const *)(__gen_e_acsl_sizeof_2), + (__e_acsl_mpz_struct const *)(__gen_e_acsl_sub_2)); + __gmpz_init_set_ui(__gen_e_acsl__6,18446744073709551615UL); + __gen_e_acsl_lt = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_mul_2), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__6)); + __gen_e_acsl_and = __gen_e_acsl_lt < 0; + __gmpz_clear(__gen_e_acsl_sizeof_2); + __gmpz_clear(__gen_e_acsl_n_2); + __gmpz_clear(__gen_e_acsl__4); + __gmpz_clear(__gen_e_acsl_add_2); + __gmpz_clear(__gen_e_acsl__5); + __gmpz_clear(__gen_e_acsl_sub_2); + __gmpz_clear(__gen_e_acsl_mul_2); + __gmpz_clear(__gen_e_acsl__6); + } + else __gen_e_acsl_and = 0; + __e_acsl_assert(__gen_e_acsl_and,(char *)"RTE",(char *)"f", + (char *)"\\valid(s + (3 .. n + 1000))",5); + __gen_e_acsl_size = __gmpz_get_ui((__e_acsl_mpz_struct const *)(__gen_e_acsl_mul)); + __gen_e_acsl_valid = __e_acsl_valid((void *)(s + 1 * 3), + __gen_e_acsl_size,(void *)s, + (void *)(& s)); + __e_acsl_assert(! __gen_e_acsl_valid,(char *)"Precondition",(char *)"f", + (char *)"!\\valid(s + (3 .. n + 1000))",5); + __gmpz_clear(__gen_e_acsl_); + __gmpz_clear(__gen_e_acsl_sizeof); + __gmpz_clear(__gen_e_acsl_n); + __gmpz_clear(__gen_e_acsl__2); + __gmpz_clear(__gen_e_acsl_add); + __gmpz_clear(__gen_e_acsl__3); + __gmpz_clear(__gen_e_acsl_sub); + __gmpz_clear(__gen_e_acsl_mul); + } + f(s,n); + __e_acsl_delete_block((void *)(& s)); + return; +} + + diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/gen_sizeof.c b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_sizeof.c new file mode 100644 index 0000000000000000000000000000000000000000..6f36aa7b510da1e343220883aa118a802555d01b --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_sizeof.c @@ -0,0 +1,17 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +int main(void) +{ + int __retres; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + int x = 0; + x ++; + /*@ assert sizeof(int) ≡ sizeof(x); */ + __e_acsl_assert(1,(char *)"Assertion",(char *)"main", + (char *)"sizeof(int) == sizeof(x)",8); + __retres = 0; + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/gen_stdout.c b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_stdout.c new file mode 100644 index 0000000000000000000000000000000000000000..fcd64e00041a1839c17ae318b316b012349491c6 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_stdout.c @@ -0,0 +1,56 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +void __e_acsl_globals_init(void) +{ + static char __e_acsl_already_run = 0; + if (! __e_acsl_already_run) { + __e_acsl_already_run = 1; + __e_acsl_store_block((void *)(& stdout),(size_t)8); + __e_acsl_full_init((void *)(& stdout)); + __e_acsl_store_block((void *)(& stdin),(size_t)8); + __e_acsl_full_init((void *)(& stdin)); + __e_acsl_store_block((void *)(& stderr),(size_t)8); + __e_acsl_full_init((void *)(& stderr)); + } + return; +} + +int main(void) +{ + int __retres; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + __e_acsl_globals_init(); + /*@ assert \valid(__fc_stderr); */ + { + int __gen_e_acsl_valid; + __gen_e_acsl_valid = __e_acsl_valid((void *)stderr,sizeof(FILE), + (void *)stderr,(void *)(& stderr)); + __e_acsl_assert(__gen_e_acsl_valid,(char *)"Assertion",(char *)"main", + (char *)"\\valid(__fc_stderr)",8); + } + /*@ assert \valid(__fc_stdin); */ + { + int __gen_e_acsl_valid_2; + __gen_e_acsl_valid_2 = __e_acsl_valid((void *)stdin,sizeof(FILE), + (void *)stdin,(void *)(& stdin)); + __e_acsl_assert(__gen_e_acsl_valid_2,(char *)"Assertion",(char *)"main", + (char *)"\\valid(__fc_stdin)",9); + } + /*@ assert \valid(__fc_stdout); */ + { + int __gen_e_acsl_valid_3; + __gen_e_acsl_valid_3 = __e_acsl_valid((void *)stdout,sizeof(FILE), + (void *)stdout,(void *)(& stdout)); + __e_acsl_assert(__gen_e_acsl_valid_3,(char *)"Assertion",(char *)"main", + (char *)"\\valid(__fc_stdout)",10); + } + __retres = 0; + __e_acsl_delete_block((void *)(& stdout)); + __e_acsl_delete_block((void *)(& stdin)); + __e_acsl_delete_block((void *)(& stderr)); + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/gen_valid.c b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_valid.c new file mode 100644 index 0000000000000000000000000000000000000000..26b8a81c4b8c33be94518b6af6c466bd69fbdb30 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_valid.c @@ -0,0 +1,524 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +extern int __e_acsl_sound_verdict; + +int *X; +int Z; +/*@ requires \valid(x); + ensures \valid(\result); */ +int *__gen_e_acsl_f(int *x); + +int *f(int *x) +{ + int *y; + __e_acsl_store_block((void *)(& y),(size_t)8); + /*@ assert ¬\valid(y); */ + { + int __gen_e_acsl_initialized; + int __gen_e_acsl_and; + __e_acsl_store_block((void *)(& x),(size_t)8); + __gen_e_acsl_initialized = __e_acsl_initialized((void *)(& y), + sizeof(int *)); + if (__gen_e_acsl_initialized) { + int __gen_e_acsl_valid; + __gen_e_acsl_valid = __e_acsl_valid((void *)y,sizeof(int),(void *)y, + (void *)(& y)); + __gen_e_acsl_and = __gen_e_acsl_valid; + } + else __gen_e_acsl_and = 0; + __e_acsl_assert(! __gen_e_acsl_and,(char *)"Assertion",(char *)"f", + (char *)"!\\valid(y)",13); + } + __e_acsl_full_init((void *)(& y)); + y = x; + /*@ assert \valid(x); */ + { + int __gen_e_acsl_valid_2; + __gen_e_acsl_valid_2 = __e_acsl_valid((void *)x,sizeof(int),(void *)x, + (void *)(& x)); + __e_acsl_assert(__gen_e_acsl_valid_2,(char *)"Assertion",(char *)"f", + (char *)"\\valid(x)",15); + } + __e_acsl_delete_block((void *)(& x)); + __e_acsl_delete_block((void *)(& y)); + return y; +} + +void g(void) +{ + int m; + int *u; + int **p; + __e_acsl_store_block((void *)(& p),(size_t)8); + __e_acsl_store_block((void *)(& u),(size_t)8); + __e_acsl_store_block((void *)(& m),(size_t)4); + __e_acsl_full_init((void *)(& p)); + p = & u; + __e_acsl_full_init((void *)(& u)); + u = & m; + __e_acsl_full_init((void *)(& m)); + m = 123; + /*@ assert \valid(*p); */ + { + int __gen_e_acsl_initialized; + int __gen_e_acsl_and_2; + __gen_e_acsl_initialized = __e_acsl_initialized((void *)p,sizeof(int *)); + if (__gen_e_acsl_initialized) { + int __gen_e_acsl_initialized_2; + int __gen_e_acsl_and; + int __gen_e_acsl_valid; + __gen_e_acsl_initialized_2 = __e_acsl_initialized((void *)(& p), + sizeof(int **)); + if (__gen_e_acsl_initialized_2) { + int __gen_e_acsl_valid_read; + __gen_e_acsl_valid_read = __e_acsl_valid_read((void *)p, + sizeof(int *), + (void *)p, + (void *)(& p)); + __gen_e_acsl_and = __gen_e_acsl_valid_read; + } + else __gen_e_acsl_and = 0; + __e_acsl_assert(__gen_e_acsl_and,(char *)"RTE",(char *)"g", + (char *)"mem_access: \\valid_read(p)",24); + __gen_e_acsl_valid = __e_acsl_valid((void *)*p,sizeof(int),(void *)*p, + (void *)p); + __gen_e_acsl_and_2 = __gen_e_acsl_valid; + } + else __gen_e_acsl_and_2 = 0; + __e_acsl_assert(__gen_e_acsl_and_2,(char *)"Assertion",(char *)"g", + (char *)"\\valid(*p)",24); + } + __e_acsl_delete_block((void *)(& p)); + __e_acsl_delete_block((void *)(& u)); + __e_acsl_delete_block((void *)(& m)); + return; +} + +/*@ requires \valid(x); + ensures \valid(\result); */ +int *__gen_e_acsl_f(int *x) +{ + int *__retres; + __e_acsl_store_block((void *)(& __retres),(size_t)8); + { + int __gen_e_acsl_valid; + __e_acsl_store_block((void *)(& x),(size_t)8); + __gen_e_acsl_valid = __e_acsl_valid((void *)x,sizeof(int),(void *)x, + (void *)(& x)); + __e_acsl_assert(__gen_e_acsl_valid,(char *)"Precondition",(char *)"f", + (char *)"\\valid(x)",9); + } + __retres = f(x); + { + int __gen_e_acsl_valid_2; + __gen_e_acsl_valid_2 = __e_acsl_valid((void *)__retres,sizeof(int), + (void *)__retres, + (void *)(& __retres)); + __e_acsl_assert(__gen_e_acsl_valid_2,(char *)"Postcondition",(char *)"f", + (char *)"\\valid(\\result)",10); + __e_acsl_delete_block((void *)(& x)); + __e_acsl_delete_block((void *)(& __retres)); + return __retres; + } +} + +void __e_acsl_globals_init(void) +{ + static char __e_acsl_already_run = 0; + if (! __e_acsl_already_run) { + __e_acsl_already_run = 1; + __e_acsl_store_block((void *)(& Z),(size_t)4); + __e_acsl_full_init((void *)(& Z)); + __e_acsl_store_block((void *)(& X),(size_t)8); + __e_acsl_full_init((void *)(& X)); + } + return; +} + +int main(void) +{ + int __retres; + int *a; + int *b; + int **c; + int ***d; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + __e_acsl_globals_init(); + __e_acsl_store_block((void *)(& d),(size_t)8); + __e_acsl_store_block((void *)(& c),(size_t)8); + __e_acsl_store_block((void *)(& b),(size_t)8); + __e_acsl_store_block((void *)(& a),(size_t)8); + int n = 0; + __e_acsl_store_block((void *)(& n),(size_t)4); + __e_acsl_full_init((void *)(& n)); + /*@ assert ¬\valid(a) ∧ ¬\valid(b) ∧ ¬\valid(X); */ + { + int __gen_e_acsl_initialized; + int __gen_e_acsl_and; + int __gen_e_acsl_and_3; + int __gen_e_acsl_and_4; + __gen_e_acsl_initialized = __e_acsl_initialized((void *)(& a), + sizeof(int *)); + if (__gen_e_acsl_initialized) { + int __gen_e_acsl_valid; + __gen_e_acsl_valid = __e_acsl_valid((void *)a,sizeof(int),(void *)a, + (void *)(& a)); + __gen_e_acsl_and = __gen_e_acsl_valid; + } + else __gen_e_acsl_and = 0; + if (! __gen_e_acsl_and) { + int __gen_e_acsl_initialized_2; + int __gen_e_acsl_and_2; + __gen_e_acsl_initialized_2 = __e_acsl_initialized((void *)(& b), + sizeof(int *)); + if (__gen_e_acsl_initialized_2) { + int __gen_e_acsl_valid_2; + __gen_e_acsl_valid_2 = __e_acsl_valid((void *)b,sizeof(int), + (void *)b,(void *)(& b)); + __gen_e_acsl_and_2 = __gen_e_acsl_valid_2; + } + else __gen_e_acsl_and_2 = 0; + __gen_e_acsl_and_3 = ! __gen_e_acsl_and_2; + } + else __gen_e_acsl_and_3 = 0; + if (__gen_e_acsl_and_3) { + int __gen_e_acsl_valid_3; + __gen_e_acsl_valid_3 = __e_acsl_valid((void *)X,sizeof(int),(void *)X, + (void *)(& X)); + __gen_e_acsl_and_4 = ! __gen_e_acsl_valid_3; + } + else __gen_e_acsl_and_4 = 0; + __e_acsl_assert(__gen_e_acsl_and_4,(char *)"Assertion",(char *)"main", + (char *)"!\\valid(a) && !\\valid(b) && !\\valid(X)",29); + } + __e_acsl_full_init((void *)(& a)); + a = (int *)malloc(sizeof(int)); + /*@ assert \valid(a) ∧ ¬\valid(b) ∧ ¬\valid(X); */ + { + int __gen_e_acsl_initialized_3; + int __gen_e_acsl_and_5; + int __gen_e_acsl_and_7; + int __gen_e_acsl_and_8; + __gen_e_acsl_initialized_3 = __e_acsl_initialized((void *)(& a), + sizeof(int *)); + if (__gen_e_acsl_initialized_3) { + int __gen_e_acsl_valid_4; + __gen_e_acsl_valid_4 = __e_acsl_valid((void *)a,sizeof(int),(void *)a, + (void *)(& a)); + __gen_e_acsl_and_5 = __gen_e_acsl_valid_4; + } + else __gen_e_acsl_and_5 = 0; + if (__gen_e_acsl_and_5) { + int __gen_e_acsl_initialized_4; + int __gen_e_acsl_and_6; + __gen_e_acsl_initialized_4 = __e_acsl_initialized((void *)(& b), + sizeof(int *)); + if (__gen_e_acsl_initialized_4) { + int __gen_e_acsl_valid_5; + __gen_e_acsl_valid_5 = __e_acsl_valid((void *)b,sizeof(int), + (void *)b,(void *)(& b)); + __gen_e_acsl_and_6 = __gen_e_acsl_valid_5; + } + else __gen_e_acsl_and_6 = 0; + __gen_e_acsl_and_7 = ! __gen_e_acsl_and_6; + } + else __gen_e_acsl_and_7 = 0; + if (__gen_e_acsl_and_7) { + int __gen_e_acsl_valid_6; + __gen_e_acsl_valid_6 = __e_acsl_valid((void *)X,sizeof(int),(void *)X, + (void *)(& X)); + __gen_e_acsl_and_8 = ! __gen_e_acsl_valid_6; + } + else __gen_e_acsl_and_8 = 0; + __e_acsl_assert(__gen_e_acsl_and_8,(char *)"Assertion",(char *)"main", + (char *)"\\valid(a) && !\\valid(b) && !\\valid(X)",31); + } + X = a; + /*@ assert \valid(a) ∧ ¬\valid(b) ∧ \valid(X); */ + { + int __gen_e_acsl_initialized_5; + int __gen_e_acsl_and_9; + int __gen_e_acsl_and_11; + int __gen_e_acsl_and_12; + __gen_e_acsl_initialized_5 = __e_acsl_initialized((void *)(& a), + sizeof(int *)); + if (__gen_e_acsl_initialized_5) { + int __gen_e_acsl_valid_7; + __gen_e_acsl_valid_7 = __e_acsl_valid((void *)a,sizeof(int),(void *)a, + (void *)(& a)); + __gen_e_acsl_and_9 = __gen_e_acsl_valid_7; + } + else __gen_e_acsl_and_9 = 0; + if (__gen_e_acsl_and_9) { + int __gen_e_acsl_initialized_6; + int __gen_e_acsl_and_10; + __gen_e_acsl_initialized_6 = __e_acsl_initialized((void *)(& b), + sizeof(int *)); + if (__gen_e_acsl_initialized_6) { + int __gen_e_acsl_valid_8; + __gen_e_acsl_valid_8 = __e_acsl_valid((void *)b,sizeof(int), + (void *)b,(void *)(& b)); + __gen_e_acsl_and_10 = __gen_e_acsl_valid_8; + } + else __gen_e_acsl_and_10 = 0; + __gen_e_acsl_and_11 = ! __gen_e_acsl_and_10; + } + else __gen_e_acsl_and_11 = 0; + if (__gen_e_acsl_and_11) { + int __gen_e_acsl_valid_9; + __gen_e_acsl_valid_9 = __e_acsl_valid((void *)X,sizeof(int),(void *)X, + (void *)(& X)); + __gen_e_acsl_and_12 = __gen_e_acsl_valid_9; + } + else __gen_e_acsl_and_12 = 0; + __e_acsl_assert(__gen_e_acsl_and_12,(char *)"Assertion",(char *)"main", + (char *)"\\valid(a) && !\\valid(b) && \\valid(X)",33); + } + __e_acsl_full_init((void *)(& b)); + b = __gen_e_acsl_f(& n); + /*@ assert \valid(a) ∧ \valid(b) ∧ \valid(X); */ + { + int __gen_e_acsl_initialized_7; + int __gen_e_acsl_and_13; + int __gen_e_acsl_and_15; + int __gen_e_acsl_and_16; + __gen_e_acsl_initialized_7 = __e_acsl_initialized((void *)(& a), + sizeof(int *)); + if (__gen_e_acsl_initialized_7) { + int __gen_e_acsl_valid_10; + __gen_e_acsl_valid_10 = __e_acsl_valid((void *)a,sizeof(int),(void *)a, + (void *)(& a)); + __gen_e_acsl_and_13 = __gen_e_acsl_valid_10; + } + else __gen_e_acsl_and_13 = 0; + if (__gen_e_acsl_and_13) { + int __gen_e_acsl_initialized_8; + int __gen_e_acsl_and_14; + __gen_e_acsl_initialized_8 = __e_acsl_initialized((void *)(& b), + sizeof(int *)); + if (__gen_e_acsl_initialized_8) { + int __gen_e_acsl_valid_11; + __gen_e_acsl_valid_11 = __e_acsl_valid((void *)b,sizeof(int), + (void *)b,(void *)(& b)); + __gen_e_acsl_and_14 = __gen_e_acsl_valid_11; + } + else __gen_e_acsl_and_14 = 0; + __gen_e_acsl_and_15 = __gen_e_acsl_and_14; + } + else __gen_e_acsl_and_15 = 0; + if (__gen_e_acsl_and_15) { + int __gen_e_acsl_valid_12; + __gen_e_acsl_valid_12 = __e_acsl_valid((void *)X,sizeof(int),(void *)X, + (void *)(& X)); + __gen_e_acsl_and_16 = __gen_e_acsl_valid_12; + } + else __gen_e_acsl_and_16 = 0; + __e_acsl_assert(__gen_e_acsl_and_16,(char *)"Assertion",(char *)"main", + (char *)"\\valid(a) && \\valid(b) && \\valid(X)",35); + } + X = b; + /*@ assert \valid(a) ∧ \valid(b) ∧ \valid(X); */ + { + int __gen_e_acsl_initialized_9; + int __gen_e_acsl_and_17; + int __gen_e_acsl_and_19; + int __gen_e_acsl_and_20; + __gen_e_acsl_initialized_9 = __e_acsl_initialized((void *)(& a), + sizeof(int *)); + if (__gen_e_acsl_initialized_9) { + int __gen_e_acsl_valid_13; + __gen_e_acsl_valid_13 = __e_acsl_valid((void *)a,sizeof(int),(void *)a, + (void *)(& a)); + __gen_e_acsl_and_17 = __gen_e_acsl_valid_13; + } + else __gen_e_acsl_and_17 = 0; + if (__gen_e_acsl_and_17) { + int __gen_e_acsl_initialized_10; + int __gen_e_acsl_and_18; + __gen_e_acsl_initialized_10 = __e_acsl_initialized((void *)(& b), + sizeof(int *)); + if (__gen_e_acsl_initialized_10) { + int __gen_e_acsl_valid_14; + __gen_e_acsl_valid_14 = __e_acsl_valid((void *)b,sizeof(int), + (void *)b,(void *)(& b)); + __gen_e_acsl_and_18 = __gen_e_acsl_valid_14; + } + else __gen_e_acsl_and_18 = 0; + __gen_e_acsl_and_19 = __gen_e_acsl_and_18; + } + else __gen_e_acsl_and_19 = 0; + if (__gen_e_acsl_and_19) { + int __gen_e_acsl_valid_15; + __gen_e_acsl_valid_15 = __e_acsl_valid((void *)X,sizeof(int),(void *)X, + (void *)(& X)); + __gen_e_acsl_and_20 = __gen_e_acsl_valid_15; + } + else __gen_e_acsl_and_20 = 0; + __e_acsl_assert(__gen_e_acsl_and_20,(char *)"Assertion",(char *)"main", + (char *)"\\valid(a) && \\valid(b) && \\valid(X)",37); + } + __e_acsl_full_init((void *)(& c)); + c = & a; + __e_acsl_full_init((void *)(& d)); + d = & c; + /*@ assert \valid(*c); */ + { + int __gen_e_acsl_initialized_11; + int __gen_e_acsl_and_22; + __gen_e_acsl_initialized_11 = __e_acsl_initialized((void *)c, + sizeof(int *)); + if (__gen_e_acsl_initialized_11) { + int __gen_e_acsl_initialized_12; + int __gen_e_acsl_and_21; + int __gen_e_acsl_valid_16; + __gen_e_acsl_initialized_12 = __e_acsl_initialized((void *)(& c), + sizeof(int **)); + if (__gen_e_acsl_initialized_12) { + int __gen_e_acsl_valid_read; + __gen_e_acsl_valid_read = __e_acsl_valid_read((void *)c, + sizeof(int *), + (void *)c, + (void *)(& c)); + __gen_e_acsl_and_21 = __gen_e_acsl_valid_read; + } + else __gen_e_acsl_and_21 = 0; + __e_acsl_assert(__gen_e_acsl_and_21,(char *)"RTE",(char *)"main", + (char *)"mem_access: \\valid_read(c)",40); + __gen_e_acsl_valid_16 = __e_acsl_valid((void *)*c,sizeof(int), + (void *)*c,(void *)c); + __gen_e_acsl_and_22 = __gen_e_acsl_valid_16; + } + else __gen_e_acsl_and_22 = 0; + __e_acsl_assert(__gen_e_acsl_and_22,(char *)"Assertion",(char *)"main", + (char *)"\\valid(*c)",40); + } + /*@ assert \valid(*(*d)); */ + { + int __gen_e_acsl_valid_read_2; + int __gen_e_acsl_initialized_13; + int __gen_e_acsl_and_26; + __gen_e_acsl_valid_read_2 = __e_acsl_valid_read((void *)d,sizeof(int **), + (void *)d,(void *)(& d)); + __e_acsl_assert(__gen_e_acsl_valid_read_2,(char *)"RTE",(char *)"main", + (char *)"mem_access: \\valid_read(d)",41); + __gen_e_acsl_initialized_13 = __e_acsl_initialized((void *)*d, + sizeof(int *)); + if (__gen_e_acsl_initialized_13) { + int __gen_e_acsl_initialized_14; + int __gen_e_acsl_and_24; + int __gen_e_acsl_initialized_16; + int __gen_e_acsl_and_25; + int __gen_e_acsl_valid_17; + __gen_e_acsl_initialized_14 = __e_acsl_initialized((void *)d, + sizeof(int **)); + if (__gen_e_acsl_initialized_14) { + int __gen_e_acsl_initialized_15; + int __gen_e_acsl_and_23; + int __gen_e_acsl_valid_read_4; + __gen_e_acsl_initialized_15 = __e_acsl_initialized((void *)(& d), + sizeof(int ***)); + if (__gen_e_acsl_initialized_15) { + int __gen_e_acsl_valid_read_3; + __gen_e_acsl_valid_read_3 = __e_acsl_valid_read((void *)d, + sizeof(int **), + (void *)d, + (void *)(& d)); + __gen_e_acsl_and_23 = __gen_e_acsl_valid_read_3; + } + else __gen_e_acsl_and_23 = 0; + __e_acsl_assert(__gen_e_acsl_and_23,(char *)"RTE",(char *)"main", + (char *)"mem_access: \\valid_read(d)",41); + __gen_e_acsl_valid_read_4 = __e_acsl_valid_read((void *)*d, + sizeof(int *), + (void *)*d,(void *)d); + __gen_e_acsl_and_24 = __gen_e_acsl_valid_read_4; + } + else __gen_e_acsl_and_24 = 0; + __e_acsl_assert(__gen_e_acsl_and_24,(char *)"RTE",(char *)"main", + (char *)"mem_access: \\valid_read(*d)",41); + __gen_e_acsl_initialized_16 = __e_acsl_initialized((void *)(& d), + sizeof(int ***)); + if (__gen_e_acsl_initialized_16) { + int __gen_e_acsl_valid_read_5; + __gen_e_acsl_valid_read_5 = __e_acsl_valid_read((void *)d, + sizeof(int **), + (void *)d, + (void *)(& d)); + __gen_e_acsl_and_25 = __gen_e_acsl_valid_read_5; + } + else __gen_e_acsl_and_25 = 0; + __e_acsl_assert(__gen_e_acsl_and_25,(char *)"RTE",(char *)"main", + (char *)"mem_access: \\valid_read(d)",41); + __gen_e_acsl_valid_17 = __e_acsl_valid((void *)*(*d),sizeof(int), + (void *)*(*d),(void *)*d); + __gen_e_acsl_and_26 = __gen_e_acsl_valid_17; + } + else __gen_e_acsl_and_26 = 0; + __e_acsl_assert(__gen_e_acsl_and_26,(char *)"Assertion",(char *)"main", + (char *)"\\valid(*(*d))",41); + } + free((void *)a); + /*@ assert ¬\valid(a) ∧ \valid(b) ∧ \valid(X); */ + { + int __gen_e_acsl_initialized_17; + int __gen_e_acsl_and_27; + int __gen_e_acsl_and_29; + int __gen_e_acsl_and_30; + __gen_e_acsl_initialized_17 = __e_acsl_initialized((void *)(& a), + sizeof(int *)); + if (__gen_e_acsl_initialized_17) { + int __gen_e_acsl_valid_18; + /*@ assert Eva: dangling_pointer: ¬\dangling(&a); */ + __gen_e_acsl_valid_18 = __e_acsl_valid((void *)a,sizeof(int),(void *)a, + (void *)(& a)); + __gen_e_acsl_and_27 = __gen_e_acsl_valid_18; + } + else __gen_e_acsl_and_27 = 0; + if (! __gen_e_acsl_and_27) { + int __gen_e_acsl_initialized_18; + int __gen_e_acsl_and_28; + __gen_e_acsl_initialized_18 = __e_acsl_initialized((void *)(& b), + sizeof(int *)); + if (__gen_e_acsl_initialized_18) { + int __gen_e_acsl_valid_19; + __gen_e_acsl_valid_19 = __e_acsl_valid((void *)b,sizeof(int), + (void *)b,(void *)(& b)); + __gen_e_acsl_and_28 = __gen_e_acsl_valid_19; + } + else __gen_e_acsl_and_28 = 0; + __gen_e_acsl_and_29 = __gen_e_acsl_and_28; + } + else __gen_e_acsl_and_29 = 0; + if (__gen_e_acsl_and_29) { + int __gen_e_acsl_valid_20; + __gen_e_acsl_valid_20 = __e_acsl_valid((void *)X,sizeof(int),(void *)X, + (void *)(& X)); + __gen_e_acsl_and_30 = __gen_e_acsl_valid_20; + } + else __gen_e_acsl_and_30 = 0; + __e_acsl_assert(__gen_e_acsl_and_30,(char *)"Assertion",(char *)"main", + (char *)"!\\valid(a) && \\valid(b) && \\valid(X)",43); + } + /*@ assert \valid(&Z); */ + { + int __gen_e_acsl_valid_21; + __gen_e_acsl_valid_21 = __e_acsl_valid((void *)(& Z),sizeof(int), + (void *)(& Z),(void *)0); + __e_acsl_assert(__gen_e_acsl_valid_21,(char *)"Assertion",(char *)"main", + (char *)"\\valid(&Z)",44); + } + g(); + __retres = 0; + __e_acsl_delete_block((void *)(& Z)); + __e_acsl_delete_block((void *)(& X)); + __e_acsl_delete_block((void *)(& n)); + __e_acsl_delete_block((void *)(& d)); + __e_acsl_delete_block((void *)(& c)); + __e_acsl_delete_block((void *)(& b)); + __e_acsl_delete_block((void *)(& a)); + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/gen_valid_alias.c b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_valid_alias.c new file mode 100644 index 0000000000000000000000000000000000000000..e3bdcf3e194fdb170d6e962d167f34218ab0f080 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_valid_alias.c @@ -0,0 +1,142 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +int main(void) +{ + int __retres; + int *a; + int *b; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + __e_acsl_store_block((void *)(& b),(size_t)8); + __e_acsl_store_block((void *)(& a),(size_t)8); + int n = 0; + /*@ assert ¬\valid(a) ∧ ¬\valid(b); */ + { + int __gen_e_acsl_initialized; + int __gen_e_acsl_and; + int __gen_e_acsl_and_3; + __gen_e_acsl_initialized = __e_acsl_initialized((void *)(& a), + sizeof(int *)); + if (__gen_e_acsl_initialized) { + int __gen_e_acsl_valid; + __gen_e_acsl_valid = __e_acsl_valid((void *)a,sizeof(int),(void *)a, + (void *)(& a)); + __gen_e_acsl_and = __gen_e_acsl_valid; + } + else __gen_e_acsl_and = 0; + if (! __gen_e_acsl_and) { + int __gen_e_acsl_initialized_2; + int __gen_e_acsl_and_2; + __gen_e_acsl_initialized_2 = __e_acsl_initialized((void *)(& b), + sizeof(int *)); + if (__gen_e_acsl_initialized_2) { + int __gen_e_acsl_valid_2; + __gen_e_acsl_valid_2 = __e_acsl_valid((void *)b,sizeof(int), + (void *)b,(void *)(& b)); + __gen_e_acsl_and_2 = __gen_e_acsl_valid_2; + } + else __gen_e_acsl_and_2 = 0; + __gen_e_acsl_and_3 = ! __gen_e_acsl_and_2; + } + else __gen_e_acsl_and_3 = 0; + __e_acsl_assert(__gen_e_acsl_and_3,(char *)"Assertion",(char *)"main", + (char *)"!\\valid(a) && !\\valid(b)",9); + } + __e_acsl_full_init((void *)(& a)); + a = (int *)malloc(sizeof(int)); + __e_acsl_initialize((void *)a,sizeof(int)); + *a = n; + __e_acsl_full_init((void *)(& b)); + b = a; + /*@ assert \valid(a) ∧ \valid(b); */ + { + int __gen_e_acsl_initialized_3; + int __gen_e_acsl_and_4; + int __gen_e_acsl_and_6; + __gen_e_acsl_initialized_3 = __e_acsl_initialized((void *)(& a), + sizeof(int *)); + if (__gen_e_acsl_initialized_3) { + int __gen_e_acsl_valid_3; + __gen_e_acsl_valid_3 = __e_acsl_valid((void *)a,sizeof(int),(void *)a, + (void *)(& a)); + __gen_e_acsl_and_4 = __gen_e_acsl_valid_3; + } + else __gen_e_acsl_and_4 = 0; + if (__gen_e_acsl_and_4) { + int __gen_e_acsl_initialized_4; + int __gen_e_acsl_and_5; + __gen_e_acsl_initialized_4 = __e_acsl_initialized((void *)(& b), + sizeof(int *)); + if (__gen_e_acsl_initialized_4) { + int __gen_e_acsl_valid_4; + __gen_e_acsl_valid_4 = __e_acsl_valid((void *)b,sizeof(int), + (void *)b,(void *)(& b)); + __gen_e_acsl_and_5 = __gen_e_acsl_valid_4; + } + else __gen_e_acsl_and_5 = 0; + __gen_e_acsl_and_6 = __gen_e_acsl_and_5; + } + else __gen_e_acsl_and_6 = 0; + __e_acsl_assert(__gen_e_acsl_and_6,(char *)"Assertion",(char *)"main", + (char *)"\\valid(a) && \\valid(b)",13); + } + /*@ assert *b ≡ n; */ + { + int __gen_e_acsl_initialized_5; + int __gen_e_acsl_and_7; + __gen_e_acsl_initialized_5 = __e_acsl_initialized((void *)(& b), + sizeof(int *)); + if (__gen_e_acsl_initialized_5) { + int __gen_e_acsl_valid_read; + __gen_e_acsl_valid_read = __e_acsl_valid_read((void *)b,sizeof(int), + (void *)b,(void *)(& b)); + __gen_e_acsl_and_7 = __gen_e_acsl_valid_read; + } + else __gen_e_acsl_and_7 = 0; + __e_acsl_assert(__gen_e_acsl_and_7,(char *)"RTE",(char *)"main", + (char *)"mem_access: \\valid_read(b)",14); + __e_acsl_assert(*b == n,(char *)"Assertion",(char *)"main", + (char *)"*b == n",14); + } + free((void *)b); + /*@ assert ¬\valid(a) ∧ ¬\valid(b); */ + { + int __gen_e_acsl_initialized_6; + int __gen_e_acsl_and_8; + int __gen_e_acsl_and_10; + __gen_e_acsl_initialized_6 = __e_acsl_initialized((void *)(& a), + sizeof(int *)); + if (__gen_e_acsl_initialized_6) { + int __gen_e_acsl_valid_5; + /*@ assert Eva: dangling_pointer: ¬\dangling(&a); */ + __gen_e_acsl_valid_5 = __e_acsl_valid((void *)a,sizeof(int),(void *)a, + (void *)(& a)); + __gen_e_acsl_and_8 = __gen_e_acsl_valid_5; + } + else __gen_e_acsl_and_8 = 0; + if (! __gen_e_acsl_and_8) { + int __gen_e_acsl_initialized_7; + int __gen_e_acsl_and_9; + __gen_e_acsl_initialized_7 = __e_acsl_initialized((void *)(& b), + sizeof(int *)); + if (__gen_e_acsl_initialized_7) { + int __gen_e_acsl_valid_6; + __gen_e_acsl_valid_6 = __e_acsl_valid((void *)b,sizeof(int), + (void *)b,(void *)(& b)); + __gen_e_acsl_and_9 = __gen_e_acsl_valid_6; + } + else __gen_e_acsl_and_9 = 0; + __gen_e_acsl_and_10 = ! __gen_e_acsl_and_9; + } + else __gen_e_acsl_and_10 = 0; + __e_acsl_assert(__gen_e_acsl_and_10,(char *)"Assertion",(char *)"main", + (char *)"!\\valid(a) && !\\valid(b)",16); + } + __retres = 0; + __e_acsl_delete_block((void *)(& b)); + __e_acsl_delete_block((void *)(& a)); + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/gen_valid_in_contract.c b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_valid_in_contract.c new file mode 100644 index 0000000000000000000000000000000000000000..6395c435c6c455b5481fa24062beb73f16574ee8 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_valid_in_contract.c @@ -0,0 +1,126 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +extern int __e_acsl_sound_verdict; + +struct list { + int element ; + struct list *next ; +}; +/*@ behavior B1: + assumes l ≡ \null; + ensures \result ≡ \old(l); + + behavior B2: + assumes ¬\valid(l) ∨ ¬\valid(l->next); + ensures \result ≡ \old(l); + */ +struct list *__gen_e_acsl_f(struct list *l); + +struct list *f(struct list *l) +{ + struct list *__retres; + __e_acsl_store_block((void *)(& __retres),(size_t)8); + __e_acsl_store_block((void *)(& l),(size_t)8); + if (l == (struct list *)0) { + __e_acsl_full_init((void *)(& __retres)); + __retres = l; + goto return_label; + } + if (l->next == (struct list *)0) { + __e_acsl_full_init((void *)(& __retres)); + __retres = l; + goto return_label; + } + __e_acsl_full_init((void *)(& __retres)); + __retres = (struct list *)0; + return_label: + { + __e_acsl_delete_block((void *)(& l)); + __e_acsl_delete_block((void *)(& __retres)); + return __retres; + } +} + +int main(void) +{ + int __retres; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + __gen_e_acsl_f((struct list *)0); + __retres = 0; + __e_acsl_memory_clean(); + return __retres; +} + +/*@ behavior B1: + assumes l ≡ \null; + ensures \result ≡ \old(l); + + behavior B2: + assumes ¬\valid(l) ∨ ¬\valid(l->next); + ensures \result ≡ \old(l); + */ +struct list *__gen_e_acsl_f(struct list *l) +{ + struct list *__gen_e_acsl_at_4; + int __gen_e_acsl_at_3; + struct list *__gen_e_acsl_at_2; + int __gen_e_acsl_at; + struct list *__retres; + __e_acsl_store_block((void *)(& __retres),(size_t)8); + __gen_e_acsl_at_4 = l; + { + int __gen_e_acsl_valid; + int __gen_e_acsl_or; + __gen_e_acsl_valid = __e_acsl_valid((void *)l,sizeof(struct list), + (void *)l,(void *)(& l)); + if (! __gen_e_acsl_valid) __gen_e_acsl_or = 1; + else { + int __gen_e_acsl_initialized; + int __gen_e_acsl_and; + __gen_e_acsl_initialized = __e_acsl_initialized((void *)(& l->next), + sizeof(struct list *)); + if (__gen_e_acsl_initialized) { + int __gen_e_acsl_valid_read; + int __gen_e_acsl_valid_2; + __gen_e_acsl_valid_read = __e_acsl_valid_read((void *)(& l->next), + sizeof(struct list *), + (void *)(& l->next), + (void *)0); + __e_acsl_assert(__gen_e_acsl_valid_read,(char *)"RTE",(char *)"f", + (char *)"mem_access: \\valid_read(&l->next)",17); + __gen_e_acsl_valid_2 = __e_acsl_valid((void *)l->next, + sizeof(struct list), + (void *)l->next, + (void *)(& l->next)); + __gen_e_acsl_and = __gen_e_acsl_valid_2; + } + else __gen_e_acsl_and = 0; + __gen_e_acsl_or = ! __gen_e_acsl_and; + } + __gen_e_acsl_at_3 = __gen_e_acsl_or; + } + __gen_e_acsl_at_2 = l; + __gen_e_acsl_at = l == (struct list *)0; + __e_acsl_store_block((void *)(& l),(size_t)8); + __retres = f(l); + { + int __gen_e_acsl_implies; + int __gen_e_acsl_implies_2; + if (! __gen_e_acsl_at) __gen_e_acsl_implies = 1; + else __gen_e_acsl_implies = __retres == __gen_e_acsl_at_2; + __e_acsl_assert(__gen_e_acsl_implies,(char *)"Postcondition",(char *)"f", + (char *)"\\old(l == \\null) ==> \\result == \\old(l)",15); + if (! __gen_e_acsl_at_3) __gen_e_acsl_implies_2 = 1; + else __gen_e_acsl_implies_2 = __retres == __gen_e_acsl_at_4; + __e_acsl_assert(__gen_e_acsl_implies_2,(char *)"Postcondition", + (char *)"f", + (char *)"\\old(!\\valid{Here}(l) || !\\valid{Here}(l->next)) ==> \\result == \\old(l)", + 18); + __e_acsl_delete_block((void *)(& l)); + __e_acsl_delete_block((void *)(& __retres)); + return __retres; + } +} + + diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/gen_vector.c b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_vector.c new file mode 100644 index 0000000000000000000000000000000000000000..eff00e76dd7c742a6409d3a95ef3c48ec880b7f4 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_vector.c @@ -0,0 +1,114 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +int LAST; +int *new_inversed(int len, int *v) +{ + int i; + int *p; + __e_acsl_store_block((void *)(& p),(size_t)8); + /*@ assert + \valid(v) ∧ \offset(v) + len * sizeof(int) ≤ \block_length(v); + */ + { + int __gen_e_acsl_valid; + int __gen_e_acsl_and; + __e_acsl_store_block((void *)(& v),(size_t)8); + __gen_e_acsl_valid = __e_acsl_valid((void *)v,sizeof(int),(void *)v, + (void *)(& v)); + if (__gen_e_acsl_valid) { + unsigned long __gen_e_acsl_offset; + __e_acsl_mpz_t __gen_e_acsl_offset_2; + __e_acsl_mpz_t __gen_e_acsl_; + __e_acsl_mpz_t __gen_e_acsl_add; + unsigned long __gen_e_acsl_block_length; + __e_acsl_mpz_t __gen_e_acsl_block_length_2; + int __gen_e_acsl_le; + __gen_e_acsl_offset = __e_acsl_offset((void *)v); + __gmpz_init_set_ui(__gen_e_acsl_offset_2,__gen_e_acsl_offset); + __gmpz_init_set_si(__gen_e_acsl_,len * 4L); + __gmpz_init(__gen_e_acsl_add); + __gmpz_add(__gen_e_acsl_add, + (__e_acsl_mpz_struct const *)(__gen_e_acsl_offset_2), + (__e_acsl_mpz_struct const *)(__gen_e_acsl_)); + __gen_e_acsl_block_length = __e_acsl_block_length((void *)v); + __gmpz_init_set_ui(__gen_e_acsl_block_length_2, + __gen_e_acsl_block_length); + __gen_e_acsl_le = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_add), + (__e_acsl_mpz_struct const *)(__gen_e_acsl_block_length_2)); + __gen_e_acsl_and = __gen_e_acsl_le <= 0; + __gmpz_clear(__gen_e_acsl_offset_2); + __gmpz_clear(__gen_e_acsl_); + __gmpz_clear(__gen_e_acsl_add); + __gmpz_clear(__gen_e_acsl_block_length_2); + } + else __gen_e_acsl_and = 0; + __e_acsl_assert(__gen_e_acsl_and,(char *)"Assertion", + (char *)"new_inversed", + (char *)"\\valid(v) && \\offset(v) + len * sizeof(int) <= \\block_length(v)", + 11); + } + __e_acsl_full_init((void *)(& p)); + p = (int *)malloc(sizeof(int) * (unsigned long)len); + i = 0; + while (i < len) { + __e_acsl_initialize((void *)(p + i),sizeof(int)); + *(p + i) = *(v + ((len - i) - 1)); + i ++; + } + __e_acsl_delete_block((void *)(& v)); + __e_acsl_delete_block((void *)(& p)); + return p; +} + +int main(void) +{ + int __retres; + int *v2; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + __e_acsl_store_block((void *)(& v2),(size_t)8); + int x = 3; + int v1[3] = {1, 2, x}; + __e_acsl_store_block((void *)(v1),(size_t)12); + __e_acsl_full_init((void *)(& v1)); + /*@ assert \valid(&v1[2]); */ + { + int __gen_e_acsl_valid; + __gen_e_acsl_valid = __e_acsl_valid((void *)(& v1[2]),sizeof(int), + (void *)(& v1[2]),(void *)0); + __e_acsl_assert(__gen_e_acsl_valid,(char *)"Assertion",(char *)"main", + (char *)"\\valid(&v1[2])",21); + } + LAST = v1[2]; + /*@ assert \initialized(&v1[2]); */ + { + int __gen_e_acsl_initialized; + __gen_e_acsl_initialized = __e_acsl_initialized((void *)(& v1[2]), + sizeof(int)); + __e_acsl_assert(__gen_e_acsl_initialized,(char *)"Assertion", + (char *)"main",(char *)"\\initialized(&v1[2])",23); + } + __e_acsl_full_init((void *)(& v2)); + v2 = new_inversed(3,v1); + /*@ assert Eva: initialization: \initialized(v2 + 2); */ + LAST = *(v2 + 2); + /*@ assert \initialized(v2 + 2); */ + { + int __gen_e_acsl_initialized_2; + __gen_e_acsl_initialized_2 = __e_acsl_initialized((void *)(v2 + 2), + sizeof(int)); + __e_acsl_assert(__gen_e_acsl_initialized_2,(char *)"Assertion", + (char *)"main",(char *)"\\initialized(v2 + 2)",26); + } + /*@ assert LAST ≡ 1; */ + __e_acsl_assert(LAST == 1,(char *)"Assertion",(char *)"main", + (char *)"LAST == 1",27); + free((void *)v2); + __retres = 0; + __e_acsl_delete_block((void *)(& v2)); + __e_acsl_delete_block((void *)(v1)); + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/gen_vla.c b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_vla.c new file mode 100644 index 0000000000000000000000000000000000000000..54dbd492180462c95fbba96043e899fa61b5f85a --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_vla.c @@ -0,0 +1,74 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +int LEN = 10; +/*@ assigns \nothing; + frees p; */ + __attribute__((__FC_BUILTIN__)) void __e_acsl_delete_block(void *p); + +/* compiler builtin: + __attribute__((__FC_BUILTIN__)) void *__builtin_alloca(unsigned long size); */ +int main(int argc, char **argv) +{ + int __retres; + unsigned long __lengthof_arr; + int i; + __e_acsl_memory_init(& argc,& argv,(size_t)8); + /*@ assert alloca_bounds: 0 < sizeof(int) * LEN ≤ 18446744073709551615; + */ + { + int __gen_e_acsl_and; + if (0L < 4L * LEN) { + __e_acsl_mpz_t __gen_e_acsl_; + __e_acsl_mpz_t __gen_e_acsl__2; + int __gen_e_acsl_le; + __gmpz_init_set_si(__gen_e_acsl_,4L * LEN); + __gmpz_init_set_ui(__gen_e_acsl__2,18446744073709551615UL); + __gen_e_acsl_le = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_), + (__e_acsl_mpz_struct const *)(__gen_e_acsl__2)); + __gen_e_acsl_and = __gen_e_acsl_le <= 0; + __gmpz_clear(__gen_e_acsl_); + __gmpz_clear(__gen_e_acsl__2); + } + else __gen_e_acsl_and = 0; + __e_acsl_assert(__gen_e_acsl_and,(char *)"Assertion",(char *)"main", + (char *)"alloca_bounds: 0 < sizeof(int) * LEN <= 18446744073709551615", + 8); + } + __lengthof_arr = (unsigned long)LEN; + int *arr = __builtin_alloca(sizeof(int) * __lengthof_arr); + __e_acsl_store_block((void *)arr,sizeof(int) * __lengthof_arr); + __e_acsl_store_block((void *)(& arr),(size_t)8); + __e_acsl_full_init((void *)(& arr)); + i = 0; + while (i <= LEN) { + if (i < LEN) { + /*@ assert \valid(arr + i); */ + { + int __gen_e_acsl_valid; + __gen_e_acsl_valid = __e_acsl_valid((void *)(arr + i),sizeof(int), + (void *)arr,(void *)(& arr)); + __e_acsl_assert(__gen_e_acsl_valid,(char *)"Assertion", + (char *)"main",(char *)"\\valid(arr + i)",12); + } + } + else { + /*@ assert ¬\valid(arr + i); */ + { + int __gen_e_acsl_valid_2; + __gen_e_acsl_valid_2 = __e_acsl_valid((void *)(arr + i),sizeof(int), + (void *)arr,(void *)(& arr)); + __e_acsl_assert(! __gen_e_acsl_valid_2,(char *)"Assertion", + (char *)"main",(char *)"!\\valid(arr + i)",14); + } + } + i ++; + } + __retres = 0; + __e_acsl_delete_block((void *)arr); + __e_acsl_delete_block((void *)(& arr)); + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/goto.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_ci/goto.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..efd026311297e55d8fefb674326118e6ece88624 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/goto.res.oracle @@ -0,0 +1,2 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/hidden_malloc.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_ci/hidden_malloc.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..c136f7aec42d0af2d20d219eb393b8605ff89ec2 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/hidden_malloc.res.oracle @@ -0,0 +1,9 @@ +[kernel:typing:implicit-function-declaration] tests/memory/hidden_malloc.c:11: Warning: + Calling undeclared function realpath. Old style K&R code? +[e-acsl] beginning translation. +[kernel:annot:missing-spec] tests/memory/hidden_malloc.c:11: Warning: + Neither code nor specification for function realpath, generating default assigns from the prototype +[e-acsl] translation done in project "e-acsl". +[eva:invalid-assigns] tests/memory/hidden_malloc.c:11: + Completely invalid destination for assigns clause *((char *)x_1 + (0 ..)). + Ignoring. diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/init.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_ci/init.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..efd026311297e55d8fefb674326118e6ece88624 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/init.res.oracle @@ -0,0 +1,2 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/init_function.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_ci/init_function.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..efd026311297e55d8fefb674326118e6ece88624 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/init_function.res.oracle @@ -0,0 +1,2 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/initialized.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_ci/initialized.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..2a7b78f4dd4b3adebdb12137fccc10171f974f8f --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/initialized.res.oracle @@ -0,0 +1,7 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". +[eva:alarm] tests/memory/initialized.c:84: Warning: + assertion got status unknown. +[eva:alarm] tests/memory/initialized.c:84: Warning: + accessing left-value that contains escaping addresses. + assert ¬\dangling(&p); diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/literal_string.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_ci/literal_string.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..efd026311297e55d8fefb674326118e6ece88624 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/literal_string.res.oracle @@ -0,0 +1,2 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/local_goto.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_ci/local_goto.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..9811cdbf49f1324c0f4cffd3aed7d450deac04cb --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/local_goto.res.oracle @@ -0,0 +1,4 @@ +[e-acsl] beginning translation. +[kernel:annot:missing-spec] FRAMAC_SHARE/libc/stdio.h:169: Warning: + Neither code nor specification for function printf, generating default assigns from the prototype +[e-acsl] translation done in project "e-acsl". diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/local_init.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_ci/local_init.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..e5104fb7e863db59eeb9c0c2a6e355a0e5b6a167 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/local_init.res.oracle @@ -0,0 +1,4 @@ +[eva:alarm] tests/memory/local_init.c:11: Warning: + out of bounds read. assert \valid_read(p); +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/local_var.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_ci/local_var.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..efd026311297e55d8fefb674326118e6ece88624 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/local_var.res.oracle @@ -0,0 +1,2 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/mainargs.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_ci/mainargs.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..9eb9554ffef0f06f41d3400d0b0fd721a00bc77a --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/mainargs.res.oracle @@ -0,0 +1,43 @@ +[e-acsl] beginning translation. +[e-acsl] Warning: annotating undefined function `strlen': + the generated program may miss memory instrumentation + if there are memory-related annotations. +[e-acsl] FRAMAC_SHARE/libc/string.h:125: Warning: + E-ACSL construct `logic functions with labels' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/string.h:125: Warning: + E-ACSL construct `assigns clause in behavior' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/string.h:127: Warning: + E-ACSL construct `logic functions performing read accesses' + is not yet supported. + Ignoring annotation. +[e-acsl] translation done in project "e-acsl". +[eva:alarm] tests/memory/mainargs.c:12: Warning: assertion got status unknown. +[eva:alarm] tests/memory/mainargs.c:12: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/memory/mainargs.c:13: Warning: assertion got status unknown. +[eva:alarm] tests/memory/mainargs.c:13: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/memory/mainargs.c:15: Warning: assertion got status unknown. +[eva:alarm] tests/memory/mainargs.c:15: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/memory/mainargs.c:15: Warning: + out of bounds read. assert \valid_read(argv + argc); +[eva:alarm] tests/memory/mainargs.c:16: Warning: assertion got status unknown. +[eva:alarm] tests/memory/mainargs.c:16: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/memory/mainargs.c:16: Warning: + out of bounds read. assert \valid_read(argv + argc); +[eva:alarm] tests/memory/mainargs.c:16: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/memory/mainargs.c:18: Warning: + function __gen_e_acsl_strlen: precondition 'valid_string_s' got status unknown. +[eva:alarm] FRAMAC_SHARE/libc/string.h:125: Warning: + function strlen: precondition 'valid_string_s' got status unknown. +[eva:alarm] FRAMAC_SHARE/libc/string.h:127: Warning: + function __gen_e_acsl_strlen: postcondition 'acsl_c_equiv' got status unknown. +[eva:alarm] tests/memory/mainargs.c:19: Warning: assertion got status unknown. +[eva:alarm] tests/memory/mainargs.c:20: Warning: assertion got status unknown. +[eva:alarm] tests/memory/mainargs.c:20: Warning: + function __e_acsl_assert: precondition got status unknown. diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/memalign.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_ci/memalign.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..674eddac861dff410a723d4a8016853a5ce17ca5 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/memalign.res.oracle @@ -0,0 +1,4 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". +[eva:alarm] tests/memory/memalign.c:14: Warning: + accessing uninitialized left-value. assert \initialized(memptr); diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/memsize.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_ci/memsize.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..fa55190b709b62274337a74a41e71d53d610d76e --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/memsize.res.oracle @@ -0,0 +1,5 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". +[eva:alarm] tests/memory/memsize.c:14: Warning: assertion got status unknown. +[eva:alarm] tests/memory/memsize.c:16: Warning: + assertion got status invalid (stopping propagation). diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/null.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_ci/null.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..efd026311297e55d8fefb674326118e6ece88624 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/null.res.oracle @@ -0,0 +1,2 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/offset.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_ci/offset.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..efd026311297e55d8fefb674326118e6ece88624 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/offset.res.oracle @@ -0,0 +1,2 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/other_constants.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_ci/other_constants.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..efd026311297e55d8fefb674326118e6ece88624 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/other_constants.res.oracle @@ -0,0 +1,2 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/ptr.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_ci/ptr.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..3e740b14f9a10f31564924427327d86fcde5839e --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/ptr.res.oracle @@ -0,0 +1,11 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". +[eva:alarm] tests/memory/ptr.i:17: Warning: assertion got status unknown. +[eva:alarm] tests/memory/ptr.i:17: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/memory/ptr.i:18: Warning: assertion got status unknown. +[eva:alarm] tests/memory/ptr.i:18: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/memory/ptr.i:19: Warning: assertion got status unknown. +[eva:alarm] tests/memory/ptr.i:19: Warning: + function __e_acsl_assert: precondition got status unknown. diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/ptr_init.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_ci/ptr_init.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..efd026311297e55d8fefb674326118e6ece88624 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/ptr_init.res.oracle @@ -0,0 +1,2 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/ranges_in_builtins.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_ci/ranges_in_builtins.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..a6b067c83c9b1f9067ea56155bc55976e2060ea8 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/ranges_in_builtins.res.oracle @@ -0,0 +1,8 @@ +[e-acsl] beginning translation. +[e-acsl] tests/memory/ranges_in_builtins.c:64: Warning: + E-ACSL construct `arithmetic over set of pointers or arrays' + is not yet supported. + Ignoring annotation. +[e-acsl] translation done in project "e-acsl". +[eva:alarm] tests/memory/ranges_in_builtins.c:21: Warning: + assertion got status invalid (stopping propagation). diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/sizeof.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_ci/sizeof.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..efd026311297e55d8fefb674326118e6ece88624 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/sizeof.res.oracle @@ -0,0 +1,2 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/stdout.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_ci/stdout.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..1dd58d9e80a90a6f03c81e9c316feeb7f88fb00d --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/stdout.res.oracle @@ -0,0 +1,5 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". +[eva:alarm] tests/memory/stdout.c:8: Warning: assertion got status unknown. +[eva:alarm] tests/memory/stdout.c:9: Warning: assertion got status unknown. +[eva:alarm] tests/memory/stdout.c:10: Warning: assertion got status unknown. diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/valid.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_ci/valid.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..10d60024c84446247288b53d197b4897a6a119ad --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/valid.res.oracle @@ -0,0 +1,5 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". +[eva:alarm] tests/memory/valid.c:43: Warning: + accessing left-value that contains escaping addresses. + assert ¬\dangling(&a); diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/valid_alias.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_ci/valid_alias.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..6fdc0e52c0e715a6d514e6ccd33a5307a271136b --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/valid_alias.res.oracle @@ -0,0 +1,5 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". +[eva:alarm] tests/memory/valid_alias.c:16: Warning: + accessing left-value that contains escaping addresses. + assert ¬\dangling(&a); diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/valid_in_contract.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_ci/valid_in_contract.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..efd026311297e55d8fefb674326118e6ece88624 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/valid_in_contract.res.oracle @@ -0,0 +1,2 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/vector.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_ci/vector.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..f511ea7c1174ae837459d1973c98a525649527c2 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/vector.res.oracle @@ -0,0 +1,7 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". +[eva:alarm] tests/memory/vector.c:11: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/memory/vector.c:25: Warning: + accessing uninitialized left-value. assert \initialized(v2 + 2); +[eva:alarm] tests/memory/vector.c:27: Warning: assertion got status unknown. diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/vla.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_ci/vla.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..50d32fb5962e6100f4dd17fd0041edf6b524f1dd --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_ci/vla.res.oracle @@ -0,0 +1,6 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". +[eva:alarm] tests/memory/vla.c:8: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/memory/vla.c:12: Warning: + assertion got status invalid (stopping propagation). diff --git a/src/plugins/e-acsl/tests/memory/oracle_dev/addrOf.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_dev/addrOf.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..431070f4cd2c23a54e002e700cf5e3b38de5ee9b --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_dev/addrOf.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/memory/addrOf.i (no preprocessing) diff --git a/src/plugins/e-acsl/tests/memory/oracle_dev/alias.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_dev/alias.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..76570c39a1839f0a05c5bb260d0478f294dfc87d --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_dev/alias.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/memory/alias.i (no preprocessing) diff --git a/src/plugins/e-acsl/tests/memory/oracle_dev/base_addr.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_dev/base_addr.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..fe96bbc669e4065fbba7c900a12576e99798f01f --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_dev/base_addr.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/memory/base_addr.c (with preprocessing) diff --git a/src/plugins/e-acsl/tests/memory/oracle_dev/block_length.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_dev/block_length.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..9a8b757a2a064fbd610f0f38dcc832bf08a72d7e --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_dev/block_length.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/memory/block_length.c (with preprocessing) diff --git a/src/plugins/e-acsl/tests/memory/oracle_dev/block_valid.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_dev/block_valid.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..1b45bb1e9d4e0c412975f7f584a3f5f41190bf4f --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_dev/block_valid.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/memory/block_valid.c (with preprocessing) diff --git a/src/plugins/e-acsl/tests/memory/oracle_dev/bypassed_var.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_dev/bypassed_var.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..bc2fc3b1336d2d4591be415e6e62bd22371b58ef --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_dev/bypassed_var.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/memory/bypassed_var.c (with preprocessing) diff --git a/src/plugins/e-acsl/tests/memory/oracle_dev/call.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_dev/call.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..5809c1481efc478b1ae9179ce5afbc4336029d2b --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_dev/call.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/memory/call.c (with preprocessing) diff --git a/src/plugins/e-acsl/tests/memory/oracle_dev/compound_initializers.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_dev/compound_initializers.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..fdb2f2e29f43957563faa4c8433c28ca551a71cd --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_dev/compound_initializers.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/memory/compound_initializers.c (with preprocessing) diff --git a/src/plugins/e-acsl/tests/memory/oracle_dev/constructor.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_dev/constructor.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..fb272a3c444be10982f0bbcd669f61999550fd56 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_dev/constructor.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/memory/constructor.c (with preprocessing) diff --git a/src/plugins/e-acsl/tests/memory/oracle_dev/ctype_macros.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_dev/ctype_macros.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..106c9f6f4a7d36a2dced986139176c3d82abc26a --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_dev/ctype_macros.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/memory/ctype_macros.c (with preprocessing) diff --git a/src/plugins/e-acsl/tests/memory/oracle_dev/early_exit.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_dev/early_exit.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..165982a9f80f193617a7400635a8ac6442cbe4d7 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_dev/early_exit.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/memory/early_exit.c (with preprocessing) diff --git a/src/plugins/e-acsl/tests/memory/oracle_dev/errno.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_dev/errno.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..46094a4bbe226c576a8f95aee14ba27b5dfe70bf --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_dev/errno.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/memory/errno.c (with preprocessing) diff --git a/src/plugins/e-acsl/tests/memory/oracle_dev/freeable.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_dev/freeable.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..b995f5e2ce349ed69711ca6030bd3cec2977eefd --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_dev/freeable.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/memory/freeable.c (with preprocessing) diff --git a/src/plugins/e-acsl/tests/memory/oracle_dev/goto.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_dev/goto.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..7f32099663f3add488d205bbd2f791e3e39a9b34 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_dev/goto.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/memory/goto.c (with preprocessing) diff --git a/src/plugins/e-acsl/tests/memory/oracle_dev/hidden_malloc.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_dev/hidden_malloc.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..dd729b732a8d3be776ffe1a2e51c33aca9dc63c3 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_dev/hidden_malloc.res.oracle @@ -0,0 +1,3 @@ +[kernel] Parsing tests/memory/hidden_malloc.c (with preprocessing) +[kernel:typing:implicit-function-declaration] tests/memory/hidden_malloc.c:11: Warning: + Calling undeclared function realpath. Old style K&R code? diff --git a/src/plugins/e-acsl/tests/memory/oracle_dev/init.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_dev/init.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..cd480f356c1cfca1517bff6ce0d69645e293b149 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_dev/init.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/memory/init.c (with preprocessing) diff --git a/src/plugins/e-acsl/tests/memory/oracle_dev/init_function.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_dev/init_function.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..bd7713301eb0c15cb7f54248e38c2a8cff586b8f --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_dev/init_function.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/memory/init_function.c (with preprocessing) diff --git a/src/plugins/e-acsl/tests/memory/oracle_dev/initialized.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_dev/initialized.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..ec68705fe630ce62dd5a9b90bf9c2e039d45e2cb --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_dev/initialized.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/memory/initialized.c (with preprocessing) diff --git a/src/plugins/e-acsl/tests/memory/oracle_dev/literal_string.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_dev/literal_string.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..adabc66ff0a7eea47c5f7efafdcfb92cfa00f744 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_dev/literal_string.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/memory/literal_string.i (no preprocessing) diff --git a/src/plugins/e-acsl/tests/memory/oracle_dev/local_goto.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_dev/local_goto.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..b8fcb3470dbfcb8da050df6fa58387387fe69b0d --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_dev/local_goto.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/memory/local_goto.c (with preprocessing) diff --git a/src/plugins/e-acsl/tests/memory/oracle_dev/local_init.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_dev/local_init.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..460acb5fa597139c788b65a53882d3224f769e9d --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_dev/local_init.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/memory/local_init.c (with preprocessing) diff --git a/src/plugins/e-acsl/tests/memory/oracle_dev/local_var.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_dev/local_var.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..3743a714794545c5ef62287213e81fef3ffa0e4b --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_dev/local_var.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/memory/local_var.c (with preprocessing) diff --git a/src/plugins/e-acsl/tests/memory/oracle_dev/mainargs.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_dev/mainargs.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..36343fa0223fdbb51d13cac0fdb58f44c333a609 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_dev/mainargs.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/memory/mainargs.c (with preprocessing) diff --git a/src/plugins/e-acsl/tests/memory/oracle_dev/memalign.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_dev/memalign.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..5b0314a0e239de01f82fde92d898059b25fa62f5 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_dev/memalign.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/memory/memalign.c (with preprocessing) diff --git a/src/plugins/e-acsl/tests/memory/oracle_dev/memsize.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_dev/memsize.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..e6f6288929b8f85163da1241f838185526930c70 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_dev/memsize.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/memory/memsize.c (with preprocessing) diff --git a/src/plugins/e-acsl/tests/memory/oracle_dev/null.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_dev/null.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..5a854c58c96a09f37219080a6c6cb8129f640230 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_dev/null.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/memory/null.i (no preprocessing) diff --git a/src/plugins/e-acsl/tests/memory/oracle_dev/offset.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_dev/offset.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..9a18d848004451c94fd0b42a86ac95ecc99ddf61 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_dev/offset.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/memory/offset.c (with preprocessing) diff --git a/src/plugins/e-acsl/tests/memory/oracle_dev/other_constants.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_dev/other_constants.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..b56718829921013ea3f8f5fc73a2f19c8496796b --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_dev/other_constants.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/memory/other_constants.i (no preprocessing) diff --git a/src/plugins/e-acsl/tests/memory/oracle_dev/ptr.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_dev/ptr.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..fcdcd5edd933540db9cfee10d831693420f086bf --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_dev/ptr.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/memory/ptr.i (no preprocessing) diff --git a/src/plugins/e-acsl/tests/memory/oracle_dev/ptr_init.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_dev/ptr_init.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..0b2ed5a9fc3516dbce7cc694cfdcaf45e0a8ed9a --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_dev/ptr_init.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/memory/ptr_init.c (with preprocessing) diff --git a/src/plugins/e-acsl/tests/memory/oracle_dev/ranges_in_builtins.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_dev/ranges_in_builtins.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..15a2210f13df3c32991408613e0b5ebb2091b79f --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_dev/ranges_in_builtins.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/memory/ranges_in_builtins.c (with preprocessing) diff --git a/src/plugins/e-acsl/tests/memory/oracle_dev/sizeof.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_dev/sizeof.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..45453873f24881a5367652c3ec53912d1685ea36 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_dev/sizeof.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/memory/sizeof.i (no preprocessing) diff --git a/src/plugins/e-acsl/tests/memory/oracle_dev/stdout.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_dev/stdout.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..b54acaedc8843427148c51bb6a1c7a8aebee30b7 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_dev/stdout.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/memory/stdout.c (with preprocessing) diff --git a/src/plugins/e-acsl/tests/memory/oracle_dev/valid.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_dev/valid.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..c325574714e3a2da8ca342144e3088da774e8e2b --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_dev/valid.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/memory/valid.c (with preprocessing) diff --git a/src/plugins/e-acsl/tests/memory/oracle_dev/valid_alias.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_dev/valid_alias.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..767b46d932fa96248caba8ceeedf72cd7bd2356c --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_dev/valid_alias.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/memory/valid_alias.c (with preprocessing) diff --git a/src/plugins/e-acsl/tests/memory/oracle_dev/valid_in_contract.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_dev/valid_in_contract.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..45dec02aac951fda0a503a2edf6a9011ef36bc1a --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_dev/valid_in_contract.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/memory/valid_in_contract.c (with preprocessing) diff --git a/src/plugins/e-acsl/tests/memory/oracle_dev/vector.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_dev/vector.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..296f399f3c8f267c128d2a151780ed432257574f --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_dev/vector.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/memory/vector.c (with preprocessing) diff --git a/src/plugins/e-acsl/tests/memory/oracle_dev/vla.res.oracle b/src/plugins/e-acsl/tests/memory/oracle_dev/vla.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..cfa640a9f3642c03e9400b7012a5e580ef2f39e3 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/oracle_dev/vla.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/memory/vla.c (with preprocessing) diff --git a/src/plugins/e-acsl/tests/memory/other_constants.i b/src/plugins/e-acsl/tests/memory/other_constants.i new file mode 100644 index 0000000000000000000000000000000000000000..b5112129a7c74e5a585f5a08d8147453b9e16c28 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/other_constants.i @@ -0,0 +1,13 @@ +/* run.config + COMMENT: non integer constants +*/ + +enum bool { false, true }; + +int main(void) { + // waiting for clarification of semantics of ACSL's literal strings + // /*@ assert "toto" != "titi"; */ + /*@ assert 'c' == 'c'; */ + /*@ assert false != true; */ + return 0; +} diff --git a/src/plugins/e-acsl/tests/memory/ptr.i b/src/plugins/e-acsl/tests/memory/ptr.i new file mode 100644 index 0000000000000000000000000000000000000000..d2821e3da57e4753b955e6e7bb7119ee0230a84d --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/ptr.i @@ -0,0 +1,30 @@ +/* run.config + COMMENT: pointers and pointer arithmetic +*/ + +int main(void) { + + int x = 1; + int t[3] = { 2, 3, 4 }; + int *p = &x; + + /*@ assert *p == 1; */ + /*@ assert *t == 2; */ + /*@ assert *(t+2) == 4; */ + /*@ assert *(t+2*sizeof(int)/sizeof((int)0x0)) == 4; */ + + for(int i = 0; i < 2; i++) { + /*@ assert (*(t+i) == i+2); */ ; + /*@ assert (*(t+(2-i)) == 4-i); */ ; + /*@ assert (*(t+2-i) == 4-i); */ ; + ; + } + + p = t+2; + t[2] = 5; + /*@ assert *p == 5; */ + int k = -1; + /*@ assert *(p+k) == 3; */ // bts #2252 + + return 0; +} diff --git a/src/plugins/e-acsl/tests/memory/ptr_init.c b/src/plugins/e-acsl/tests/memory/ptr_init.c new file mode 100644 index 0000000000000000000000000000000000000000..e97796dbcbc048a6483d75ee56dd85168fcf253d --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/ptr_init.c @@ -0,0 +1,29 @@ +/* run.config + COMMENT: initialized and function calls +*/ + +#include "stdlib.h" + +extern void *malloc(size_t); + +int *A, *B; + +void f() { + A = B; +} + +void g(int *C, int* D) { + /*@ assert \initialized(&C); */ +} + +int main(void) { + int *x, *y; + B = (int*) malloc(sizeof(int)); + y = (int*) malloc(sizeof(int)); + x = y; + f(); + /*@ assert \initialized(&A); */ + /*@ assert \initialized(&x); */ + g(x, y); + return 0; +} diff --git a/src/plugins/e-acsl/tests/memory/ranges_in_builtins.c b/src/plugins/e-acsl/tests/memory/ranges_in_builtins.c new file mode 100644 index 0000000000000000000000000000000000000000..7c94e87d3ceb3f39f32c651abca2c300842dd83a --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/ranges_in_builtins.c @@ -0,0 +1,73 @@ +/* run.config + COMMENT: ranges in a few builtins +*/ +#include "stdlib.h" +/*@ requires !\valid(s + (3..n+1000)); */ +void f(char *s, long n){} +/*@ requires \valid(ptr + (0 .. size - 1)); + ensures ! \valid(ptr + (0 .. size + 1)); + // In pure ACSL, the following predicate is true; + // however at runtime, its evalulation results in UB ==> false. + // ensures ! \valid(ptr + (0 .. SIZE_MAX*SIZE_MAX)); */ +void g(long *ptr, size_t size) { } +extern void *malloc(size_t p); +extern void free(void* p); +struct S { int a[2]; float *b; float *c;}; +int main(void) { + int *a; + a = malloc(10*sizeof(int)); + /*@ assert \valid(a + (0 .. 4)); */ ; + int j = 2; + /*@ assert \valid(a + (4 .. 8+j)); */ ; + /*@ assert !\valid(a + (10 .. 11)); */ ; + free(a); + + char *b; + b = malloc(10*sizeof(char)); + /*@ assert \valid(b + (0 .. 10)); */ ; + /*@ assert !\valid(b + (11 .. 15)); */ ; + + long t[3] = {7l, 8l, 9l}; + /*@ assert \valid(&t[0..2]); */ ; + /*@ assert !\valid(&t[3..5]); */ ; + g(t, 3); + + double t2[4]; + t2[0] = 0.5; + t2[1] = 1.5; + /*@ assert \initialized(&t2[0..1]); */ ; + /*@ assert !\initialized(&t2[2..3]); */ ; + + /*@ assert !\initialized(b + (0 .. 10));*/ + free(b); + + int n = 2; + float t3[7][2][4]; + /*@ assert !\initialized(&t3[(n-1)..(n+2)][1][0..1]); */ ; + + /*@ assert !\valid_read(&t3[6][1][0] + (2..10)); */ + /*@ assert \valid_read(&t3[(n-1)..(n+2)][1]); */ + + struct S s; + s.a[0] = 7; s.a[1] = 8; + /*@ assert \initialized(&s.a[0] + (1..2)); */ ; + /*@ assert !\initialized(s.b + (0..1)); */ ; + + int **multi_dynamic; + int size1 = 5, size2 = 9; + multi_dynamic = malloc(size1 * sizeof(*multi_dynamic)); + int i; + for(i = 0; i < size1; i++) { + multi_dynamic[i] = malloc(size2 * sizeof(*(multi_dynamic[i]))); + } + /*@ assert \valid(&multi_dynamic[4][1..7]); */ // single call to builtin + /*@ assert \valid(&multi_dynamic[2..4][1..7]); */ // need to modify Mmodel + // => not_yet + for(i = i-1 ; i >= 0 ; i--) { + free(multi_dynamic[i]); + } + free(multi_dynamic); + + char c = 'w'; + f(&c, 5); +} \ No newline at end of file diff --git a/src/plugins/e-acsl/tests/memory/sizeof.i b/src/plugins/e-acsl/tests/memory/sizeof.i new file mode 100644 index 0000000000000000000000000000000000000000..d52b87d39370fc4866257084e6c9d500d8cae218 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/sizeof.i @@ -0,0 +1,10 @@ +/* run.config + COMMENT: sizeof +*/ + +int main(void) { + int x = 0; + x++; /* prevent GCC's warning */ + /*@ assert sizeof(int) == sizeof(x); */ ; + return 0; +} diff --git a/src/plugins/e-acsl/tests/memory/stdout.c b/src/plugins/e-acsl/tests/memory/stdout.c new file mode 100644 index 0000000000000000000000000000000000000000..0238e9d99a5bc81c1c2720f928cf98a4fd2d0465 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/stdout.c @@ -0,0 +1,12 @@ +/* run.config + COMMENT: ensure that standard streams are properly tracked +*/ + +#include <stdio.h> + +int main(void) { + /*@assert \valid(stderr); */ + /*@assert \valid(stdin); */ + /*@assert \valid(stdout); */ + return 0; +} diff --git a/src/plugins/e-acsl/tests/memory/valid.c b/src/plugins/e-acsl/tests/memory/valid.c new file mode 100644 index 0000000000000000000000000000000000000000..9d48defa0489f8e15e856dcfe425108282545090 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/valid.c @@ -0,0 +1,47 @@ +/* run.config + COMMENT: \valid +*/ + +#include "stdlib.h" + +int *X, Z; + +/*@ requires \valid(x); + @ ensures \valid(\result); */ +int *f(int *x) { + int *y; + /*@ assert ! \valid(y); */ + y = x; + /*@ assert \valid(x); */ + return y; +} + +void g(void) { + int m, *u, **p; + p=&u; + u=&m; + m=123; + //@ assert \valid(*p); +} + +int main(void) { + int *a, *b, **c, ***d, n = 0; + /*@ assert ! \valid(a) && ! \valid(b) && ! \valid(X); */ + a = malloc(sizeof(int)); + /*@ assert \valid(a) && ! \valid(b) && ! \valid(X); */ + X = a; + /*@ assert \valid(a) && ! \valid(b) && \valid(X); */ + b = f(&n); + /*@ assert \valid(a) && \valid(b) && \valid(X); */ + X = b; + /*@ assert \valid(a) && \valid(b) && \valid(X); */ + c = &a; + d = &c; + /*@ assert \valid(*c); */ + /*@ assert \valid(**d); */ + free(a); + /*@ assert ! \valid(a) && \valid(b) && \valid(X); */ + /*@ assert \valid(&Z); */ + g(); + return 0; +} diff --git a/src/plugins/e-acsl/tests/memory/valid_alias.c b/src/plugins/e-acsl/tests/memory/valid_alias.c new file mode 100644 index 0000000000000000000000000000000000000000..8ec383b38de98745681ce6df2fc173cb2b615ae9 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/valid_alias.c @@ -0,0 +1,18 @@ +/* run.config + COMMENT: \valid in presence of aliasing +*/ + +#include "stdlib.h" + +int main(void) { + int *a, *b, n = 0; + /*@ assert ! \valid(a) && ! \valid(b); */ + a = malloc(sizeof(int)); + *a = n; + b = a; + /*@ assert \valid(a) && \valid(b); */ + /*@ assert *b == n; */ + free(b); + /*@ assert ! \valid(a) && ! \valid(b); */ + return 0; +} diff --git a/src/plugins/e-acsl/tests/memory/valid_in_contract.c b/src/plugins/e-acsl/tests/memory/valid_in_contract.c new file mode 100644 index 0000000000000000000000000000000000000000..ed7db447fc4a4978bd1872808f3c086ffe413b63 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/valid_in_contract.c @@ -0,0 +1,32 @@ +/* run.config + COMMENT: function contract involving \valid +*/ + +#include <stdlib.h> + +struct list { + int element; + struct list * next; +}; + +/*@ + @ behavior B1: + @ assumes l == \null; + @ ensures \result == l; + @ behavior B2: + @ assumes ! \valid(l) || ! \valid(l->next); + @ ensures \result == l; +*/ +struct list * f(struct list * l) { + /* length = 0 */ + if(l == NULL) return l; + /* length = 1 : already sorted */ + if(l->next == NULL) return l; + + return NULL; +} + +int main() { + f(NULL); + return 0; +} diff --git a/src/plugins/e-acsl/tests/memory/vector.c b/src/plugins/e-acsl/tests/memory/vector.c new file mode 100644 index 0000000000000000000000000000000000000000..bda4a716fef8c3aa2639da29bb3198421cb4289e --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/vector.c @@ -0,0 +1,30 @@ +/* run.config + COMMENT: function call + initialized +*/ + +#include<stdlib.h> + +int LAST; + +int* new_inversed(int len, int *v) { + int i, *p; + //@ assert \valid(v) && \offset(v)+len*sizeof(int) <= \block_length(v); + p = malloc(sizeof(int)*len); + for(i=0; i<len; i++) + p[i] = v[len-i-1]; + return p; +} + +int main(void) { + int x = 3; + int v1[3]= { 1, 2, x }, *v2; + //@ assert \valid(&v1[2]); + LAST = v1[2]; + //@ assert \initialized(v1+2); + v2 = new_inversed(3, v1); + LAST = v2[2]; + //@ assert \initialized(v2+2); + //@ assert LAST == 1; + free(v2); + return 0; +} diff --git a/src/plugins/e-acsl/tests/memory/vla.c b/src/plugins/e-acsl/tests/memory/vla.c new file mode 100644 index 0000000000000000000000000000000000000000..0d2107a0bad4d549fcfa62d1c43b9b98aefd8674 --- /dev/null +++ b/src/plugins/e-acsl/tests/memory/vla.c @@ -0,0 +1,18 @@ +/* run.config + COMMENT: Check variable-length arrays +*/ + +int LEN = 10; + +int main(int argc, char **argv) { + int arr[LEN]; + int i; + for (i = 0; i <= LEN; i++) { + if (i < LEN) { + /*@assert \valid(&arr[i]); */ + } else { + /*@assert ! \valid(&arr[i]); */ + } + } + return 0; +} diff --git a/src/plugins/e-acsl/tests/print.ml b/src/plugins/e-acsl/tests/print.ml new file mode 100644 index 0000000000000000000000000000000000000000..4cd4e8bfd8407702c8e826719b7553644b671ec2 --- /dev/null +++ b/src/plugins/e-acsl/tests/print.ml @@ -0,0 +1,40 @@ +(**************************************************************************) +(* *) +(* This file is part of the Frama-C's E-ACSL plug-in. *) +(* *) +(* Copyright (C) 2012-2018 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +module Printer_extension(X:Printer.PrinterClass) = struct + + class printer = object + inherit Printer.extensible_printer () as super + + method! global fmt g = + let loc, _ = Cil_datatype.Global.loc g in + let file = loc.Filepath.pos_path in + if file = Datatype.Filepath.dummy || List.exists + (fun s -> Datatype.Filepath.of_string s = file) + (Kernel.Files.get ()) + then super#global fmt g + + end + +end + +let () = Printer.update_printer (module Printer_extension) diff --git a/src/plugins/e-acsl/tests/special/README.md b/src/plugins/e-acsl/tests/special/README.md new file mode 100644 index 0000000000000000000000000000000000000000..f36bad2af25636f67698f0d360fc902e3ec0b6e5 --- /dev/null +++ b/src/plugins/e-acsl/tests/special/README.md @@ -0,0 +1,2 @@ +Test files which require special configurations which cannot be factorized +in a convenient way. diff --git a/src/plugins/e-acsl/tests/special/builtin.i b/src/plugins/e-acsl/tests/special/builtin.i new file mode 100644 index 0000000000000000000000000000000000000000..5a4e114c5423bcdbdc2dc0f7a29cde752351a3b1 --- /dev/null +++ b/src/plugins/e-acsl/tests/special/builtin.i @@ -0,0 +1,17 @@ +/* run.config_ci + COMMENT: -e-acsl-builtins + LOG: gen_builtin.c + STDOPT: #"-e-acsl-builtins incr" +*/ + +int incr(int); + +/*@ ensures \result == incr(i); */ +int f(int i) { int j = i + 1; return j; } + +int incr(int x) { return x + 1; } + +int main() { + int i = f(2); + return 0; +} diff --git a/src/plugins/e-acsl/tests/special/e-acsl-functions.c b/src/plugins/e-acsl/tests/special/e-acsl-functions.c new file mode 100644 index 0000000000000000000000000000000000000000..dbed3c949013f461bd4ff205c05f15c92334ac89 --- /dev/null +++ b/src/plugins/e-acsl/tests/special/e-acsl-functions.c @@ -0,0 +1,30 @@ +/* run.config_ci + COMMENT: test option -e-acsl-functions + LOG: gen_@PTEST_NAME@.c + STDOPT: #"-e-acsl-functions f" +*/ + +/*@ requires \initialized(p); + @ requires *p == 0; + @ ensures \result == \old(*p); */ +int f(int *p) { + /*@ loop invariant 0 <= i <= 1; */ + for(int i = 0; i < 1; i++) ; + return 0; +} + +/*@ requires \initialized(p); + @ requires *p == 1; + @ ensures \result == \old(*p); */ +int g(int *p) { + /*@ loop invariant 0 <= i <= 1; */ + for(int i = 0; i < 1; i++) ; + return 0; +} + +int main(void) { + int x = 0; + int y = 0; + f(&x); + g(&y); +} diff --git a/src/plugins/e-acsl/tests/special/e-acsl-instrument.c b/src/plugins/e-acsl/tests/special/e-acsl-instrument.c new file mode 100644 index 0000000000000000000000000000000000000000..6d047c1921b2db4e5438f146fa9d4dfc112f4c08 --- /dev/null +++ b/src/plugins/e-acsl/tests/special/e-acsl-instrument.c @@ -0,0 +1,59 @@ +/* run.config_ci + COMMENT: test option -e-acsl-instrument; cannot run Eva on this example + LOG: gen_@PTEST_NAME@.c + STDOPT:#"-e-acsl-instrument='@@all,-uninstrument1,-uninstrument2'" +*/ + +#include <stdarg.h> + +int uninstrument1(int *p) { + *p = 0; + return 0; +} + +/*@ requires \valid(p); */ +int uninstrument2(int *p) { + { int *q = p; + *p = 0; + goto L; + } + L: + return 0; +} + +int instrument1(int *p) { + *p = 0; + return 0; +} + +/*@ requires \valid(p); */ +int instrument2(int *p) { + { int *q = p; + *p = 0; + goto L; + } + L: + return 0; +} + +/* test combination of -e-acsl-instrument and -variadic-no-translation; + see gitlab's issue #88 */ +int vol(int n, ...) { + va_list vl; + va_start(vl, n); + int r = va_arg(vl, int); + va_end(vl); + return 1; +} + +int main(void) { + int x; + int y = 0; + instrument1(&x); + uninstrument1(&x); + instrument2(&x); + uninstrument2(&x); + /*@ assert \initialized(&x); */ + /*@ assert \initialized(&y); */ + return vol(6, 1); +} diff --git a/src/plugins/e-acsl/tests/special/e-acsl-valid.c b/src/plugins/e-acsl/tests/special/e-acsl-valid.c new file mode 100644 index 0000000000000000000000000000000000000000..0991da238f6abea0dc712b85916fbcadf6d1d2b1 --- /dev/null +++ b/src/plugins/e-acsl/tests/special/e-acsl-valid.c @@ -0,0 +1,39 @@ +/* run.config_ci + COMMENT: test option -e-acsl-no-valid + DONTRUN: + LOG: gen_@PTEST_NAME@.c + STDOPT: #"-e-acsl-prepare -e-acsl-share ./share/e-acsl -eva -eva-verbose 0 -then -e-acsl-no-valid" +*/ + +#include <stdlib.h> + +/*@ requires \valid(y); + @ requires *x >= 0; + @ ensures *x == \old(*x)+1; + @ assigns *x \from *x,x; + @ behavior b1: + @ assumes *x == 1; + @ assigns \nothing; + @ ensures *x < 0; + @ behavior b2: + @ assumes *x == 0; + @ ensures *x == 1; + @ complete behaviors; + @ disjoint behaviors b1, b2; + @ */ +void f(int *x, int *y) { + /*@ requires *x >= 0; + @ ensures 2 >= 1; + @ assigns *x; */ + { (*x)++; } + /*@ loop invariant 0 <= i <= 1; + @ loop variant 2 - i; */ + for(int i = 0; i < 1; i++) /*@ assert 1 == 1; */ /*@ assert \valid(y); */ ; +} + +int main(void) { + int x = 0; + int *y = (int *)malloc(sizeof(int)); + f(&x, y); + return 0; +} diff --git a/src/plugins/e-acsl/tests/special/oracle_ci/builtin.res.oracle b/src/plugins/e-acsl/tests/special/oracle_ci/builtin.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..f829e96e46483dba4975d357c55444c4b1fba88d --- /dev/null +++ b/src/plugins/e-acsl/tests/special/oracle_ci/builtin.res.oracle @@ -0,0 +1,4 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". +[eva:alarm] tests/special/builtin.i:9: Warning: + function __gen_e_acsl_f: postcondition got status unknown. diff --git a/src/plugins/e-acsl/tests/special/oracle_ci/e-acsl-functions.res.oracle b/src/plugins/e-acsl/tests/special/oracle_ci/e-acsl-functions.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..4661ead8e7059ddb6a7055c38aa6b21734ab6e5c --- /dev/null +++ b/src/plugins/e-acsl/tests/special/oracle_ci/e-acsl-functions.res.oracle @@ -0,0 +1,4 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". +[eva:alarm] tests/special/e-acsl-functions.c:29: Warning: + function g: precondition *p ≡ 1 got status invalid. diff --git a/src/plugins/e-acsl/tests/special/oracle_ci/e-acsl-instrument.res.oracle b/src/plugins/e-acsl/tests/special/oracle_ci/e-acsl-instrument.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..aabd7fab72b0dbd8439dbcae86b304ca634d327f --- /dev/null +++ b/src/plugins/e-acsl/tests/special/oracle_ci/e-acsl-instrument.res.oracle @@ -0,0 +1,14 @@ +[e-acsl] beginning translation. +[kernel:annot:missing-spec] :0: Warning: + Neither code nor specification for function __builtin_va_arg, generating default assigns from the prototype +[kernel:annot:missing-spec] :0: Warning: + Neither code nor specification for function __builtin_va_end, generating default assigns from the prototype +[kernel:annot:missing-spec] :0: Warning: + Neither code nor specification for function __builtin_va_start, generating default assigns from the prototype +[e-acsl] tests/special/e-acsl-instrument.c:58: Warning: + ignoring effect of variadic function vol +[e-acsl] translation done in project "e-acsl". +[eva:alarm] tests/special/e-acsl-instrument.c:44: Warning: + accessing uninitialized left-value. + assert \initialized(&tmp); + (tmp from vararg) diff --git a/src/plugins/e-acsl/tests/special/oracle_ci/e-acsl-valid.res.oracle b/src/plugins/e-acsl/tests/special/oracle_ci/e-acsl-valid.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..8a102a933b40c01c21491f96630d750b81d7f818 --- /dev/null +++ b/src/plugins/e-acsl/tests/special/oracle_ci/e-acsl-valid.res.oracle @@ -0,0 +1,40 @@ +[eva:alarm] tests/special/e-acsl-valid.c:36: Warning: + function f: precondition \valid(y) got status unknown. +[e-acsl] beginning translation. +[kernel:annot:missing-spec] FRAMAC_SHARE/e-acsl/e_acsl.h:165: Warning: + Neither code nor specification for function aligned_alloc, generating default assigns from the prototype +[kernel:annot:missing-spec] FRAMAC_SHARE/e-acsl/e_acsl.h:181: Warning: + Neither code nor specification for function __e_acsl_mspaces_init, generating default assigns from the prototype +[kernel:annot:missing-spec] FRAMAC_SHARE/e-acsl/e_acsl.h:446: Warning: + Neither code nor specification for function __e_acsl_builtin_printf, generating default assigns from the prototype +[kernel:annot:missing-spec] FRAMAC_SHARE/e-acsl/e_acsl.h:450: Warning: + Neither code nor specification for function __e_acsl_builtin_fprintf, generating default assigns from the prototype +[kernel:annot:missing-spec] FRAMAC_SHARE/e-acsl/e_acsl.h:454: Warning: + Neither code nor specification for function __e_acsl_builtin_dprintf, generating default assigns from the prototype +[kernel:annot:missing-spec] FRAMAC_SHARE/e-acsl/e_acsl.h:458: Warning: + Neither code nor specification for function __e_acsl_builtin_sprintf, generating default assigns from the prototype +[kernel:annot:missing-spec] FRAMAC_SHARE/e-acsl/e_acsl.h:462: Warning: + Neither code nor specification for function __e_acsl_builtin_snprintf, generating default assigns from the prototype +[kernel:annot:missing-spec] FRAMAC_SHARE/e-acsl/e_acsl.h:467: Warning: + Neither code nor specification for function __e_acsl_builtin_syslog, generating default assigns from the prototype +[kernel:annot:missing-spec] FRAMAC_SHARE/e-acsl/e_acsl.h:488: Warning: + Neither code nor specification for function __e_acsl_floating_point_exception, generating default assigns from the prototype +[kernel] Current source was: tests/special/e-acsl-valid.c:33 + The full backtrace is: + Raised at file "src/libraries/project/project.ml", line 405, characters 59-66 + Called from file "src/main.ml", line 155, characters 14-1023 + Called from file "src/main.ml", line 121, characters 12-34 + Called from file "src/libraries/project/state_builder.ml", line 565, characters 17-22 + Called from file "src/main.ml", line 258, characters 11-56 + Called from file "queue.ml", line 121, characters 6-15 + Called from file "src/kernel_internals/runtime/boot.ml", line 36, characters 4-20 + Called from file "src/kernel_services/cmdline_parameters/cmdline.ml", line 792, characters 2-9 + Called from file "src/kernel_services/cmdline_parameters/cmdline.ml", line 807, characters 30-76 + Called from file "src/kernel_services/cmdline_parameters/cmdline.ml", line 229, characters 4-8 + + Unexpected error (E_ACSL.Misc.Unregistered_library_function("__e_acsl_store_block")). + Please report as 'crash' at http://bts.frama-c.com/. + Your Frama-C version is 19.0+dev (Potassium). + Note that a version and a backtrace alone often do not contain enough + information to understand the bug. Guidelines for reporting bugs are at: + http://bts.frama-c.com/dokuwiki/doku.php?id=mantis:frama-c:bug_reporting_guidelines diff --git a/src/plugins/e-acsl/tests/special/oracle_ci/gen_builtin.c b/src/plugins/e-acsl/tests/special/oracle_ci/gen_builtin.c new file mode 100644 index 0000000000000000000000000000000000000000..a1e4cd5f61765508c79776859fe56db818208453 --- /dev/null +++ b/src/plugins/e-acsl/tests/special/oracle_ci/gen_builtin.c @@ -0,0 +1,50 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +extern int __e_acsl_sound_verdict; + +int incr(int x); + +/*@ ensures \result ≡ incr(\old(i)); */ +int __gen_e_acsl_f(int i); + +int f(int i) +{ + int j = i + 1; + return j; +} + +int incr(int x) +{ + int __retres; + __retres = x + 1; + return __retres; +} + +int main(void) +{ + int __retres; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + int i = __gen_e_acsl_f(2); + __retres = 0; + return __retres; +} + +/*@ ensures \result ≡ incr(\old(i)); */ +int __gen_e_acsl_f(int i) +{ + int __gen_e_acsl_at; + int __retres; + __gen_e_acsl_at = i; + __retres = f(i); + { + int __gen_e_acsl_incr_app; + __gen_e_acsl_incr_app = incr(__gen_e_acsl_at); + __e_acsl_assert(__retres == __gen_e_acsl_incr_app, + (char *)"Postcondition",(char *)"f", + (char *)"\\result == incr(\\old(i))",9); + return __retres; + } +} + + diff --git a/src/plugins/e-acsl/tests/special/oracle_ci/gen_e-acsl-functions.c b/src/plugins/e-acsl/tests/special/oracle_ci/gen_e-acsl-functions.c new file mode 100644 index 0000000000000000000000000000000000000000..7dcecd4a65f39260739590086a682211769142a5 --- /dev/null +++ b/src/plugins/e-acsl/tests/special/oracle_ci/gen_e-acsl-functions.c @@ -0,0 +1,104 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +extern int __e_acsl_sound_verdict; + +/*@ requires \initialized(p); + requires *p ≡ 0; + ensures \result ≡ \old(*p); + */ +int __gen_e_acsl_f(int *p); + +int f(int *p) +{ + int __retres; + __e_acsl_store_block((void *)(& p),(size_t)8); + { + int i = 0; + { + { + int __gen_e_acsl_and; + if (0 <= i) __gen_e_acsl_and = i <= 1; else __gen_e_acsl_and = 0; + __e_acsl_assert(__gen_e_acsl_and,(char *)"Invariant",(char *)"f", + (char *)"0 <= i <= 1",11); + } + /*@ loop invariant 0 ≤ i ≤ 1; */ + while (i < 1) { + int __gen_e_acsl_and_2; + i ++; + if (0 <= i) __gen_e_acsl_and_2 = i <= 1; else __gen_e_acsl_and_2 = 0; + __e_acsl_assert(__gen_e_acsl_and_2,(char *)"Invariant",(char *)"f", + (char *)"0 <= i <= 1",11); + } + } + } + __retres = 0; + __e_acsl_delete_block((void *)(& p)); + return __retres; +} + +/*@ requires \initialized(p); + requires *p ≡ 1; + ensures \result ≡ \old(*p); + */ +int g(int *p) +{ + int __retres; + { + int i = 0; + /*@ loop invariant 0 ≤ i ≤ 1; */ + while (i < 1) i ++; + } + __retres = 0; + return __retres; +} + +int main(void) +{ + int __retres; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + int x = 0; + __e_acsl_store_block((void *)(& x),(size_t)4); + __e_acsl_full_init((void *)(& x)); + int y = 0; + __gen_e_acsl_f(& x); + g(& y); + __retres = 0; + __e_acsl_delete_block((void *)(& x)); + __e_acsl_memory_clean(); + return __retres; +} + +/*@ requires \initialized(p); + requires *p ≡ 0; + ensures \result ≡ \old(*p); + */ +int __gen_e_acsl_f(int *p) +{ + int __gen_e_acsl_at; + int __retres; + { + int __gen_e_acsl_valid_read; + __gen_e_acsl_valid_read = __e_acsl_valid_read((void *)p,sizeof(int), + (void *)p,(void *)(& p)); + __e_acsl_assert(__gen_e_acsl_valid_read,(char *)"RTE",(char *)"f", + (char *)"mem_access: \\valid_read(p)",9); + __gen_e_acsl_at = *p; + } + { + int __gen_e_acsl_initialized; + __e_acsl_store_block((void *)(& p),(size_t)8); + __gen_e_acsl_initialized = __e_acsl_initialized((void *)p,sizeof(int)); + __e_acsl_assert(__gen_e_acsl_initialized,(char *)"Precondition", + (char *)"f",(char *)"\\initialized(p)",7); + __e_acsl_assert(*p == 0,(char *)"Precondition",(char *)"f", + (char *)"*p == 0",8); + } + __retres = f(p); + __e_acsl_assert(__retres == __gen_e_acsl_at,(char *)"Postcondition", + (char *)"f",(char *)"\\result == \\old(*p)",9); + __e_acsl_delete_block((void *)(& p)); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/special/oracle_ci/gen_e-acsl-instrument.c b/src/plugins/e-acsl/tests/special/oracle_ci/gen_e-acsl-instrument.c new file mode 100644 index 0000000000000000000000000000000000000000..b3bd734d1350fa922b5e19ad1fafbe2be5f011e4 --- /dev/null +++ b/src/plugins/e-acsl/tests/special/oracle_ci/gen_e-acsl-instrument.c @@ -0,0 +1,162 @@ +/* Generated by Frama-C */ +#include "stdarg.h" +#include "stdio.h" +#include "stdlib.h" +extern int __e_acsl_sound_verdict; + +/* compiler builtin: + void __builtin_va_arg(__builtin_va_list, unsigned long, void *); */ +/* compiler builtin: + void __builtin_va_end(__builtin_va_list); */ +/* compiler builtin: + void __builtin_va_start(__builtin_va_list); */ +int __gen_e_acsl_uninstrument1(int *p); + +int uninstrument1(int *p) +{ + int __retres; + *p = 0; + __retres = 0; + return __retres; +} + +/*@ requires \valid(p); */ +int __gen_e_acsl_uninstrument2(int *p); + +int uninstrument2(int *p) +{ + int __retres; + { + int *q = p; + *p = 0; + goto L; + } + L: __retres = 0; + return __retres; +} + +int instrument1(int *p) +{ + int __retres; + __e_acsl_store_block((void *)(& p),(size_t)8); + __e_acsl_initialize((void *)p,sizeof(int)); + *p = 0; + __retres = 0; + __e_acsl_delete_block((void *)(& p)); + return __retres; +} + +/*@ requires \valid(p); */ +int __gen_e_acsl_instrument2(int *p); + +int instrument2(int *p) +{ + int __retres; + __e_acsl_store_block((void *)(& p),(size_t)8); + { + int *q = p; + __e_acsl_store_block((void *)(& q),(size_t)8); + __e_acsl_full_init((void *)(& q)); + __e_acsl_initialize((void *)p,sizeof(int)); + *p = 0; + __e_acsl_delete_block((void *)(& q)); + goto L; + __e_acsl_delete_block((void *)(& q)); + } + L: __retres = 0; + __e_acsl_delete_block((void *)(& p)); + return __retres; +} + +int vol(int n , ...) +{ + int __retres; + va_list vl; + int tmp; + __builtin_va_start(vl,n); + tmp = __builtin_va_arg (vl, int); + /*@ assert Eva: initialization: \initialized(&tmp); */ + int r = tmp; + __builtin_va_end(vl); + __retres = 1; + return __retres; +} + +int main(void) +{ + int x; + int tmp; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + __e_acsl_store_block((void *)(& x),(size_t)4); + int y = 0; + __e_acsl_store_block((void *)(& y),(size_t)4); + __e_acsl_full_init((void *)(& y)); + instrument1(& x); + __gen_e_acsl_uninstrument1(& x); + __gen_e_acsl_instrument2(& x); + __gen_e_acsl_uninstrument2(& x); + /*@ assert \initialized(&x); */ + { + int __gen_e_acsl_initialized; + __gen_e_acsl_initialized = __e_acsl_initialized((void *)(& x), + sizeof(int)); + __e_acsl_assert(__gen_e_acsl_initialized,(char *)"Assertion", + (char *)"main",(char *)"\\initialized(&x)",56); + } + /*@ assert \initialized(&y); */ + { + int __gen_e_acsl_initialized_2; + __gen_e_acsl_initialized_2 = __e_acsl_initialized((void *)(& y), + sizeof(int)); + __e_acsl_assert(__gen_e_acsl_initialized_2,(char *)"Assertion", + (char *)"main",(char *)"\\initialized(&y)",57); + } + tmp = vol(6,1); + __e_acsl_delete_block((void *)(& y)); + __e_acsl_delete_block((void *)(& x)); + __e_acsl_memory_clean(); + return tmp; +} + +/*@ requires \valid(p); */ +int __gen_e_acsl_instrument2(int *p) +{ + int __retres; + { + int __gen_e_acsl_valid; + __e_acsl_store_block((void *)(& p),(size_t)8); + __gen_e_acsl_valid = __e_acsl_valid((void *)p,sizeof(int),(void *)p, + (void *)(& p)); + __e_acsl_assert(__gen_e_acsl_valid,(char *)"Precondition", + (char *)"instrument2",(char *)"\\valid(p)",29); + } + __retres = instrument2(p); + __e_acsl_delete_block((void *)(& p)); + return __retres; +} + +/*@ requires \valid(p); */ +int __gen_e_acsl_uninstrument2(int *p) +{ + int __retres; + { + int __gen_e_acsl_valid; + __gen_e_acsl_valid = __e_acsl_valid((void *)p,sizeof(int),(void *)p, + (void *)(& p)); + __e_acsl_assert(__gen_e_acsl_valid,(char *)"Precondition", + (char *)"uninstrument2",(char *)"\\valid(p)",14); + } + __e_acsl_sound_verdict = 0; + __retres = uninstrument2(p); + return __retres; +} + +int __gen_e_acsl_uninstrument1(int *p) +{ + int __retres; + __e_acsl_sound_verdict = 0; + __retres = uninstrument1(p); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/special/oracle_ci/gen_e-acsl-valid.c b/src/plugins/e-acsl/tests/special/oracle_ci/gen_e-acsl-valid.c new file mode 100644 index 0000000000000000000000000000000000000000..e8b9353fea7d19ba27ac7b4b670716a1d84d9276 --- /dev/null +++ b/src/plugins/e-acsl/tests/special/oracle_ci/gen_e-acsl-valid.c @@ -0,0 +1,211 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +extern int __e_acsl_sound_verdict; + +/*@ requires \valid(y); + requires *x ≥ 0; + ensures *\old(x) ≡ \old(*x) + 1; + assigns *x; + assigns *x \from *x, x; + + behavior b1: + assumes *x ≡ 1; + ensures *\old(x) < 0; + assigns \nothing; + + behavior b2: + assumes *x ≡ 0; + ensures *\old(x) ≡ 1; + + complete behaviors b2, b1; + disjoint behaviors b1, b2; + */ +void __gen_e_acsl_f(int *x, int *y); + +void f(int *x, int *y) +{ + /*@ requires *x ≥ 0; + ensures 2 ≥ 1; + assigns *x; */ + { + { + int __gen_e_acsl_valid_read; + __e_acsl_store_block((void *)(& y),(size_t)8); + __e_acsl_store_block((void *)(& x),(size_t)8); + __gen_e_acsl_valid_read = __e_acsl_valid_read((void *)x,sizeof(int), + (void *)x,(void *)(& x)); + __e_acsl_assert(__gen_e_acsl_valid_read,(char *)"RTE",(char *)"f", + (char *)"mem_access: \\valid_read(x)",27); + __e_acsl_assert(*x >= 0,(char *)"Precondition",(char *)"f", + (char *)"*x >= 0",27); + } + __e_acsl_initialize((void *)x,sizeof(int)); + (*x) ++; + __e_acsl_assert(1,(char *)"Postcondition",(char *)"f",(char *)"2 >= 1", + 28); + } + { + int i = 0; + /*@ loop variant 2 - i; */ + { + { + int __gen_e_acsl_and; + if (0 <= i) __gen_e_acsl_and = i <= 1; else __gen_e_acsl_and = 0; + __e_acsl_assert(__gen_e_acsl_and,(char *)"Invariant",(char *)"f", + (char *)"0 <= i <= 1",31); + } + /*@ loop invariant 0 ≤ i ≤ 1; */ + while (i < 1) { + /*@ assert 1 ≡ 1; */ + __e_acsl_assert(1,(char *)"Assertion",(char *)"f",(char *)"1 == 1", + 33); + /*@ assert \valid(y); */ + { + int __gen_e_acsl_valid; + __gen_e_acsl_valid = __e_acsl_valid((void *)y,sizeof(int), + (void *)y,(void *)(& y)); + __e_acsl_assert(__gen_e_acsl_valid,(char *)"Assertion",(char *)"f", + (char *)"\\valid(y)",33); + } + { + int __gen_e_acsl_and_2; + i ++; + if (0 <= i) __gen_e_acsl_and_2 = i <= 1; + else __gen_e_acsl_and_2 = 0; + __e_acsl_assert(__gen_e_acsl_and_2,(char *)"Invariant",(char *)"f", + (char *)"0 <= i <= 1",31); + } + } + } + } + __e_acsl_delete_block((void *)(& y)); + __e_acsl_delete_block((void *)(& x)); + return; +} + +int main(void) +{ + int __retres; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + int x = 0; + __e_acsl_store_block((void *)(& x),(size_t)4); + __e_acsl_full_init((void *)(& x)); + int *y = malloc(sizeof(int)); + __e_acsl_store_block((void *)(& y),(size_t)8); + __e_acsl_full_init((void *)(& y)); + __gen_e_acsl_f(& x,y); + __retres = 0; + __e_acsl_delete_block((void *)(& y)); + __e_acsl_delete_block((void *)(& x)); + __e_acsl_memory_clean(); + return __retres; +} + +/*@ requires \valid(y); + requires *x ≥ 0; + ensures *\old(x) ≡ \old(*x) + 1; + assigns *x; + assigns *x \from *x, x; + + behavior b1: + assumes *x ≡ 1; + ensures *\old(x) < 0; + assigns \nothing; + + behavior b2: + assumes *x ≡ 0; + ensures *\old(x) ≡ 1; + + complete behaviors b2, b1; + disjoint behaviors b1, b2; + */ +void __gen_e_acsl_f(int *x, int *y) +{ + long __gen_e_acsl_at_6; + int *__gen_e_acsl_at_5; + int *__gen_e_acsl_at_4; + int __gen_e_acsl_at_3; + int *__gen_e_acsl_at_2; + int __gen_e_acsl_at; + { + int __gen_e_acsl_valid_read_5; + __gen_e_acsl_valid_read_5 = __e_acsl_valid_read((void *)x,sizeof(int), + (void *)x,(void *)(& x)); + __e_acsl_assert(__gen_e_acsl_valid_read_5,(char *)"RTE",(char *)"f", + (char *)"mem_access: \\valid_read(x)",14); + __gen_e_acsl_at_6 = (long)*x; + } + __gen_e_acsl_at_5 = x; + __gen_e_acsl_at_4 = x; + { + int __gen_e_acsl_valid_read_3; + __gen_e_acsl_valid_read_3 = __e_acsl_valid_read((void *)x,sizeof(int), + (void *)x,(void *)(& x)); + __e_acsl_assert(__gen_e_acsl_valid_read_3,(char *)"RTE",(char *)"f", + (char *)"mem_access: \\valid_read(x)",21); + __gen_e_acsl_at_3 = *x == 0; + } + __gen_e_acsl_at_2 = x; + { + int __gen_e_acsl_valid_read; + __gen_e_acsl_valid_read = __e_acsl_valid_read((void *)x,sizeof(int), + (void *)x,(void *)(& x)); + __e_acsl_assert(__gen_e_acsl_valid_read,(char *)"RTE",(char *)"f", + (char *)"mem_access: \\valid_read(x)",17); + __gen_e_acsl_at = *x == 1; + } + { + int __gen_e_acsl_valid; + __e_acsl_store_block((void *)(& y),(size_t)8); + __e_acsl_store_block((void *)(& x),(size_t)8); + __gen_e_acsl_valid = __e_acsl_valid((void *)y,sizeof(int),(void *)y, + (void *)(& y)); + __e_acsl_assert(__gen_e_acsl_valid,(char *)"Precondition",(char *)"f", + (char *)"\\valid(y)",12); + __e_acsl_assert(*x >= 0,(char *)"Precondition",(char *)"f", + (char *)"*x >= 0",13); + } + f(x,y); + { + int __gen_e_acsl_implies; + int __gen_e_acsl_implies_2; + if (! __gen_e_acsl_at) __gen_e_acsl_implies = 1; + else { + int __gen_e_acsl_valid_read_2; + __gen_e_acsl_valid_read_2 = __e_acsl_valid_read((void *)__gen_e_acsl_at_2, + sizeof(int), + (void *)__gen_e_acsl_at_2, + (void *)(& __gen_e_acsl_at_2)); + __e_acsl_assert(__gen_e_acsl_valid_read_2,(char *)"RTE",(char *)"f", + (char *)"mem_access: \\valid_read(__gen_e_acsl_at_2)", + 19); + __gen_e_acsl_implies = *__gen_e_acsl_at_2 < 0; + } + __e_acsl_assert(__gen_e_acsl_implies,(char *)"Postcondition",(char *)"f", + (char *)"\\old(*x == 1) ==> *\\old(x) < 0",19); + if (! __gen_e_acsl_at_3) __gen_e_acsl_implies_2 = 1; + else { + int __gen_e_acsl_valid_read_4; + __gen_e_acsl_valid_read_4 = __e_acsl_valid_read((void *)__gen_e_acsl_at_4, + sizeof(int), + (void *)__gen_e_acsl_at_4, + (void *)(& __gen_e_acsl_at_4)); + __e_acsl_assert(__gen_e_acsl_valid_read_4,(char *)"RTE",(char *)"f", + (char *)"mem_access: \\valid_read(__gen_e_acsl_at_4)", + 22); + __gen_e_acsl_implies_2 = *__gen_e_acsl_at_4 == 1; + } + __e_acsl_assert(__gen_e_acsl_implies_2,(char *)"Postcondition", + (char *)"f",(char *)"\\old(*x == 0) ==> *\\old(x) == 1", + 22); + __e_acsl_assert((long)*__gen_e_acsl_at_5 == __gen_e_acsl_at_6 + 1L, + (char *)"Postcondition",(char *)"f", + (char *)"*\\old(x) == \\old(*x) + 1",14); + __e_acsl_delete_block((void *)(& y)); + __e_acsl_delete_block((void *)(& x)); + return; + } +} + + diff --git a/src/plugins/e-acsl/tests/special/oracle_dev/builtin.res.oracle b/src/plugins/e-acsl/tests/special/oracle_dev/builtin.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..89a3dd0cebac8883f2d4148a0a74b4346b5aa97b --- /dev/null +++ b/src/plugins/e-acsl/tests/special/oracle_dev/builtin.res.oracle @@ -0,0 +1,6 @@ +[kernel] Parsing tests/special/builtin.i (no preprocessing) +[kernel:annot-error] tests/special/builtin.i:9: Warning: + unbound function incr. Ignoring logic specification of function f +[kernel] User Error: warning annot-error treated as fatal error. +[kernel] User Error: stopping on file "tests/special/builtin.i" that has errors. +[kernel] Frama-C aborted: invalid user input. diff --git a/src/plugins/e-acsl/tests/special/oracle_dev/e-acsl-functions.res.oracle b/src/plugins/e-acsl/tests/special/oracle_dev/e-acsl-functions.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..0e725129643c7b30e93ea6195c25aba9922e6972 --- /dev/null +++ b/src/plugins/e-acsl/tests/special/oracle_dev/e-acsl-functions.res.oracle @@ -0,0 +1,5 @@ +[kernel] User Error: cannot load plug-in 'frama-c-e_acsl': cannot load module + Details: error loading shared library: Dynlink.Error (Dynlink.Cannot_open_dll "Failure(\"./top/E_ACSL.cmxs: cannot open shared object file: No such file or directory\")") +[kernel] User Error: compilation of './tests/print.ml' failed +[kernel] User Error: Deferred error message was emitted during execution. See above messages for more information. +[kernel] Frama-C aborted: invalid user input. diff --git a/src/plugins/e-acsl/tests/special/oracle_dev/e-acsl-instrument.res.oracle b/src/plugins/e-acsl/tests/special/oracle_dev/e-acsl-instrument.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..b26c0b6174b2a72251653d396860c71ab5ba9664 --- /dev/null +++ b/src/plugins/e-acsl/tests/special/oracle_dev/e-acsl-instrument.res.oracle @@ -0,0 +1,4 @@ +[kernel] User Error: cannot load plug-in 'frama-c-e_acsl': cannot load module + Details: error loading shared library: Dynlink.Error (Dynlink.Cannot_open_dll "Failure(\"./top/E_ACSL.cmxs: cannot open shared object file: No such file or directory\")") +[kernel] User Error: Deferred error message was emitted during execution. See above messages for more information. +[kernel] Frama-C aborted: invalid user input. diff --git a/src/plugins/e-acsl/tests/special/oracle_dev/e-acsl-valid.res.oracle b/src/plugins/e-acsl/tests/special/oracle_dev/e-acsl-valid.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..ccf69854a1a6f0658c365947a9e8c53bcb5c9db5 --- /dev/null +++ b/src/plugins/e-acsl/tests/special/oracle_dev/e-acsl-valid.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/special/e-acsl-valid.c (with preprocessing) diff --git a/src/plugins/e-acsl/tests/special/test_config_dev b/src/plugins/e-acsl/tests/special/test_config_dev new file mode 100644 index 0000000000000000000000000000000000000000..bbceafbed9b9fb0880caf31fe392053620ea2cbb --- /dev/null +++ b/src/plugins/e-acsl/tests/special/test_config_dev @@ -0,0 +1 @@ +DONTRUN: diff --git a/src/plugins/e-acsl/tests/temporal/oracle_ci/gen_t_addr-by-val.c b/src/plugins/e-acsl/tests/temporal/oracle_ci/gen_t_addr-by-val.c new file mode 100644 index 0000000000000000000000000000000000000000..f9e0c4bc1f7020632b28278b5878d19a273003ff --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/oracle_ci/gen_t_addr-by-val.c @@ -0,0 +1,37 @@ +/* Generated by Frama-C */ +#include "stdint.h" +#include "stdio.h" +#include "stdlib.h" +int main(int argc, char **argv) +{ + int __retres; + char *p; + int *q; + __e_acsl_memory_init(& argc,& argv,(size_t)8); + __e_acsl_store_block((void *)(& q),(size_t)8); + __e_acsl_store_block((void *)(& p),(size_t)8); + uintptr_t addr = (unsigned long)(& argc); + __e_acsl_store_block((void *)(& addr),(size_t)8); + __e_acsl_full_init((void *)(& addr)); + __e_acsl_temporal_store_nblock((void *)(& q),(void *)(& argc)); + __e_acsl_full_init((void *)(& q)); + q = & argc; + __e_acsl_temporal_store_nblock((void *)(& p),(void *)((char *)addr)); + __e_acsl_full_init((void *)(& p)); + p = (char *)addr; + __e_acsl_temporal_store_nblock((void *)(& p),(void *)0x123456); + __e_acsl_full_init((void *)(& p)); + p = (char *)0x123456; + __e_acsl_temporal_store_nreferent((void *)(& p),(void *)(& q)); + __e_acsl_full_init((void *)(& p)); + p = (char *)q; + __retres = 0; + __e_acsl_delete_block((void *)(& argc)); + __e_acsl_delete_block((void *)(& q)); + __e_acsl_delete_block((void *)(& p)); + __e_acsl_delete_block((void *)(& addr)); + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/temporal/oracle_ci/gen_t_args.c b/src/plugins/e-acsl/tests/temporal/oracle_ci/gen_t_args.c new file mode 100644 index 0000000000000000000000000000000000000000..2b08cabc5205e650549e34f8d5a6308d15b97645 --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/oracle_ci/gen_t_args.c @@ -0,0 +1,54 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +int main(int argc, char const **argv) +{ + int __retres; + __e_acsl_memory_init(& argc,(char ***)(& argv),(size_t)8); + /*@ assert \valid(&argc); */ + { + int __gen_e_acsl_valid; + __gen_e_acsl_valid = __e_acsl_valid((void *)(& argc),sizeof(int), + (void *)(& argc),(void *)0); + __e_acsl_assert(__gen_e_acsl_valid,(char *)"Assertion",(char *)"main", + (char *)"\\valid(&argc)",8); + } + /*@ assert \valid(argv); */ + { + int __gen_e_acsl_valid_2; + __gen_e_acsl_valid_2 = __e_acsl_valid((void *)argv,sizeof(char const *), + (void *)argv,(void *)(& argv)); + __e_acsl_assert(__gen_e_acsl_valid_2,(char *)"Assertion",(char *)"main", + (char *)"\\valid(argv)",9); + } + /*@ assert \valid(*argv); */ + { + int __gen_e_acsl_initialized; + int __gen_e_acsl_and; + __gen_e_acsl_initialized = __e_acsl_initialized((void *)argv, + sizeof(char const *)); + if (__gen_e_acsl_initialized) { + int __gen_e_acsl_valid_read; + int __gen_e_acsl_valid_3; + __gen_e_acsl_valid_read = __e_acsl_valid_read((void *)argv, + sizeof(char const *), + (void *)argv, + (void *)(& argv)); + __e_acsl_assert(__gen_e_acsl_valid_read,(char *)"RTE",(char *)"main", + (char *)"mem_access: \\valid_read(argv)",10); + __gen_e_acsl_valid_3 = __e_acsl_valid((void *)*argv,sizeof(char const), + (void *)*argv,(void *)argv); + __gen_e_acsl_and = __gen_e_acsl_valid_3; + } + else __gen_e_acsl_and = 0; + __e_acsl_assert(__gen_e_acsl_and,(char *)"Assertion",(char *)"main", + (char *)"\\valid(*argv)",10); + } + __retres = 0; + __e_acsl_delete_block((void *)(& argv)); + __e_acsl_delete_block((void *)(& argc)); + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/temporal/oracle_ci/gen_t_array.c b/src/plugins/e-acsl/tests/temporal/oracle_ci/gen_t_array.c new file mode 100644 index 0000000000000000000000000000000000000000..ebf6b609885673fda98d5c46825cab468eb8fa24 --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/oracle_ci/gen_t_array.c @@ -0,0 +1,80 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +int main(void) +{ + int __retres; + int *src[3]; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + __e_acsl_store_block((void *)(src),(size_t)24); + int a = 111; + __e_acsl_store_block((void *)(& a),(size_t)4); + __e_acsl_full_init((void *)(& a)); + int b = 222; + __e_acsl_store_block((void *)(& b),(size_t)4); + __e_acsl_full_init((void *)(& b)); + __e_acsl_temporal_store_nblock((void *)(src),(void *)(& a)); + __e_acsl_initialize((void *)(src),sizeof(int *)); + src[0] = & a; + __e_acsl_temporal_store_nblock((void *)(& src[1]),(void *)(& b)); + __e_acsl_initialize((void *)(& src[1]),sizeof(int *)); + src[1] = & b; + /*@ assert \valid(src[0]); */ + { + int __gen_e_acsl_initialized; + int __gen_e_acsl_and; + __gen_e_acsl_initialized = __e_acsl_initialized((void *)(src), + sizeof(int *)); + if (__gen_e_acsl_initialized) { + int __gen_e_acsl_valid; + __gen_e_acsl_valid = __e_acsl_valid((void *)src[0],sizeof(int), + (void *)src[0],(void *)(src)); + __gen_e_acsl_and = __gen_e_acsl_valid; + } + else __gen_e_acsl_and = 0; + __e_acsl_assert(__gen_e_acsl_and,(char *)"Assertion",(char *)"main", + (char *)"\\valid(src[0])",13); + } + /*@ assert \valid(src[1]); */ + { + int __gen_e_acsl_initialized_2; + int __gen_e_acsl_and_2; + __gen_e_acsl_initialized_2 = __e_acsl_initialized((void *)(& src[1]), + sizeof(int *)); + if (__gen_e_acsl_initialized_2) { + int __gen_e_acsl_valid_2; + __gen_e_acsl_valid_2 = __e_acsl_valid((void *)src[1],sizeof(int), + (void *)src[1], + (void *)(& src[1])); + __gen_e_acsl_and_2 = __gen_e_acsl_valid_2; + } + else __gen_e_acsl_and_2 = 0; + __e_acsl_assert(__gen_e_acsl_and_2,(char *)"Assertion",(char *)"main", + (char *)"\\valid(src[1])",14); + } + /*@ assert ¬\valid(src[2]); */ + { + int __gen_e_acsl_initialized_3; + int __gen_e_acsl_and_3; + __gen_e_acsl_initialized_3 = __e_acsl_initialized((void *)(& src[2]), + sizeof(int *)); + if (__gen_e_acsl_initialized_3) { + int __gen_e_acsl_valid_3; + __gen_e_acsl_valid_3 = __e_acsl_valid((void *)src[2],sizeof(int), + (void *)src[2], + (void *)(& src[2])); + __gen_e_acsl_and_3 = __gen_e_acsl_valid_3; + } + else __gen_e_acsl_and_3 = 0; + __e_acsl_assert(! __gen_e_acsl_and_3,(char *)"Assertion",(char *)"main", + (char *)"!\\valid(src[2])",15); + } + __retres = 0; + __e_acsl_delete_block((void *)(src)); + __e_acsl_delete_block((void *)(& b)); + __e_acsl_delete_block((void *)(& a)); + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/temporal/oracle_ci/gen_t_char.c b/src/plugins/e-acsl/tests/temporal/oracle_ci/gen_t_char.c new file mode 100644 index 0000000000000000000000000000000000000000..9f33d50ec0f6cc65b9a325863bcae783756bd39f --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/oracle_ci/gen_t_char.c @@ -0,0 +1,66 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +int main(int argc, char const **argv) +{ + int __retres; + __e_acsl_memory_init(& argc,(char ***)(& argv),(size_t)8); + char a __attribute__((__aligned__(4))) = (char)'1'; + __e_acsl_store_block((void *)(& a),(size_t)1); + __e_acsl_full_init((void *)(& a)); + char b __attribute__((__aligned__(4))) = (char)'2'; + __e_acsl_store_block((void *)(& b),(size_t)1); + __e_acsl_full_init((void *)(& b)); + char *p = & a; + __e_acsl_store_block((void *)(& p),(size_t)8); + __e_acsl_full_init((void *)(& p)); + __e_acsl_temporal_store_nblock((void *)(& p),(void *)(& a)); + char *q = & b; + __e_acsl_store_block((void *)(& q),(size_t)8); + __e_acsl_full_init((void *)(& q)); + __e_acsl_temporal_store_nblock((void *)(& q),(void *)(& b)); + __e_acsl_temporal_store_nreferent((void *)(& p),(void *)(& q)); + __e_acsl_full_init((void *)(& p)); + p = q; + /*@ assert \valid(p); */ + { + int __gen_e_acsl_initialized; + int __gen_e_acsl_and; + __gen_e_acsl_initialized = __e_acsl_initialized((void *)(& p), + sizeof(char *)); + if (__gen_e_acsl_initialized) { + int __gen_e_acsl_valid; + __gen_e_acsl_valid = __e_acsl_valid((void *)p,sizeof(char),(void *)p, + (void *)(& p)); + __gen_e_acsl_and = __gen_e_acsl_valid; + } + else __gen_e_acsl_and = 0; + __e_acsl_assert(__gen_e_acsl_and,(char *)"Assertion",(char *)"main", + (char *)"\\valid(p)",17); + } + /*@ assert \valid(q); */ + { + int __gen_e_acsl_initialized_2; + int __gen_e_acsl_and_2; + __gen_e_acsl_initialized_2 = __e_acsl_initialized((void *)(& q), + sizeof(char *)); + if (__gen_e_acsl_initialized_2) { + int __gen_e_acsl_valid_2; + __gen_e_acsl_valid_2 = __e_acsl_valid((void *)q,sizeof(char),(void *)q, + (void *)(& q)); + __gen_e_acsl_and_2 = __gen_e_acsl_valid_2; + } + else __gen_e_acsl_and_2 = 0; + __e_acsl_assert(__gen_e_acsl_and_2,(char *)"Assertion",(char *)"main", + (char *)"\\valid(q)",18); + } + __retres = 0; + __e_acsl_delete_block((void *)(& q)); + __e_acsl_delete_block((void *)(& p)); + __e_acsl_delete_block((void *)(& b)); + __e_acsl_delete_block((void *)(& a)); + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/temporal/oracle_ci/gen_t_darray.c b/src/plugins/e-acsl/tests/temporal/oracle_ci/gen_t_darray.c new file mode 100644 index 0000000000000000000000000000000000000000..2f4b60632e3efb4f252bf3c81903e5134a3ff1a7 --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/oracle_ci/gen_t_darray.c @@ -0,0 +1,121 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +void area_triangle(double (*vertices)[4]) +{ + /*@ assert rte: mem_access: \valid_read((double *)*(vertices + 0)); */ + { + int __gen_e_acsl_valid_read; + __e_acsl_store_block((void *)(& vertices),(size_t)8); + __e_acsl_temporal_pull_parameter((void *)(& vertices),0U,8UL); + __gen_e_acsl_valid_read = __e_acsl_valid_read((void *)(*(vertices + 0)), + sizeof(double), + (void *)(*(vertices + 0)), + (void *)(*(vertices + 0))); + __e_acsl_assert(__gen_e_acsl_valid_read,(char *)"Assertion", + (char *)"area_triangle", + (char *)"rte: mem_access: \\valid_read((double *)*(vertices + 0))", + 6); + } + /*@ assert rte: mem_access: \valid_read((double *)*(vertices + 1)); */ + { + int __gen_e_acsl_valid_read_2; + __gen_e_acsl_valid_read_2 = __e_acsl_valid_read((void *)(*(vertices + 1)), + sizeof(double), + (void *)(*(vertices + 1)), + (void *)(*(vertices + 1))); + __e_acsl_assert(__gen_e_acsl_valid_read_2,(char *)"Assertion", + (char *)"area_triangle", + (char *)"rte: mem_access: \\valid_read((double *)*(vertices + 1))", + 7); + } + __e_acsl_delete_block((void *)(& vertices)); + return; +} + +void abe_matrix(double (*vertices)[4]) +{ + __e_acsl_store_block((void *)(& vertices),(size_t)8); + __e_acsl_temporal_pull_parameter((void *)(& vertices),0U,8UL); + __e_acsl_temporal_reset_parameters(); + __e_acsl_temporal_reset_return(); + __e_acsl_temporal_save_nreferent_parameter((void *)(& vertices),0U); + area_triangle(vertices); + __e_acsl_delete_block((void *)(& vertices)); + return; +} + +double Vertices[3][4]; +double Vertices2[3][4] = {}; +void __e_acsl_globals_init(void) +{ + static char __e_acsl_already_run = 0; + if (! __e_acsl_already_run) { + __e_acsl_already_run = 1; + __e_acsl_store_block((void *)(Vertices2),(size_t)96); + __e_acsl_full_init((void *)(& Vertices2)); + __e_acsl_store_block((void *)(Vertices),(size_t)96); + __e_acsl_full_init((void *)(& Vertices)); + } + return; +} + +int main(int argc, char const **argv) +{ + int __retres; + double vertices2[3][4]; + double vertices3[3][4]; + double triple_vertices[2][3][4]; + __e_acsl_memory_init(& argc,(char ***)(& argv),(size_t)8); + __e_acsl_globals_init(); + __e_acsl_store_block((void *)(triple_vertices),(size_t)192); + __e_acsl_store_block((void *)(vertices3),(size_t)96); + __e_acsl_store_block((void *)(vertices2),(size_t)96); + double vertices[3][4] = + {{1.0, 2.0, 3.0, 4.0}, {5.0, 6.0, 7.0, 8.0}, {9.0, 10.0, 11.0, 12.0}}; + __e_acsl_store_block((void *)(vertices),(size_t)96); + __e_acsl_full_init((void *)(& vertices)); + double triple_vertices2[2][3][4] = {}; + __e_acsl_store_block((void *)(triple_vertices2),(size_t)192); + __e_acsl_full_init((void *)(& triple_vertices2)); + __e_acsl_temporal_reset_parameters(); + __e_acsl_temporal_reset_return(); + __e_acsl_temporal_save_nblock_parameter((void *)(vertices),0U); + abe_matrix(vertices); + __e_acsl_temporal_reset_parameters(); + __e_acsl_temporal_reset_return(); + __e_acsl_temporal_save_nblock_parameter((void *)(vertices2),0U); + abe_matrix(vertices2); + __e_acsl_temporal_reset_parameters(); + __e_acsl_temporal_reset_return(); + __e_acsl_temporal_save_nblock_parameter((void *)(vertices3),0U); + abe_matrix(vertices3); + __e_acsl_temporal_reset_parameters(); + __e_acsl_temporal_reset_return(); + __e_acsl_temporal_save_nblock_parameter((void *)(Vertices),0U); + abe_matrix(Vertices); + __e_acsl_temporal_reset_parameters(); + __e_acsl_temporal_reset_return(); + __e_acsl_temporal_save_nblock_parameter((void *)(Vertices2),0U); + abe_matrix(Vertices2); + __e_acsl_temporal_reset_parameters(); + __e_acsl_temporal_reset_return(); + __e_acsl_temporal_save_nblock_parameter((void *)(triple_vertices[0]),0U); + abe_matrix(triple_vertices[0]); + __e_acsl_temporal_reset_parameters(); + __e_acsl_temporal_reset_return(); + __e_acsl_temporal_save_nblock_parameter((void *)(triple_vertices2[0]),0U); + abe_matrix(triple_vertices2[0]); + __retres = 0; + __e_acsl_delete_block((void *)(Vertices2)); + __e_acsl_delete_block((void *)(Vertices)); + __e_acsl_delete_block((void *)(triple_vertices2)); + __e_acsl_delete_block((void *)(triple_vertices)); + __e_acsl_delete_block((void *)(vertices3)); + __e_acsl_delete_block((void *)(vertices2)); + __e_acsl_delete_block((void *)(vertices)); + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/temporal/oracle_ci/gen_t_dpointer.c b/src/plugins/e-acsl/tests/temporal/oracle_ci/gen_t_dpointer.c new file mode 100644 index 0000000000000000000000000000000000000000..8a600eed354a833a550e737cc928c75e20c9d93a --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/oracle_ci/gen_t_dpointer.c @@ -0,0 +1,96 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +int main(void) +{ + int __retres; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + __e_acsl_temporal_reset_parameters(); + __e_acsl_temporal_reset_return(); + int **p = malloc(sizeof(int *) * (unsigned long)3); + __e_acsl_store_block((void *)(& p),(size_t)8); + __e_acsl_full_init((void *)(& p)); + __e_acsl_temporal_store_nblock((void *)(& p),(void *)*(& p)); + int i = 0; + while (i < 3) { + /*@ assert \valid(p + i); */ + { + int __gen_e_acsl_valid; + __gen_e_acsl_valid = __e_acsl_valid((void *)(p + i),sizeof(int *), + (void *)p,(void *)(& p)); + __e_acsl_assert(__gen_e_acsl_valid,(char *)"Assertion",(char *)"main", + (char *)"\\valid(p + i)",12); + } + __e_acsl_temporal_reset_parameters(); + __e_acsl_temporal_reset_return(); + __e_acsl_initialize((void *)(p + i),sizeof(int *)); + *(p + i) = (int *)malloc(sizeof(int)); + /*@ assert Eva: initialization: \initialized(p + i); */ + __e_acsl_temporal_store_nblock((void *)(p + i),(void *)*(p + i)); + /*@ assert \valid(*(p + i)); */ + { + int __gen_e_acsl_initialized; + int __gen_e_acsl_and; + __gen_e_acsl_initialized = __e_acsl_initialized((void *)(p + i), + sizeof(int *)); + if (__gen_e_acsl_initialized) { + int __gen_e_acsl_valid_read; + int __gen_e_acsl_valid_2; + __gen_e_acsl_valid_read = __e_acsl_valid_read((void *)(p + i), + sizeof(int *), + (void *)p, + (void *)(& p)); + __e_acsl_assert(__gen_e_acsl_valid_read,(char *)"RTE",(char *)"main", + (char *)"mem_access: \\valid_read(p + i)",14); + /*@ assert Eva: initialization: \initialized(p + i); */ + __gen_e_acsl_valid_2 = __e_acsl_valid((void *)*(p + i),sizeof(int), + (void *)*(p + i), + (void *)(p + i)); + __gen_e_acsl_and = __gen_e_acsl_valid_2; + } + else __gen_e_acsl_and = 0; + __e_acsl_assert(__gen_e_acsl_and,(char *)"Assertion",(char *)"main", + (char *)"\\valid(*(p + i))",14); + } + i ++; + } + __e_acsl_temporal_reset_parameters(); + __e_acsl_temporal_reset_return(); + __e_acsl_temporal_save_nreferent_parameter((void *)(p + 2),0U); + /*@ assert Eva: initialization: \initialized(p + 2); */ + free((void *)*(p + 2)); + __e_acsl_temporal_reset_parameters(); + __e_acsl_temporal_reset_return(); + malloc(sizeof(int)); + /*@ assert ¬\valid(*(p + 2)); */ + { + int __gen_e_acsl_initialized_2; + int __gen_e_acsl_and_2; + __gen_e_acsl_initialized_2 = __e_acsl_initialized((void *)(p + 2), + sizeof(int *)); + if (__gen_e_acsl_initialized_2) { + int __gen_e_acsl_valid_read_2; + int __gen_e_acsl_valid_3; + __gen_e_acsl_valid_read_2 = __e_acsl_valid_read((void *)(p + 2), + sizeof(int *), + (void *)p, + (void *)(& p)); + __e_acsl_assert(__gen_e_acsl_valid_read_2,(char *)"RTE",(char *)"main", + (char *)"mem_access: \\valid_read(p + 2)",20); + /*@ assert Eva: dangling_pointer: ¬\dangling(p + 2); */ + __gen_e_acsl_valid_3 = __e_acsl_valid((void *)*(p + 2),sizeof(int), + (void *)*(p + 2),(void *)( + p + 2)); + __gen_e_acsl_and_2 = __gen_e_acsl_valid_3; + } + else __gen_e_acsl_and_2 = 0; + __e_acsl_assert(! __gen_e_acsl_and_2,(char *)"Assertion",(char *)"main", + (char *)"!\\valid(*(p + 2))",20); + } + __retres = 0; + __e_acsl_delete_block((void *)(& p)); + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/temporal/oracle_ci/gen_t_fptr.c b/src/plugins/e-acsl/tests/temporal/oracle_ci/gen_t_fptr.c new file mode 100644 index 0000000000000000000000000000000000000000..837b97facf22a3adac0f651c28c979335402aba4 --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/oracle_ci/gen_t_fptr.c @@ -0,0 +1,72 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +int *foo(int *p) +{ + int *q = p; + return q; +} + +void __e_acsl_globals_init(void) +{ + static char __e_acsl_already_run = 0; + if (! __e_acsl_already_run) { + __e_acsl_already_run = 1; + __e_acsl_store_block((void *)(& foo),(size_t)1); + __e_acsl_full_init((void *)(& foo)); + } + return; +} + +int main(int argc, char const **argv) +{ + int __retres; + int *q; + __e_acsl_memory_init(& argc,(char ***)(& argv),(size_t)8); + __e_acsl_globals_init(); + __e_acsl_store_block((void *)(& q),(size_t)8); + int *p = & argc; + __e_acsl_store_block((void *)(& p),(size_t)8); + __e_acsl_full_init((void *)(& p)); + __e_acsl_temporal_store_nblock((void *)(& p),(void *)(& argc)); + int *(*fp)(int *) = & foo; + __e_acsl_store_block((void *)(& fp),(size_t)8); + __e_acsl_full_init((void *)(& fp)); + __e_acsl_temporal_store_nblock((void *)(& fp),(void *)(& foo)); + __e_acsl_temporal_store_nblock((void *)(& fp),(void *)(& foo)); + __e_acsl_full_init((void *)(& fp)); + fp = & foo; + /*@ assert \valid_function(fp); */ ; + __e_acsl_temporal_reset_parameters(); + __e_acsl_temporal_reset_return(); + __e_acsl_temporal_save_nreferent_parameter((void *)(& p),0U); + __e_acsl_full_init((void *)(& q)); + q = (*fp)(p); + __e_acsl_temporal_store_nblock((void *)(& q),(void *)*(& q)); + /*@ assert \valid(q); */ + { + int __gen_e_acsl_initialized; + int __gen_e_acsl_and; + __gen_e_acsl_initialized = __e_acsl_initialized((void *)(& q), + sizeof(int *)); + if (__gen_e_acsl_initialized) { + int __gen_e_acsl_valid; + __gen_e_acsl_valid = __e_acsl_valid((void *)q,sizeof(int),(void *)q, + (void *)(& q)); + __gen_e_acsl_and = __gen_e_acsl_valid; + } + else __gen_e_acsl_and = 0; + __e_acsl_assert(__gen_e_acsl_and,(char *)"Assertion",(char *)"main", + (char *)"\\valid(q)",20); + } + __retres = 0; + __e_acsl_delete_block((void *)(& argc)); + __e_acsl_delete_block((void *)(& foo)); + __e_acsl_delete_block((void *)(& fp)); + __e_acsl_delete_block((void *)(& q)); + __e_acsl_delete_block((void *)(& p)); + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/temporal/oracle_ci/gen_t_fun_lib.c b/src/plugins/e-acsl/tests/temporal/oracle_ci/gen_t_fun_lib.c new file mode 100644 index 0000000000000000000000000000000000000000..26fe07d6ba1546ca386355d8c1933139da2fe53b --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/oracle_ci/gen_t_fun_lib.c @@ -0,0 +1,150 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +/*@ assigns \result, *(x_0 + (0 ..)), *(x_1 + (0 ..)); + assigns \result \from *(x_0 + (0 ..)), *(x_1 + (0 ..)); + assigns *(x_0 + (0 ..)) \from *(x_0 + (0 ..)), *(x_1 + (0 ..)); + assigns *(x_1 + (0 ..)) \from *(x_0 + (0 ..)), *(x_1 + (0 ..)); + */ +extern int ( /* missing proto */ realpath)(char *x_0, char *x_1); + +int main(void) +{ + int __retres; + int tmp_0; + int tmp_1; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + __e_acsl_store_block((void *)(& tmp_1),(size_t)4); + __e_acsl_store_block((void *)(& tmp_0),(size_t)4); + char *c = (char *)"."; + __e_acsl_temporal_reset_parameters(); + __e_acsl_temporal_reset_return(); + char *p = malloc((unsigned long)256); + __e_acsl_store_block((void *)(& p),(size_t)8); + __e_acsl_full_init((void *)(& p)); + __e_acsl_temporal_store_nblock((void *)(& p),(void *)*(& p)); + char *q = (char *)0; + __e_acsl_store_block((void *)(& q),(size_t)8); + __e_acsl_full_init((void *)(& q)); + __e_acsl_temporal_store_nblock((void *)(& q),(void *)0); + __e_acsl_temporal_reset_parameters(); + __e_acsl_temporal_reset_return(); + __e_acsl_full_init((void *)(& q)); + q = (char *)malloc((unsigned long)256); + __e_acsl_temporal_store_nblock((void *)(& q),(void *)*(& q)); + /*@ assert \valid(q) ∧ \valid(p); */ + { + int __gen_e_acsl_initialized; + int __gen_e_acsl_and; + int __gen_e_acsl_and_3; + __gen_e_acsl_initialized = __e_acsl_initialized((void *)(& q), + sizeof(char *)); + if (__gen_e_acsl_initialized) { + int __gen_e_acsl_valid; + __gen_e_acsl_valid = __e_acsl_valid((void *)q,sizeof(char),(void *)q, + (void *)(& q)); + __gen_e_acsl_and = __gen_e_acsl_valid; + } + else __gen_e_acsl_and = 0; + if (__gen_e_acsl_and) { + int __gen_e_acsl_initialized_2; + int __gen_e_acsl_and_2; + __gen_e_acsl_initialized_2 = __e_acsl_initialized((void *)(& p), + sizeof(char *)); + if (__gen_e_acsl_initialized_2) { + int __gen_e_acsl_valid_2; + __gen_e_acsl_valid_2 = __e_acsl_valid((void *)p,sizeof(char), + (void *)p,(void *)(& p)); + __gen_e_acsl_and_2 = __gen_e_acsl_valid_2; + } + else __gen_e_acsl_and_2 = 0; + __gen_e_acsl_and_3 = __gen_e_acsl_and_2; + } + else __gen_e_acsl_and_3 = 0; + __e_acsl_assert(__gen_e_acsl_and_3,(char *)"Assertion",(char *)"main", + (char *)"\\valid(q) && \\valid(p)",16); + } + __e_acsl_temporal_reset_parameters(); + __e_acsl_temporal_reset_return(); + __e_acsl_temporal_save_nreferent_parameter((void *)(& q),1U); + __e_acsl_full_init((void *)(& tmp_0)); + tmp_0 = realpath(c,q); + char *path = (char *)tmp_0; + __e_acsl_store_block((void *)(& path),(size_t)8); + __e_acsl_full_init((void *)(& path)); + __e_acsl_temporal_store_nblock((void *)(& path),(void *)((char *)tmp_0)); + __e_acsl_temporal_reset_parameters(); + __e_acsl_temporal_reset_return(); + __e_acsl_temporal_save_nreferent_parameter((void *)(& q),1U); + __e_acsl_full_init((void *)(& tmp_1)); + tmp_1 = realpath(c,q); + __e_acsl_temporal_store_nblock((void *)(& path),(void *)((char *)tmp_1)); + __e_acsl_full_init((void *)(& path)); + path = (char *)tmp_1; + /*@ assert \valid(path); */ + { + int __gen_e_acsl_initialized_3; + int __gen_e_acsl_and_4; + __gen_e_acsl_initialized_3 = __e_acsl_initialized((void *)(& path), + sizeof(char *)); + if (__gen_e_acsl_initialized_3) { + int __gen_e_acsl_valid_3; + __gen_e_acsl_valid_3 = __e_acsl_valid((void *)path,sizeof(char), + (void *)path,(void *)(& path)); + __gen_e_acsl_and_4 = __gen_e_acsl_valid_3; + } + else __gen_e_acsl_and_4 = 0; + __e_acsl_assert(__gen_e_acsl_and_4,(char *)"Assertion",(char *)"main", + (char *)"\\valid(path)",23); + } + __e_acsl_temporal_reset_parameters(); + __e_acsl_temporal_reset_return(); + __e_acsl_temporal_save_nreferent_parameter((void *)(& p),0U); + free((void *)p); + __e_acsl_temporal_reset_parameters(); + __e_acsl_temporal_reset_return(); + __e_acsl_temporal_save_nreferent_parameter((void *)(& path),0U); + free((void *)path); + /*@ assert ¬\valid(p) ∧ ¬\valid(path); */ + { + int __gen_e_acsl_initialized_4; + int __gen_e_acsl_and_5; + int __gen_e_acsl_and_7; + __gen_e_acsl_initialized_4 = __e_acsl_initialized((void *)(& p), + sizeof(char *)); + if (__gen_e_acsl_initialized_4) { + int __gen_e_acsl_valid_4; + __gen_e_acsl_valid_4 = __e_acsl_valid((void *)p,sizeof(char),(void *)p, + (void *)(& p)); + __gen_e_acsl_and_5 = __gen_e_acsl_valid_4; + } + else __gen_e_acsl_and_5 = 0; + if (! __gen_e_acsl_and_5) { + int __gen_e_acsl_initialized_5; + int __gen_e_acsl_and_6; + __gen_e_acsl_initialized_5 = __e_acsl_initialized((void *)(& path), + sizeof(char *)); + if (__gen_e_acsl_initialized_5) { + int __gen_e_acsl_valid_5; + __gen_e_acsl_valid_5 = __e_acsl_valid((void *)path,sizeof(char), + (void *)path,(void *)(& path)); + __gen_e_acsl_and_6 = __gen_e_acsl_valid_5; + } + else __gen_e_acsl_and_6 = 0; + __gen_e_acsl_and_7 = ! __gen_e_acsl_and_6; + } + else __gen_e_acsl_and_7 = 0; + __e_acsl_assert(__gen_e_acsl_and_7,(char *)"Assertion",(char *)"main", + (char *)"!\\valid(p) && !\\valid(path)",30); + } + __retres = 0; + __e_acsl_delete_block((void *)(& tmp_1)); + __e_acsl_delete_block((void *)(& tmp_0)); + __e_acsl_delete_block((void *)(& path)); + __e_acsl_delete_block((void *)(& q)); + __e_acsl_delete_block((void *)(& p)); + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/temporal/oracle_ci/gen_t_fun_ptr.c b/src/plugins/e-acsl/tests/temporal/oracle_ci/gen_t_fun_ptr.c new file mode 100644 index 0000000000000000000000000000000000000000..519c9b90503b34b704dfb043aeb2e2d0ac4ad551 --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/oracle_ci/gen_t_fun_ptr.c @@ -0,0 +1,61 @@ +/* Generated by Frama-C */ +#include "stdint.h" +#include "stdio.h" +#include "stdlib.h" +int *pfun(char c, int *p, int *p2, int *p3, int *p4, int i) +{ + __e_acsl_store_block((void *)(& p),(size_t)8); + __e_acsl_temporal_pull_parameter((void *)(& p),1U,8UL); + int *q = p; + __e_acsl_store_block((void *)(& q),(size_t)8); + __e_acsl_full_init((void *)(& q)); + __e_acsl_temporal_store_nreferent((void *)(& q),(void *)(& p)); + __e_acsl_temporal_save_return((void *)(& q)); + __e_acsl_delete_block((void *)(& p)); + __e_acsl_delete_block((void *)(& q)); + return q; +} + +int main(int argc, char const **argv) +{ + int __retres; + __e_acsl_memory_init(& argc,(char ***)(& argv),(size_t)8); + int a = 1; + __e_acsl_store_block((void *)(& a),(size_t)4); + __e_acsl_full_init((void *)(& a)); + int *p = & a; + __e_acsl_store_block((void *)(& p),(size_t)8); + __e_acsl_full_init((void *)(& p)); + __e_acsl_temporal_store_nblock((void *)(& p),(void *)(& a)); + uintptr_t addr = (unsigned long)(& addr); + __e_acsl_temporal_reset_parameters(); + __e_acsl_temporal_reset_return(); + __e_acsl_temporal_save_nreferent_parameter((void *)(& p),1U); + __e_acsl_temporal_save_nblock_parameter((void *)(& a),2U); + __e_acsl_full_init((void *)(& p)); + p = pfun((char)'a',p,& a,(int *)0,(int *)addr,2); + __e_acsl_temporal_pull_return((void *)(& p)); + /*@ assert \valid(p); */ + { + int __gen_e_acsl_initialized; + int __gen_e_acsl_and; + __gen_e_acsl_initialized = __e_acsl_initialized((void *)(& p), + sizeof(int *)); + if (__gen_e_acsl_initialized) { + int __gen_e_acsl_valid; + __gen_e_acsl_valid = __e_acsl_valid((void *)p,sizeof(int),(void *)p, + (void *)(& p)); + __gen_e_acsl_and = __gen_e_acsl_valid; + } + else __gen_e_acsl_and = 0; + __e_acsl_assert(__gen_e_acsl_and,(char *)"Assertion",(char *)"main", + (char *)"\\valid(p)",28); + } + __retres = 0; + __e_acsl_delete_block((void *)(& p)); + __e_acsl_delete_block((void *)(& a)); + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/temporal/oracle_ci/gen_t_getenv.c b/src/plugins/e-acsl/tests/temporal/oracle_ci/gen_t_getenv.c new file mode 100644 index 0000000000000000000000000000000000000000..33d62b000f28824c4abb58276a7d1c0825a3ce62 --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/oracle_ci/gen_t_getenv.c @@ -0,0 +1,101 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +char *__gen_e_acsl_literal_string_2; +char *__gen_e_acsl_literal_string; +extern int __e_acsl_sound_verdict; + +void __e_acsl_globals_init(void) +{ + static char __e_acsl_already_run = 0; + if (! __e_acsl_already_run) { + __e_acsl_already_run = 1; + __gen_e_acsl_literal_string_2 = "PATH"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_2, + sizeof("PATH")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_2); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_2); + __gen_e_acsl_literal_string = "HOME"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string,sizeof("HOME")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string); + } + return; +} + +int main(int argc, char const **argv) +{ + int __retres; + __e_acsl_memory_init(& argc,(char ***)(& argv),(size_t)8); + __e_acsl_globals_init(); + char *g1 = (char *)0; + __e_acsl_store_block((void *)(& g1),(size_t)8); + __e_acsl_full_init((void *)(& g1)); + __e_acsl_temporal_store_nblock((void *)(& g1),(void *)0); + __e_acsl_temporal_reset_parameters(); + __e_acsl_temporal_reset_return(); + __e_acsl_full_init((void *)(& g1)); + g1 = __gen_e_acsl_getenv(__gen_e_acsl_literal_string); + __e_acsl_temporal_pull_return((void *)(& g1)); + __e_acsl_temporal_reset_parameters(); + __e_acsl_temporal_reset_return(); + char *g2 = __gen_e_acsl_getenv(__gen_e_acsl_literal_string_2); + __e_acsl_store_block((void *)(& g2),(size_t)8); + __e_acsl_full_init((void *)(& g2)); + __e_acsl_temporal_pull_return((void *)(& g2)); + /*@ assert g1 ≡ \null ∨ \valid(g1); */ + { + int __gen_e_acsl_or; + /*@ assert + Eva: ptr_comparison: \pointer_comparable((void *)g1, (void *)0); + */ + if (g1 == (char *)0) __gen_e_acsl_or = 1; + else { + int __gen_e_acsl_initialized; + int __gen_e_acsl_and; + __gen_e_acsl_initialized = __e_acsl_initialized((void *)(& g1), + sizeof(char *)); + if (__gen_e_acsl_initialized) { + int __gen_e_acsl_valid; + __gen_e_acsl_valid = __e_acsl_valid((void *)g1,sizeof(char), + (void *)g1,(void *)(& g1)); + __gen_e_acsl_and = __gen_e_acsl_valid; + } + else __gen_e_acsl_and = 0; + __gen_e_acsl_or = __gen_e_acsl_and; + } + __e_acsl_assert(__gen_e_acsl_or,(char *)"Assertion",(char *)"main", + (char *)"g1 == \\null || \\valid(g1)",13); + } + /*@ assert g2 ≡ \null ∨ \valid(g2); */ + { + int __gen_e_acsl_or_2; + /*@ assert + Eva: ptr_comparison: \pointer_comparable((void *)g2, (void *)0); + */ + if (g2 == (char *)0) __gen_e_acsl_or_2 = 1; + else { + int __gen_e_acsl_initialized_2; + int __gen_e_acsl_and_2; + __gen_e_acsl_initialized_2 = __e_acsl_initialized((void *)(& g2), + sizeof(char *)); + if (__gen_e_acsl_initialized_2) { + int __gen_e_acsl_valid_2; + __gen_e_acsl_valid_2 = __e_acsl_valid((void *)g2,sizeof(char), + (void *)g2,(void *)(& g2)); + __gen_e_acsl_and_2 = __gen_e_acsl_valid_2; + } + else __gen_e_acsl_and_2 = 0; + __gen_e_acsl_or_2 = __gen_e_acsl_and_2; + } + __e_acsl_assert(__gen_e_acsl_or_2,(char *)"Assertion",(char *)"main", + (char *)"g2 == \\null || \\valid(g2)",14); + } + __retres = 0; + __e_acsl_delete_block((void *)(& g2)); + __e_acsl_delete_block((void *)(& g1)); + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/temporal/oracle_ci/gen_t_global_init.c b/src/plugins/e-acsl/tests/temporal/oracle_ci/gen_t_global_init.c new file mode 100644 index 0000000000000000000000000000000000000000..0432d38a6a3dd24fa38e17efed1b331bff5ef679 --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/oracle_ci/gen_t_global_init.c @@ -0,0 +1,206 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +char *__gen_e_acsl_literal_string; +char *__gen_e_acsl_literal_string_2; +char *__gen_e_acsl_literal_string_4; +char *__gen_e_acsl_literal_string_3; +struct tree_desc { + int *extra_bits ; +}; +typedef struct tree_desc tree_desc; +struct tree_desc2 { + struct tree_desc desc ; +}; +typedef struct tree_desc2 tree_desc2; +static int extra_lbits[1] = {0}; +static tree_desc l_desc = {.extra_bits = extra_lbits}; +static tree_desc descs[2] = + {{.extra_bits = extra_lbits}, {.extra_bits = extra_lbits}}; +static tree_desc2 l_desc2 = {.desc = {.extra_bits = extra_lbits}}; +static tree_desc2 descs2[2] = + {{.desc = {.extra_bits = extra_lbits}}, + {.desc = {.extra_bits = extra_lbits}}}; +void build_tree(tree_desc *desc) +{ + int *extra; + __e_acsl_store_block((void *)(& extra),(size_t)8); + __e_acsl_store_block((void *)(& desc),(size_t)8); + __e_acsl_temporal_pull_parameter((void *)(& desc),0U,8UL); + __e_acsl_temporal_store_nreferent((void *)(& extra), + (void *)(& desc->extra_bits)); + __e_acsl_full_init((void *)(& extra)); + extra = desc->extra_bits; + /*@ assert \valid(extra); */ + { + int __gen_e_acsl_initialized; + int __gen_e_acsl_and; + __gen_e_acsl_initialized = __e_acsl_initialized((void *)(& extra), + sizeof(int *)); + if (__gen_e_acsl_initialized) { + int __gen_e_acsl_valid; + __gen_e_acsl_valid = __e_acsl_valid((void *)extra,sizeof(int), + (void *)extra,(void *)(& extra)); + __gen_e_acsl_and = __gen_e_acsl_valid; + } + else __gen_e_acsl_and = 0; + __e_acsl_assert(__gen_e_acsl_and,(char *)"Assertion", + (char *)"build_tree",(char *)"\\valid(extra)",39); + } + __e_acsl_delete_block((void *)(& desc)); + __e_acsl_delete_block((void *)(& extra)); + return; +} + +char const *strings[2][2] = {{"the", "tha"}, {"thi", "tho"}}; +void __e_acsl_globals_init(void) +{ + static char __e_acsl_already_run = 0; + if (! __e_acsl_already_run) { + __e_acsl_already_run = 1; + __gen_e_acsl_literal_string = "tho"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string,sizeof("tho")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string); + __gen_e_acsl_literal_string_2 = "thi"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_2,sizeof("thi")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_2); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_2); + __gen_e_acsl_literal_string_4 = "the"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_4,sizeof("the")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_4); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_4); + __gen_e_acsl_literal_string_3 = "tha"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_3,sizeof("tha")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_3); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_3); + __e_acsl_store_block((void *)(descs2),(size_t)16); + __e_acsl_full_init((void *)(& descs2)); + __e_acsl_store_block((void *)(& l_desc2),(size_t)8); + __e_acsl_full_init((void *)(& l_desc2)); + __e_acsl_store_block((void *)(descs),(size_t)16); + __e_acsl_full_init((void *)(& descs)); + __e_acsl_store_block((void *)(& l_desc),(size_t)8); + __e_acsl_full_init((void *)(& l_desc)); + __e_acsl_store_block((void *)(extra_lbits),(size_t)4); + __e_acsl_full_init((void *)(& extra_lbits)); + __e_acsl_store_block((void *)(strings),(size_t)32); + __e_acsl_full_init((void *)(& strings)); + __e_acsl_temporal_store_nblock((void *)(& descs2[0].desc.extra_bits), + (void *)(extra_lbits)); + __e_acsl_temporal_store_nblock((void *)(& descs2[1].desc.extra_bits), + (void *)(extra_lbits)); + __e_acsl_temporal_store_nblock((void *)(& l_desc2.desc.extra_bits), + (void *)(extra_lbits)); + __e_acsl_temporal_store_nblock((void *)(& descs[0].extra_bits), + (void *)(extra_lbits)); + __e_acsl_temporal_store_nblock((void *)(& descs[1].extra_bits), + (void *)(extra_lbits)); + __e_acsl_temporal_store_nblock((void *)(& l_desc.extra_bits), + (void *)(extra_lbits)); + __e_acsl_temporal_store_nblock((void *)(& strings[0][0]), + (void *)__gen_e_acsl_literal_string_4); + __e_acsl_temporal_store_nblock((void *)(& strings[0][1]), + (void *)__gen_e_acsl_literal_string_3); + __e_acsl_temporal_store_nblock((void *)(& strings[1][0]), + (void *)__gen_e_acsl_literal_string_2); + __e_acsl_temporal_store_nblock((void *)(& strings[1][1]), + (void *)__gen_e_acsl_literal_string); + } + return; +} + +int main(int argc, char const **argv) +{ + int __retres; + __e_acsl_memory_init(& argc,(char ***)(& argv),(size_t)8); + __e_acsl_globals_init(); + __e_acsl_temporal_reset_parameters(); + __e_acsl_temporal_reset_return(); + __e_acsl_temporal_save_nblock_parameter((void *)(& l_desc),0U); + build_tree(& l_desc); + __e_acsl_temporal_reset_parameters(); + __e_acsl_temporal_reset_return(); + __e_acsl_temporal_save_nblock_parameter((void *)(descs),0U); + build_tree(descs); + __e_acsl_temporal_reset_parameters(); + __e_acsl_temporal_reset_return(); + __e_acsl_temporal_save_nblock_parameter((void *)(& descs[1]),0U); + build_tree(& descs[1]); + __e_acsl_temporal_reset_parameters(); + __e_acsl_temporal_reset_return(); + __e_acsl_temporal_save_nblock_parameter((void *)(& l_desc2.desc),0U); + build_tree(& l_desc2.desc); + __e_acsl_temporal_reset_parameters(); + __e_acsl_temporal_reset_return(); + __e_acsl_temporal_save_nblock_parameter((void *)(& descs2[0].desc),0U); + build_tree(& descs2[0].desc); + __e_acsl_temporal_reset_parameters(); + __e_acsl_temporal_reset_return(); + __e_acsl_temporal_save_nblock_parameter((void *)(& descs2[1].desc),0U); + build_tree(& descs2[1].desc); + char **p = (char **)(strings); + __e_acsl_store_block((void *)(& p),(size_t)8); + __e_acsl_full_init((void *)(& p)); + __e_acsl_temporal_store_nblock((void *)(& p),(void *)(strings)); + /*@ assert \valid_read(p); */ + { + int __gen_e_acsl_initialized; + int __gen_e_acsl_and; + __gen_e_acsl_initialized = __e_acsl_initialized((void *)(& p), + sizeof(char **)); + if (__gen_e_acsl_initialized) { + int __gen_e_acsl_valid_read; + __gen_e_acsl_valid_read = __e_acsl_valid_read((void *)p,sizeof(char *), + (void *)p,(void *)(& p)); + __gen_e_acsl_and = __gen_e_acsl_valid_read; + } + else __gen_e_acsl_and = 0; + __e_acsl_assert(__gen_e_acsl_and,(char *)"Assertion",(char *)"main", + (char *)"\\valid_read(p)",57); + } + /*@ assert \valid_read(*p); */ + { + int __gen_e_acsl_initialized_2; + int __gen_e_acsl_and_3; + __gen_e_acsl_initialized_2 = __e_acsl_initialized((void *)p, + sizeof(char *)); + if (__gen_e_acsl_initialized_2) { + int __gen_e_acsl_initialized_3; + int __gen_e_acsl_and_2; + int __gen_e_acsl_valid_read_3; + __gen_e_acsl_initialized_3 = __e_acsl_initialized((void *)(& p), + sizeof(char **)); + if (__gen_e_acsl_initialized_3) { + int __gen_e_acsl_valid_read_2; + __gen_e_acsl_valid_read_2 = __e_acsl_valid_read((void *)p, + sizeof(char *), + (void *)p, + (void *)(& p)); + __gen_e_acsl_and_2 = __gen_e_acsl_valid_read_2; + } + else __gen_e_acsl_and_2 = 0; + __e_acsl_assert(__gen_e_acsl_and_2,(char *)"RTE",(char *)"main", + (char *)"mem_access: \\valid_read(p)",58); + __gen_e_acsl_valid_read_3 = __e_acsl_valid_read((void *)*p, + sizeof(char), + (void *)*p,(void *)p); + __gen_e_acsl_and_3 = __gen_e_acsl_valid_read_3; + } + else __gen_e_acsl_and_3 = 0; + __e_acsl_assert(__gen_e_acsl_and_3,(char *)"Assertion",(char *)"main", + (char *)"\\valid_read(*p)",58); + } + __retres = 0; + __e_acsl_delete_block((void *)(descs2)); + __e_acsl_delete_block((void *)(& l_desc2)); + __e_acsl_delete_block((void *)(descs)); + __e_acsl_delete_block((void *)(& l_desc)); + __e_acsl_delete_block((void *)(extra_lbits)); + __e_acsl_delete_block((void *)(strings)); + __e_acsl_delete_block((void *)(& p)); + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/temporal/oracle_ci/gen_t_labels.c b/src/plugins/e-acsl/tests/temporal/oracle_ci/gen_t_labels.c new file mode 100644 index 0000000000000000000000000000000000000000..08ef108b0acd4adc0ec82fe32aa35f35416312c5 --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/oracle_ci/gen_t_labels.c @@ -0,0 +1,110 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +void foo(int *a, int *b) +{ + __e_acsl_store_block((void *)(& b),(size_t)8); + __e_acsl_store_block((void *)(& a),(size_t)8); + __e_acsl_temporal_pull_parameter((void *)(& a),0U,8UL); + __e_acsl_temporal_pull_parameter((void *)(& b),1U,8UL); + int t = *a; + __e_acsl_initialize((void *)a,sizeof(int)); + *a = *b; + __e_acsl_initialize((void *)b,sizeof(int)); + *b = t; + __e_acsl_delete_block((void *)(& b)); + __e_acsl_delete_block((void *)(& a)); + return; +} + +int *Q; +int *bar(void) +{ + RET: ; + return Q; +} + +int main(int argc, char const **argv) +{ + int __retres; + __e_acsl_memory_init(& argc,(char ***)(& argv),(size_t)8); + int a = 11; + __e_acsl_store_block((void *)(& a),(size_t)4); + __e_acsl_full_init((void *)(& a)); + int b = 12; + __e_acsl_store_block((void *)(& b),(size_t)4); + __e_acsl_full_init((void *)(& b)); + int *p = & a; + __e_acsl_store_block((void *)(& p),(size_t)8); + __e_acsl_full_init((void *)(& p)); + __e_acsl_temporal_store_nblock((void *)(& p),(void *)(& a)); + int *q = & b; + __e_acsl_store_block((void *)(& q),(size_t)8); + __e_acsl_full_init((void *)(& q)); + __e_acsl_temporal_store_nblock((void *)(& q),(void *)(& b)); + LAB: __e_acsl_temporal_reset_parameters(); + __e_acsl_temporal_reset_return(); + __e_acsl_temporal_save_nreferent_parameter((void *)(& p),0U); + __e_acsl_temporal_save_nreferent_parameter((void *)(& q),1U); + foo(p,q); + /*@ assert \valid(p) ∧ \valid(q); */ + { + int __gen_e_acsl_initialized; + int __gen_e_acsl_and; + int __gen_e_acsl_and_3; + __gen_e_acsl_initialized = __e_acsl_initialized((void *)(& p), + sizeof(int *)); + if (__gen_e_acsl_initialized) { + int __gen_e_acsl_valid; + __gen_e_acsl_valid = __e_acsl_valid((void *)p,sizeof(int),(void *)p, + (void *)(& p)); + __gen_e_acsl_and = __gen_e_acsl_valid; + } + else __gen_e_acsl_and = 0; + if (__gen_e_acsl_and) { + int __gen_e_acsl_initialized_2; + int __gen_e_acsl_and_2; + __gen_e_acsl_initialized_2 = __e_acsl_initialized((void *)(& q), + sizeof(int *)); + if (__gen_e_acsl_initialized_2) { + int __gen_e_acsl_valid_2; + __gen_e_acsl_valid_2 = __e_acsl_valid((void *)q,sizeof(int), + (void *)q,(void *)(& q)); + __gen_e_acsl_and_2 = __gen_e_acsl_valid_2; + } + else __gen_e_acsl_and_2 = 0; + __gen_e_acsl_and_3 = __gen_e_acsl_and_2; + } + else __gen_e_acsl_and_3 = 0; + __e_acsl_assert(__gen_e_acsl_and_3,(char *)"Assertion",(char *)"main", + (char *)"\\valid(p) && \\valid(q)",28); + } + LAB2: __e_acsl_temporal_store_nreferent((void *)(& q),(void *)(& p)); + __e_acsl_full_init((void *)(& q)); + q = p; + /*@ assert \valid(p); */ + { + int __gen_e_acsl_initialized_3; + int __gen_e_acsl_and_4; + __gen_e_acsl_initialized_3 = __e_acsl_initialized((void *)(& p), + sizeof(int *)); + if (__gen_e_acsl_initialized_3) { + int __gen_e_acsl_valid_3; + __gen_e_acsl_valid_3 = __e_acsl_valid((void *)p,sizeof(int),(void *)p, + (void *)(& p)); + __gen_e_acsl_and_4 = __gen_e_acsl_valid_3; + } + else __gen_e_acsl_and_4 = 0; + __e_acsl_assert(__gen_e_acsl_and_4,(char *)"Assertion",(char *)"main", + (char *)"\\valid(p)",32); + } + __retres = 0; + __e_acsl_delete_block((void *)(& q)); + __e_acsl_delete_block((void *)(& p)); + __e_acsl_delete_block((void *)(& b)); + __e_acsl_delete_block((void *)(& a)); + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/temporal/oracle_ci/gen_t_lit_string.c b/src/plugins/e-acsl/tests/temporal/oracle_ci/gen_t_lit_string.c new file mode 100644 index 0000000000000000000000000000000000000000..528b6f1f6f5bf5f25a5fc7a584c0c9ddf9e1a444 --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/oracle_ci/gen_t_lit_string.c @@ -0,0 +1,188 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +char *__gen_e_acsl_literal_string_2; +char *__gen_e_acsl_literal_string; +void __e_acsl_globals_init(void) +{ + static char __e_acsl_already_run = 0; + if (! __e_acsl_already_run) { + __e_acsl_already_run = 1; + __gen_e_acsl_literal_string_2 = "g"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_2,sizeof("g")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_2); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_2); + __gen_e_acsl_literal_string = "f"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string,sizeof("f")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string); + } + return; +} + +int main(void) +{ + int __retres; + char *g; + char *q; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + __e_acsl_globals_init(); + __e_acsl_store_block((void *)(& q),(size_t)8); + __e_acsl_store_block((void *)(& g),(size_t)8); + char *f = (char *)__gen_e_acsl_literal_string; + __e_acsl_store_block((void *)(& f),(size_t)8); + __e_acsl_full_init((void *)(& f)); + __e_acsl_temporal_store_nblock((void *)(& f), + (void *)__gen_e_acsl_literal_string); + /*@ assert \valid_read(f) ∧ ¬\valid(f); */ + { + int __gen_e_acsl_initialized; + int __gen_e_acsl_and; + int __gen_e_acsl_and_3; + __gen_e_acsl_initialized = __e_acsl_initialized((void *)(& f), + sizeof(char *)); + if (__gen_e_acsl_initialized) { + int __gen_e_acsl_valid_read; + __gen_e_acsl_valid_read = __e_acsl_valid_read((void *)f,sizeof(char), + (void *)f,(void *)(& f)); + __gen_e_acsl_and = __gen_e_acsl_valid_read; + } + else __gen_e_acsl_and = 0; + if (__gen_e_acsl_and) { + int __gen_e_acsl_initialized_2; + int __gen_e_acsl_and_2; + __gen_e_acsl_initialized_2 = __e_acsl_initialized((void *)(& f), + sizeof(char *)); + if (__gen_e_acsl_initialized_2) { + int __gen_e_acsl_valid; + __gen_e_acsl_valid = __e_acsl_valid((void *)f,sizeof(char),(void *)f, + (void *)(& f)); + __gen_e_acsl_and_2 = __gen_e_acsl_valid; + } + else __gen_e_acsl_and_2 = 0; + __gen_e_acsl_and_3 = ! __gen_e_acsl_and_2; + } + else __gen_e_acsl_and_3 = 0; + __e_acsl_assert(__gen_e_acsl_and_3,(char *)"Assertion",(char *)"main", + (char *)"\\valid_read(f) && !\\valid(f)",9); + } + __e_acsl_temporal_store_nblock((void *)(& g), + (void *)__gen_e_acsl_literal_string_2); + __e_acsl_full_init((void *)(& g)); + g = (char *)__gen_e_acsl_literal_string_2; + /*@ assert \valid_read(g) ∧ ¬\valid(g); */ + { + int __gen_e_acsl_initialized_3; + int __gen_e_acsl_and_4; + int __gen_e_acsl_and_6; + __gen_e_acsl_initialized_3 = __e_acsl_initialized((void *)(& g), + sizeof(char *)); + if (__gen_e_acsl_initialized_3) { + int __gen_e_acsl_valid_read_2; + __gen_e_acsl_valid_read_2 = __e_acsl_valid_read((void *)g,sizeof(char), + (void *)g, + (void *)(& g)); + __gen_e_acsl_and_4 = __gen_e_acsl_valid_read_2; + } + else __gen_e_acsl_and_4 = 0; + if (__gen_e_acsl_and_4) { + int __gen_e_acsl_initialized_4; + int __gen_e_acsl_and_5; + __gen_e_acsl_initialized_4 = __e_acsl_initialized((void *)(& g), + sizeof(char *)); + if (__gen_e_acsl_initialized_4) { + int __gen_e_acsl_valid_2; + __gen_e_acsl_valid_2 = __e_acsl_valid((void *)g,sizeof(char), + (void *)g,(void *)(& g)); + __gen_e_acsl_and_5 = __gen_e_acsl_valid_2; + } + else __gen_e_acsl_and_5 = 0; + __gen_e_acsl_and_6 = ! __gen_e_acsl_and_5; + } + else __gen_e_acsl_and_6 = 0; + __e_acsl_assert(__gen_e_acsl_and_6,(char *)"Assertion",(char *)"main", + (char *)"\\valid_read(g) && !\\valid(g)",12); + } + char *p = f; + __e_acsl_store_block((void *)(& p),(size_t)8); + __e_acsl_full_init((void *)(& p)); + __e_acsl_temporal_store_nreferent((void *)(& p),(void *)(& f)); + /*@ assert \valid_read(p) ∧ ¬\valid(p); */ + { + int __gen_e_acsl_initialized_5; + int __gen_e_acsl_and_7; + int __gen_e_acsl_and_9; + __gen_e_acsl_initialized_5 = __e_acsl_initialized((void *)(& p), + sizeof(char *)); + if (__gen_e_acsl_initialized_5) { + int __gen_e_acsl_valid_read_3; + __gen_e_acsl_valid_read_3 = __e_acsl_valid_read((void *)p,sizeof(char), + (void *)p, + (void *)(& p)); + __gen_e_acsl_and_7 = __gen_e_acsl_valid_read_3; + } + else __gen_e_acsl_and_7 = 0; + if (__gen_e_acsl_and_7) { + int __gen_e_acsl_initialized_6; + int __gen_e_acsl_and_8; + __gen_e_acsl_initialized_6 = __e_acsl_initialized((void *)(& p), + sizeof(char *)); + if (__gen_e_acsl_initialized_6) { + int __gen_e_acsl_valid_3; + __gen_e_acsl_valid_3 = __e_acsl_valid((void *)p,sizeof(char), + (void *)p,(void *)(& p)); + __gen_e_acsl_and_8 = __gen_e_acsl_valid_3; + } + else __gen_e_acsl_and_8 = 0; + __gen_e_acsl_and_9 = ! __gen_e_acsl_and_8; + } + else __gen_e_acsl_and_9 = 0; + __e_acsl_assert(__gen_e_acsl_and_9,(char *)"Assertion",(char *)"main", + (char *)"\\valid_read(p) && !\\valid(p)",15); + } + __e_acsl_temporal_store_nreferent((void *)(& q),(void *)(& f)); + __e_acsl_full_init((void *)(& q)); + q = f; + /*@ assert \valid_read(q) ∧ ¬\valid(q); */ + { + int __gen_e_acsl_initialized_7; + int __gen_e_acsl_and_10; + int __gen_e_acsl_and_12; + __gen_e_acsl_initialized_7 = __e_acsl_initialized((void *)(& q), + sizeof(char *)); + if (__gen_e_acsl_initialized_7) { + int __gen_e_acsl_valid_read_4; + __gen_e_acsl_valid_read_4 = __e_acsl_valid_read((void *)q,sizeof(char), + (void *)q, + (void *)(& q)); + __gen_e_acsl_and_10 = __gen_e_acsl_valid_read_4; + } + else __gen_e_acsl_and_10 = 0; + if (__gen_e_acsl_and_10) { + int __gen_e_acsl_initialized_8; + int __gen_e_acsl_and_11; + __gen_e_acsl_initialized_8 = __e_acsl_initialized((void *)(& q), + sizeof(char *)); + if (__gen_e_acsl_initialized_8) { + int __gen_e_acsl_valid_4; + __gen_e_acsl_valid_4 = __e_acsl_valid((void *)q,sizeof(char), + (void *)q,(void *)(& q)); + __gen_e_acsl_and_11 = __gen_e_acsl_valid_4; + } + else __gen_e_acsl_and_11 = 0; + __gen_e_acsl_and_12 = ! __gen_e_acsl_and_11; + } + else __gen_e_acsl_and_12 = 0; + __e_acsl_assert(__gen_e_acsl_and_12,(char *)"Assertion",(char *)"main", + (char *)"\\valid_read(q) && !\\valid(q)",18); + } + __retres = 0; + __e_acsl_delete_block((void *)(& q)); + __e_acsl_delete_block((void *)(& p)); + __e_acsl_delete_block((void *)(& g)); + __e_acsl_delete_block((void *)(& f)); + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/temporal/oracle_ci/gen_t_local_init.c b/src/plugins/e-acsl/tests/temporal/oracle_ci/gen_t_local_init.c new file mode 100644 index 0000000000000000000000000000000000000000..da938a09b43d8bb106db836f515bb1381512efe0 --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/oracle_ci/gen_t_local_init.c @@ -0,0 +1,425 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +char *__gen_e_acsl_literal_string_4; +char *__gen_e_acsl_literal_string_3; +char *__gen_e_acsl_literal_string; +char *__gen_e_acsl_literal_string_2; +char *__gen_e_acsl_literal_string_5; +char *__gen_e_acsl_literal_string_7; +char *__gen_e_acsl_literal_string_6; +struct tree_desc { + int *extra_bits ; +}; +typedef struct tree_desc tree_desc; +struct tree_desc2 { + struct tree_desc desc ; +}; +typedef struct tree_desc2 tree_desc2; +void build_tree(tree_desc *desc) +{ + int *extra; + __e_acsl_store_block((void *)(& extra),(size_t)8); + __e_acsl_store_block((void *)(& desc),(size_t)8); + __e_acsl_temporal_pull_parameter((void *)(& desc),0U,8UL); + __e_acsl_temporal_store_nreferent((void *)(& extra), + (void *)(& desc->extra_bits)); + __e_acsl_full_init((void *)(& extra)); + extra = desc->extra_bits; + /*@ assert \valid(extra); */ + { + int __gen_e_acsl_initialized; + int __gen_e_acsl_and; + __gen_e_acsl_initialized = __e_acsl_initialized((void *)(& extra), + sizeof(int *)); + if (__gen_e_acsl_initialized) { + int __gen_e_acsl_valid; + __gen_e_acsl_valid = __e_acsl_valid((void *)extra,sizeof(int), + (void *)extra,(void *)(& extra)); + __gen_e_acsl_and = __gen_e_acsl_valid; + } + else __gen_e_acsl_and = 0; + __e_acsl_assert(__gen_e_acsl_and,(char *)"Assertion", + (char *)"build_tree",(char *)"\\valid(extra)",23); + } + __e_acsl_delete_block((void *)(& desc)); + __e_acsl_delete_block((void *)(& extra)); + return; +} + +char *Strings[2][2] = + {{(char *)"the", (char *)"tha"}, {(char *)"thi", (char *)"tho"}}; +char *Str[4] = {(char *)"foo", (char *)"bar", (char *)"baz", (char *)0}; +void __e_acsl_globals_init(void) +{ + static char __e_acsl_already_run = 0; + if (! __e_acsl_already_run) { + __e_acsl_already_run = 1; + __gen_e_acsl_literal_string_4 = "tho"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_4,sizeof("tho")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_4); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_4); + __gen_e_acsl_literal_string_3 = "thi"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_3,sizeof("thi")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_3); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_3); + __gen_e_acsl_literal_string = "the"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string,sizeof("the")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string); + __gen_e_acsl_literal_string_2 = "tha"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_2,sizeof("tha")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_2); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_2); + __gen_e_acsl_literal_string_5 = "foo"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_5,sizeof("foo")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_5); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_5); + __gen_e_acsl_literal_string_7 = "baz"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_7,sizeof("baz")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_7); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_7); + __gen_e_acsl_literal_string_6 = "bar"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string_6,sizeof("bar")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string_6); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string_6); + __e_acsl_store_block((void *)(Str),(size_t)32); + __e_acsl_full_init((void *)(& Str)); + __e_acsl_store_block((void *)(Strings),(size_t)32); + __e_acsl_full_init((void *)(& Strings)); + __e_acsl_temporal_store_nblock((void *)(Str), + (void *)__gen_e_acsl_literal_string_5); + __e_acsl_temporal_store_nblock((void *)(& Str[1]), + (void *)__gen_e_acsl_literal_string_6); + __e_acsl_temporal_store_nblock((void *)(& Str[2]), + (void *)__gen_e_acsl_literal_string_7); + __e_acsl_temporal_store_nblock((void *)(& Str[3]),(void *)0); + __e_acsl_temporal_store_nblock((void *)(& Strings[0][0]), + (void *)__gen_e_acsl_literal_string); + __e_acsl_temporal_store_nblock((void *)(& Strings[0][1]), + (void *)__gen_e_acsl_literal_string_2); + __e_acsl_temporal_store_nblock((void *)(& Strings[1][0]), + (void *)__gen_e_acsl_literal_string_3); + __e_acsl_temporal_store_nblock((void *)(& Strings[1][1]), + (void *)__gen_e_acsl_literal_string_4); + } + return; +} + +int main(int argc, char const **argv) +{ + int __retres; + __e_acsl_memory_init(& argc,(char ***)(& argv),(size_t)8); + __e_acsl_globals_init(); + char *strings[2][2] = + {{(char *)__gen_e_acsl_literal_string, + (char *)__gen_e_acsl_literal_string_2}, + {(char *)__gen_e_acsl_literal_string_3, + (char *)__gen_e_acsl_literal_string_4}}; + __e_acsl_store_block((void *)(strings),(size_t)32); + __e_acsl_full_init((void *)(& strings)); + __e_acsl_temporal_store_nblock((void *)(& strings[1][1]), + (void *)__gen_e_acsl_literal_string_4); + __e_acsl_temporal_store_nblock((void *)(& strings[1][0]), + (void *)__gen_e_acsl_literal_string_3); + __e_acsl_temporal_store_nblock((void *)(& strings[0][1]), + (void *)__gen_e_acsl_literal_string_2); + __e_acsl_temporal_store_nblock((void *)(& strings[0][0]), + (void *)__gen_e_acsl_literal_string); + char **p = (char **)(strings); + __e_acsl_store_block((void *)(& p),(size_t)8); + __e_acsl_full_init((void *)(& p)); + __e_acsl_temporal_store_nblock((void *)(& p),(void *)(strings)); + /*@ assert \valid_read(p); */ + { + int __gen_e_acsl_initialized; + int __gen_e_acsl_and; + __gen_e_acsl_initialized = __e_acsl_initialized((void *)(& p), + sizeof(char **)); + if (__gen_e_acsl_initialized) { + int __gen_e_acsl_valid_read; + __gen_e_acsl_valid_read = __e_acsl_valid_read((void *)p,sizeof(char *), + (void *)p,(void *)(& p)); + __gen_e_acsl_and = __gen_e_acsl_valid_read; + } + else __gen_e_acsl_and = 0; + __e_acsl_assert(__gen_e_acsl_and,(char *)"Assertion",(char *)"main", + (char *)"\\valid_read(p)",41); + } + /*@ assert \valid_read(*p); */ + { + int __gen_e_acsl_initialized_2; + int __gen_e_acsl_and_3; + __gen_e_acsl_initialized_2 = __e_acsl_initialized((void *)p, + sizeof(char *)); + if (__gen_e_acsl_initialized_2) { + int __gen_e_acsl_initialized_3; + int __gen_e_acsl_and_2; + int __gen_e_acsl_valid_read_3; + __gen_e_acsl_initialized_3 = __e_acsl_initialized((void *)(& p), + sizeof(char **)); + if (__gen_e_acsl_initialized_3) { + int __gen_e_acsl_valid_read_2; + __gen_e_acsl_valid_read_2 = __e_acsl_valid_read((void *)p, + sizeof(char *), + (void *)p, + (void *)(& p)); + __gen_e_acsl_and_2 = __gen_e_acsl_valid_read_2; + } + else __gen_e_acsl_and_2 = 0; + __e_acsl_assert(__gen_e_acsl_and_2,(char *)"RTE",(char *)"main", + (char *)"mem_access: \\valid_read(p)",42); + __gen_e_acsl_valid_read_3 = __e_acsl_valid_read((void *)*p, + sizeof(char), + (void *)*p,(void *)p); + __gen_e_acsl_and_3 = __gen_e_acsl_valid_read_3; + } + else __gen_e_acsl_and_3 = 0; + __e_acsl_assert(__gen_e_acsl_and_3,(char *)"Assertion",(char *)"main", + (char *)"\\valid_read(*p)",42); + } + char *str[4] = + {(char *)__gen_e_acsl_literal_string_5, + (char *)__gen_e_acsl_literal_string_6, + (char *)__gen_e_acsl_literal_string_7, + (char *)0}; + __e_acsl_store_block((void *)(str),(size_t)32); + __e_acsl_full_init((void *)(& str)); + __e_acsl_temporal_store_nblock((void *)(& str[3]),(void *)0); + __e_acsl_temporal_store_nblock((void *)(& str[2]), + (void *)__gen_e_acsl_literal_string_7); + __e_acsl_temporal_store_nblock((void *)(& str[1]), + (void *)__gen_e_acsl_literal_string_6); + __e_acsl_temporal_store_nblock((void *)(str), + (void *)__gen_e_acsl_literal_string_5); + __e_acsl_temporal_store_nblock((void *)(& p),(void *)(& str)); + __e_acsl_full_init((void *)(& p)); + p = (char **)(& str); + /*@ assert \valid_read(p); */ + { + int __gen_e_acsl_initialized_4; + int __gen_e_acsl_and_4; + __gen_e_acsl_initialized_4 = __e_acsl_initialized((void *)(& p), + sizeof(char **)); + if (__gen_e_acsl_initialized_4) { + int __gen_e_acsl_valid_read_4; + __gen_e_acsl_valid_read_4 = __e_acsl_valid_read((void *)p, + sizeof(char *), + (void *)p, + (void *)(& p)); + __gen_e_acsl_and_4 = __gen_e_acsl_valid_read_4; + } + else __gen_e_acsl_and_4 = 0; + __e_acsl_assert(__gen_e_acsl_and_4,(char *)"Assertion",(char *)"main", + (char *)"\\valid_read(p)",48); + } + /*@ assert \valid_read(*p); */ + { + int __gen_e_acsl_initialized_5; + int __gen_e_acsl_and_6; + __gen_e_acsl_initialized_5 = __e_acsl_initialized((void *)p, + sizeof(char *)); + if (__gen_e_acsl_initialized_5) { + int __gen_e_acsl_initialized_6; + int __gen_e_acsl_and_5; + int __gen_e_acsl_valid_read_6; + __gen_e_acsl_initialized_6 = __e_acsl_initialized((void *)(& p), + sizeof(char **)); + if (__gen_e_acsl_initialized_6) { + int __gen_e_acsl_valid_read_5; + __gen_e_acsl_valid_read_5 = __e_acsl_valid_read((void *)p, + sizeof(char *), + (void *)p, + (void *)(& p)); + __gen_e_acsl_and_5 = __gen_e_acsl_valid_read_5; + } + else __gen_e_acsl_and_5 = 0; + __e_acsl_assert(__gen_e_acsl_and_5,(char *)"RTE",(char *)"main", + (char *)"mem_access: \\valid_read(p)",49); + __gen_e_acsl_valid_read_6 = __e_acsl_valid_read((void *)*p, + sizeof(char), + (void *)*p,(void *)p); + __gen_e_acsl_and_6 = __gen_e_acsl_valid_read_6; + } + else __gen_e_acsl_and_6 = 0; + __e_acsl_assert(__gen_e_acsl_and_6,(char *)"Assertion",(char *)"main", + (char *)"\\valid_read(*p)",49); + } + char **P = (char **)(Strings); + __e_acsl_store_block((void *)(& P),(size_t)8); + __e_acsl_full_init((void *)(& P)); + __e_acsl_temporal_store_nblock((void *)(& P),(void *)(Strings)); + /*@ assert \valid_read(P); */ + { + int __gen_e_acsl_initialized_7; + int __gen_e_acsl_and_7; + __gen_e_acsl_initialized_7 = __e_acsl_initialized((void *)(& P), + sizeof(char **)); + if (__gen_e_acsl_initialized_7) { + int __gen_e_acsl_valid_read_7; + __gen_e_acsl_valid_read_7 = __e_acsl_valid_read((void *)P, + sizeof(char *), + (void *)P, + (void *)(& P)); + __gen_e_acsl_and_7 = __gen_e_acsl_valid_read_7; + } + else __gen_e_acsl_and_7 = 0; + __e_acsl_assert(__gen_e_acsl_and_7,(char *)"Assertion",(char *)"main", + (char *)"\\valid_read(P)",53); + } + /*@ assert \valid_read(*P); */ + { + int __gen_e_acsl_initialized_8; + int __gen_e_acsl_and_9; + __gen_e_acsl_initialized_8 = __e_acsl_initialized((void *)P, + sizeof(char *)); + if (__gen_e_acsl_initialized_8) { + int __gen_e_acsl_initialized_9; + int __gen_e_acsl_and_8; + int __gen_e_acsl_valid_read_9; + __gen_e_acsl_initialized_9 = __e_acsl_initialized((void *)(& P), + sizeof(char **)); + if (__gen_e_acsl_initialized_9) { + int __gen_e_acsl_valid_read_8; + __gen_e_acsl_valid_read_8 = __e_acsl_valid_read((void *)P, + sizeof(char *), + (void *)P, + (void *)(& P)); + __gen_e_acsl_and_8 = __gen_e_acsl_valid_read_8; + } + else __gen_e_acsl_and_8 = 0; + __e_acsl_assert(__gen_e_acsl_and_8,(char *)"RTE",(char *)"main", + (char *)"mem_access: \\valid_read(P)",54); + __gen_e_acsl_valid_read_9 = __e_acsl_valid_read((void *)*P, + sizeof(char), + (void *)*P,(void *)P); + __gen_e_acsl_and_9 = __gen_e_acsl_valid_read_9; + } + else __gen_e_acsl_and_9 = 0; + __e_acsl_assert(__gen_e_acsl_and_9,(char *)"Assertion",(char *)"main", + (char *)"\\valid_read(*P)",54); + } + __e_acsl_temporal_store_nblock((void *)(& P),(void *)(& Str)); + __e_acsl_full_init((void *)(& P)); + P = (char **)(& Str); + /*@ assert \valid_read(P); */ + { + int __gen_e_acsl_initialized_10; + int __gen_e_acsl_and_10; + __gen_e_acsl_initialized_10 = __e_acsl_initialized((void *)(& P), + sizeof(char **)); + if (__gen_e_acsl_initialized_10) { + int __gen_e_acsl_valid_read_10; + __gen_e_acsl_valid_read_10 = __e_acsl_valid_read((void *)P, + sizeof(char *), + (void *)P, + (void *)(& P)); + __gen_e_acsl_and_10 = __gen_e_acsl_valid_read_10; + } + else __gen_e_acsl_and_10 = 0; + __e_acsl_assert(__gen_e_acsl_and_10,(char *)"Assertion",(char *)"main", + (char *)"\\valid_read(P)",58); + } + /*@ assert \valid_read(*P); */ + { + int __gen_e_acsl_initialized_11; + int __gen_e_acsl_and_12; + __gen_e_acsl_initialized_11 = __e_acsl_initialized((void *)P, + sizeof(char *)); + if (__gen_e_acsl_initialized_11) { + int __gen_e_acsl_initialized_12; + int __gen_e_acsl_and_11; + int __gen_e_acsl_valid_read_12; + __gen_e_acsl_initialized_12 = __e_acsl_initialized((void *)(& P), + sizeof(char **)); + if (__gen_e_acsl_initialized_12) { + int __gen_e_acsl_valid_read_11; + __gen_e_acsl_valid_read_11 = __e_acsl_valid_read((void *)P, + sizeof(char *), + (void *)P, + (void *)(& P)); + __gen_e_acsl_and_11 = __gen_e_acsl_valid_read_11; + } + else __gen_e_acsl_and_11 = 0; + __e_acsl_assert(__gen_e_acsl_and_11,(char *)"RTE",(char *)"main", + (char *)"mem_access: \\valid_read(P)",59); + __gen_e_acsl_valid_read_12 = __e_acsl_valid_read((void *)*P, + sizeof(char), + (void *)*P,(void *)P); + __gen_e_acsl_and_12 = __gen_e_acsl_valid_read_12; + } + else __gen_e_acsl_and_12 = 0; + __e_acsl_assert(__gen_e_acsl_and_12,(char *)"Assertion",(char *)"main", + (char *)"\\valid_read(*P)",59); + } + int extra_lbits[1] = {0}; + __e_acsl_store_block((void *)(extra_lbits),(size_t)4); + __e_acsl_full_init((void *)(& extra_lbits)); + tree_desc l_desc = {.extra_bits = extra_lbits}; + __e_acsl_store_block((void *)(& l_desc),(size_t)8); + __e_acsl_full_init((void *)(& l_desc)); + __e_acsl_temporal_store_nblock((void *)(& l_desc.extra_bits), + (void *)(extra_lbits)); + tree_desc descs[2] = + {{.extra_bits = extra_lbits}, {.extra_bits = extra_lbits}}; + __e_acsl_store_block((void *)(descs),(size_t)16); + __e_acsl_full_init((void *)(& descs)); + __e_acsl_temporal_store_nblock((void *)(& descs[1].extra_bits), + (void *)(extra_lbits)); + __e_acsl_temporal_store_nblock((void *)(& descs[0].extra_bits), + (void *)(extra_lbits)); + tree_desc2 l_desc2 = {.desc = {.extra_bits = extra_lbits}}; + __e_acsl_store_block((void *)(& l_desc2),(size_t)8); + __e_acsl_full_init((void *)(& l_desc2)); + __e_acsl_temporal_store_nblock((void *)(& l_desc2.desc.extra_bits), + (void *)(extra_lbits)); + tree_desc2 descs2[2] = + {{.desc = {.extra_bits = extra_lbits}}, + {.desc = {.extra_bits = extra_lbits}}}; + __e_acsl_store_block((void *)(descs2),(size_t)16); + __e_acsl_full_init((void *)(& descs2)); + __e_acsl_temporal_store_nblock((void *)(& descs2[1].desc.extra_bits), + (void *)(extra_lbits)); + __e_acsl_temporal_store_nblock((void *)(& descs2[0].desc.extra_bits), + (void *)(extra_lbits)); + __e_acsl_temporal_reset_parameters(); + __e_acsl_temporal_reset_return(); + __e_acsl_temporal_save_nblock_parameter((void *)(& l_desc),0U); + build_tree(& l_desc); + __e_acsl_temporal_reset_parameters(); + __e_acsl_temporal_reset_return(); + __e_acsl_temporal_save_nblock_parameter((void *)(descs),0U); + build_tree(descs); + __e_acsl_temporal_reset_parameters(); + __e_acsl_temporal_reset_return(); + __e_acsl_temporal_save_nblock_parameter((void *)(& descs[1]),0U); + build_tree(& descs[1]); + __e_acsl_temporal_reset_parameters(); + __e_acsl_temporal_reset_return(); + __e_acsl_temporal_save_nblock_parameter((void *)(& l_desc2.desc),0U); + build_tree(& l_desc2.desc); + __e_acsl_temporal_reset_parameters(); + __e_acsl_temporal_reset_return(); + __e_acsl_temporal_save_nblock_parameter((void *)(& descs2[0].desc),0U); + build_tree(& descs2[0].desc); + __e_acsl_temporal_reset_parameters(); + __e_acsl_temporal_reset_return(); + __e_acsl_temporal_save_nblock_parameter((void *)(& descs2[1].desc),0U); + build_tree(& descs2[1].desc); + __retres = 0; + __e_acsl_delete_block((void *)(Str)); + __e_acsl_delete_block((void *)(Strings)); + __e_acsl_delete_block((void *)(descs2)); + __e_acsl_delete_block((void *)(& l_desc2)); + __e_acsl_delete_block((void *)(descs)); + __e_acsl_delete_block((void *)(& l_desc)); + __e_acsl_delete_block((void *)(extra_lbits)); + __e_acsl_delete_block((void *)(& P)); + __e_acsl_delete_block((void *)(str)); + __e_acsl_delete_block((void *)(& p)); + __e_acsl_delete_block((void *)(strings)); + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/temporal/oracle_ci/gen_t_malloc-asan.c b/src/plugins/e-acsl/tests/temporal/oracle_ci/gen_t_malloc-asan.c new file mode 100644 index 0000000000000000000000000000000000000000..8095a59581baf85e20d7e1ba6fb1b92f7260cc0b --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/oracle_ci/gen_t_malloc-asan.c @@ -0,0 +1,84 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +char *__gen_e_acsl_literal_string; +void __e_acsl_globals_init(void) +{ + static char __e_acsl_already_run = 0; + if (! __e_acsl_already_run) { + __e_acsl_already_run = 1; + __gen_e_acsl_literal_string = "Same address %p in %d steps\n"; + __e_acsl_store_block((void *)__gen_e_acsl_literal_string, + sizeof("Same address %p in %d steps\n")); + __e_acsl_full_init((void *)__gen_e_acsl_literal_string); + __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string); + } + return; +} + +int main(void) +{ + int __retres; + int *p; + int *q; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + __e_acsl_globals_init(); + __e_acsl_store_block((void *)(& q),(size_t)8); + __e_acsl_store_block((void *)(& p),(size_t)8); + int counter = 0; + size_t limit = (unsigned long)10000; + __e_acsl_temporal_reset_parameters(); + __e_acsl_temporal_reset_return(); + __e_acsl_full_init((void *)(& p)); + p = (int *)malloc((unsigned long)(1024 * 1024)); + __e_acsl_temporal_store_nblock((void *)(& p),(void *)*(& p)); + __e_acsl_temporal_store_nreferent((void *)(& q),(void *)(& p)); + __e_acsl_full_init((void *)(& q)); + q = p; + __e_acsl_temporal_reset_parameters(); + __e_acsl_temporal_reset_return(); + __e_acsl_temporal_save_nreferent_parameter((void *)(& p),0U); + free((void *)p); + while ((size_t)counter < limit) { + __e_acsl_temporal_reset_parameters(); + __e_acsl_temporal_reset_return(); + __e_acsl_full_init((void *)(& p)); + p = (int *)malloc((unsigned long)(1024 * 1024)); + __e_acsl_temporal_store_nblock((void *)(& p),(void *)*(& p)); + counter ++; + /*@ assert Eva: dangling_pointer: ¬\dangling(&q); */ + if (p != q) { + __e_acsl_temporal_reset_parameters(); + __e_acsl_temporal_reset_return(); + __e_acsl_temporal_save_nreferent_parameter((void *)(& p),0U); + free((void *)p); + } + else { + __e_acsl_temporal_reset_parameters(); + __e_acsl_temporal_reset_return(); + __e_acsl_temporal_save_nreferent_parameter((void *)(& p),1U); + printf(__gen_e_acsl_literal_string,p,counter); + break; + } + __e_acsl_temporal_store_nblock((void *)(& p),(void *)0); + __e_acsl_full_init((void *)(& p)); + p = (int *)0; + } + if (p) { + __e_acsl_initialize((void *)q,sizeof(int)); + *q = 1; + __e_acsl_initialize((void *)p,sizeof(int)); + *p = 2; + } + __e_acsl_temporal_reset_parameters(); + __e_acsl_temporal_reset_return(); + __e_acsl_temporal_save_nreferent_parameter((void *)(& p),0U); + free((void *)p); + __retres = 0; + __e_acsl_delete_block((void *)(& q)); + __e_acsl_delete_block((void *)(& p)); + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/temporal/oracle_ci/gen_t_malloc.c b/src/plugins/e-acsl/tests/temporal/oracle_ci/gen_t_malloc.c new file mode 100644 index 0000000000000000000000000000000000000000..ce90dc8e2a7ec6ef116969480608d37b58c0d3dd --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/oracle_ci/gen_t_malloc.c @@ -0,0 +1,212 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +int main(void) +{ + int __retres; + int *p; + int *q; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + __e_acsl_store_block((void *)(& q),(size_t)8); + __e_acsl_store_block((void *)(& p),(size_t)8); + /*@ assert ¬\valid(p); */ + { + int __gen_e_acsl_initialized; + int __gen_e_acsl_and; + __gen_e_acsl_initialized = __e_acsl_initialized((void *)(& p), + sizeof(int *)); + if (__gen_e_acsl_initialized) { + int __gen_e_acsl_valid; + __gen_e_acsl_valid = __e_acsl_valid((void *)p,sizeof(int),(void *)p, + (void *)(& p)); + __gen_e_acsl_and = __gen_e_acsl_valid; + } + else __gen_e_acsl_and = 0; + __e_acsl_assert(! __gen_e_acsl_and,(char *)"Assertion",(char *)"main", + (char *)"!\\valid(p)",11); + } + /*@ assert ¬\valid(q); */ + { + int __gen_e_acsl_initialized_2; + int __gen_e_acsl_and_2; + __gen_e_acsl_initialized_2 = __e_acsl_initialized((void *)(& q), + sizeof(int *)); + if (__gen_e_acsl_initialized_2) { + int __gen_e_acsl_valid_2; + __gen_e_acsl_valid_2 = __e_acsl_valid((void *)q,sizeof(int),(void *)q, + (void *)(& q)); + __gen_e_acsl_and_2 = __gen_e_acsl_valid_2; + } + else __gen_e_acsl_and_2 = 0; + __e_acsl_assert(! __gen_e_acsl_and_2,(char *)"Assertion",(char *)"main", + (char *)"!\\valid(q)",12); + } + __e_acsl_temporal_reset_parameters(); + __e_acsl_temporal_reset_return(); + __e_acsl_full_init((void *)(& p)); + p = (int *)malloc(sizeof(int)); + __e_acsl_temporal_store_nblock((void *)(& p),(void *)*(& p)); + __e_acsl_temporal_store_nreferent((void *)(& q),(void *)(& p)); + __e_acsl_full_init((void *)(& q)); + q = p; + /*@ assert \valid(p); */ + { + int __gen_e_acsl_initialized_3; + int __gen_e_acsl_and_3; + __gen_e_acsl_initialized_3 = __e_acsl_initialized((void *)(& p), + sizeof(int *)); + if (__gen_e_acsl_initialized_3) { + int __gen_e_acsl_valid_3; + __gen_e_acsl_valid_3 = __e_acsl_valid((void *)p,sizeof(int),(void *)p, + (void *)(& p)); + __gen_e_acsl_and_3 = __gen_e_acsl_valid_3; + } + else __gen_e_acsl_and_3 = 0; + __e_acsl_assert(__gen_e_acsl_and_3,(char *)"Assertion",(char *)"main", + (char *)"\\valid(p)",17); + } + /*@ assert \valid(q); */ + { + int __gen_e_acsl_initialized_4; + int __gen_e_acsl_and_4; + __gen_e_acsl_initialized_4 = __e_acsl_initialized((void *)(& q), + sizeof(int *)); + if (__gen_e_acsl_initialized_4) { + int __gen_e_acsl_valid_4; + __gen_e_acsl_valid_4 = __e_acsl_valid((void *)q,sizeof(int),(void *)q, + (void *)(& q)); + __gen_e_acsl_and_4 = __gen_e_acsl_valid_4; + } + else __gen_e_acsl_and_4 = 0; + __e_acsl_assert(__gen_e_acsl_and_4,(char *)"Assertion",(char *)"main", + (char *)"\\valid(q)",18); + } + __e_acsl_temporal_reset_parameters(); + __e_acsl_temporal_reset_return(); + __e_acsl_temporal_save_nreferent_parameter((void *)(& q),0U); + free((void *)q); + /*@ assert ¬\valid(p); */ + { + int __gen_e_acsl_initialized_5; + int __gen_e_acsl_and_5; + __gen_e_acsl_initialized_5 = __e_acsl_initialized((void *)(& p), + sizeof(int *)); + if (__gen_e_acsl_initialized_5) { + int __gen_e_acsl_valid_5; + /*@ assert Eva: dangling_pointer: ¬\dangling(&p); */ + __gen_e_acsl_valid_5 = __e_acsl_valid((void *)p,sizeof(int),(void *)p, + (void *)(& p)); + __gen_e_acsl_and_5 = __gen_e_acsl_valid_5; + } + else __gen_e_acsl_and_5 = 0; + __e_acsl_assert(! __gen_e_acsl_and_5,(char *)"Assertion",(char *)"main", + (char *)"!\\valid(p)",22); + } + /*@ assert ¬\valid(q); */ + { + int __gen_e_acsl_initialized_6; + int __gen_e_acsl_and_6; + __gen_e_acsl_initialized_6 = __e_acsl_initialized((void *)(& q), + sizeof(int *)); + if (__gen_e_acsl_initialized_6) { + int __gen_e_acsl_valid_6; + __gen_e_acsl_valid_6 = __e_acsl_valid((void *)q,sizeof(int),(void *)q, + (void *)(& q)); + __gen_e_acsl_and_6 = __gen_e_acsl_valid_6; + } + else __gen_e_acsl_and_6 = 0; + __e_acsl_assert(! __gen_e_acsl_and_6,(char *)"Assertion",(char *)"main", + (char *)"!\\valid(q)",23); + } + __e_acsl_temporal_reset_parameters(); + __e_acsl_temporal_reset_return(); + __e_acsl_full_init((void *)(& p)); + p = (int *)malloc(sizeof(int)); + __e_acsl_temporal_store_nblock((void *)(& p),(void *)*(& p)); + /*@ assert \valid(p); */ + { + int __gen_e_acsl_initialized_7; + int __gen_e_acsl_and_7; + __gen_e_acsl_initialized_7 = __e_acsl_initialized((void *)(& p), + sizeof(int *)); + if (__gen_e_acsl_initialized_7) { + int __gen_e_acsl_valid_7; + __gen_e_acsl_valid_7 = __e_acsl_valid((void *)p,sizeof(int),(void *)p, + (void *)(& p)); + __gen_e_acsl_and_7 = __gen_e_acsl_valid_7; + } + else __gen_e_acsl_and_7 = 0; + __e_acsl_assert(__gen_e_acsl_and_7,(char *)"Assertion",(char *)"main", + (char *)"\\valid(p)",28); + } + /*@ assert ¬\valid(q); */ + { + int __gen_e_acsl_initialized_8; + int __gen_e_acsl_and_8; + __gen_e_acsl_initialized_8 = __e_acsl_initialized((void *)(& q), + sizeof(int *)); + if (__gen_e_acsl_initialized_8) { + int __gen_e_acsl_valid_8; + __gen_e_acsl_valid_8 = __e_acsl_valid((void *)q,sizeof(int),(void *)q, + (void *)(& q)); + __gen_e_acsl_and_8 = __gen_e_acsl_valid_8; + } + else __gen_e_acsl_and_8 = 0; + __e_acsl_assert(! __gen_e_acsl_and_8,(char *)"Assertion",(char *)"main", + (char *)"!\\valid(q)",29); + } + __e_acsl_initialize((void *)q,sizeof(int)); + *q = 1; + __e_acsl_initialize((void *)p,sizeof(int)); + *p = 2; + __e_acsl_temporal_reset_parameters(); + __e_acsl_temporal_reset_return(); + __e_acsl_full_init((void *)(& q)); + q = (int *)calloc((unsigned long)4096,(unsigned long)1); + __e_acsl_temporal_store_nblock((void *)(& q),(void *)*(& q)); + /*@ assert \valid(q); */ + { + int __gen_e_acsl_initialized_9; + int __gen_e_acsl_and_9; + __gen_e_acsl_initialized_9 = __e_acsl_initialized((void *)(& q), + sizeof(int *)); + if (__gen_e_acsl_initialized_9) { + int __gen_e_acsl_valid_9; + __gen_e_acsl_valid_9 = __e_acsl_valid((void *)q,sizeof(int),(void *)q, + (void *)(& q)); + __gen_e_acsl_and_9 = __gen_e_acsl_valid_9; + } + else __gen_e_acsl_and_9 = 0; + __e_acsl_assert(__gen_e_acsl_and_9,(char *)"Assertion",(char *)"main", + (char *)"\\valid(q)",35); + } + __e_acsl_temporal_reset_parameters(); + __e_acsl_temporal_reset_return(); + __e_acsl_temporal_save_nreferent_parameter((void *)(& q),0U); + __e_acsl_full_init((void *)(& q)); + q = (int *)realloc((void *)q,(unsigned long)8192); + __e_acsl_temporal_store_nblock((void *)(& q),(void *)*(& q)); + /*@ assert \valid(q); */ + { + int __gen_e_acsl_initialized_10; + int __gen_e_acsl_and_10; + __gen_e_acsl_initialized_10 = __e_acsl_initialized((void *)(& q), + sizeof(int *)); + if (__gen_e_acsl_initialized_10) { + int __gen_e_acsl_valid_10; + __gen_e_acsl_valid_10 = __e_acsl_valid((void *)q,sizeof(int),(void *)q, + (void *)(& q)); + __gen_e_acsl_and_10 = __gen_e_acsl_valid_10; + } + else __gen_e_acsl_and_10 = 0; + __e_acsl_assert(__gen_e_acsl_and_10,(char *)"Assertion",(char *)"main", + (char *)"\\valid(q)",39); + } + __retres = 0; + __e_acsl_delete_block((void *)(& q)); + __e_acsl_delete_block((void *)(& p)); + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/temporal/oracle_ci/gen_t_memcpy.c b/src/plugins/e-acsl/tests/temporal/oracle_ci/gen_t_memcpy.c new file mode 100644 index 0000000000000000000000000000000000000000..18a7163bb5648065ea7fb49a9c45a9a2b3e8343b --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/oracle_ci/gen_t_memcpy.c @@ -0,0 +1,354 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +#include "string.h" +extern int __e_acsl_sound_verdict; + +int main(void) +{ + int __retres; + int *src[2]; + int *dest[2]; + int *tmp_1; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + __e_acsl_store_block((void *)(& tmp_1),(size_t)8); + __e_acsl_store_block((void *)(dest),(size_t)16); + __e_acsl_store_block((void *)(src),(size_t)16); + int a = 111; + __e_acsl_store_block((void *)(& a),(size_t)4); + __e_acsl_full_init((void *)(& a)); + int b = 222; + __e_acsl_store_block((void *)(& b),(size_t)4); + __e_acsl_full_init((void *)(& b)); + int size = (int)(sizeof(int *) * (unsigned long)2); + __e_acsl_temporal_store_nblock((void *)(src),(void *)(& a)); + __e_acsl_initialize((void *)(src),sizeof(int *)); + src[0] = & a; + __e_acsl_temporal_store_nblock((void *)(& src[1]),(void *)(& b)); + __e_acsl_initialize((void *)(& src[1]),sizeof(int *)); + src[1] = & b; + __e_acsl_temporal_store_nblock((void *)(dest),(void *)0); + __e_acsl_initialize((void *)(dest),sizeof(int *)); + dest[0] = (int *)0; + __e_acsl_temporal_store_nblock((void *)(& dest[1]),(void *)0); + __e_acsl_initialize((void *)(& dest[1]),sizeof(int *)); + dest[1] = (int *)0; + /*@ assert \valid(src[0]); */ + { + int __gen_e_acsl_initialized; + int __gen_e_acsl_and; + __gen_e_acsl_initialized = __e_acsl_initialized((void *)(src), + sizeof(int *)); + if (__gen_e_acsl_initialized) { + int __gen_e_acsl_valid; + __gen_e_acsl_valid = __e_acsl_valid((void *)src[0],sizeof(int), + (void *)src[0],(void *)(src)); + __gen_e_acsl_and = __gen_e_acsl_valid; + } + else __gen_e_acsl_and = 0; + __e_acsl_assert(__gen_e_acsl_and,(char *)"Assertion",(char *)"main", + (char *)"\\valid(src[0])",22); + } + /*@ assert \valid(src[1]); */ + { + int __gen_e_acsl_initialized_2; + int __gen_e_acsl_and_2; + __gen_e_acsl_initialized_2 = __e_acsl_initialized((void *)(& src[1]), + sizeof(int *)); + if (__gen_e_acsl_initialized_2) { + int __gen_e_acsl_valid_2; + __gen_e_acsl_valid_2 = __e_acsl_valid((void *)src[1],sizeof(int), + (void *)src[1], + (void *)(& src[1])); + __gen_e_acsl_and_2 = __gen_e_acsl_valid_2; + } + else __gen_e_acsl_and_2 = 0; + __e_acsl_assert(__gen_e_acsl_and_2,(char *)"Assertion",(char *)"main", + (char *)"\\valid(src[1])",23); + } + __e_acsl_temporal_reset_parameters(); + __e_acsl_temporal_reset_return(); + __e_acsl_temporal_save_nblock_parameter((void *)(& dest),0U); + __e_acsl_temporal_save_nblock_parameter((void *)(& src),1U); + __gen_e_acsl_memcpy((void *)(& dest),(void const *)(& src), + (unsigned long)size); + /*@ assert \valid(dest[0]); */ + { + int __gen_e_acsl_initialized_3; + int __gen_e_acsl_and_3; + __gen_e_acsl_initialized_3 = __e_acsl_initialized((void *)(dest), + sizeof(int *)); + if (__gen_e_acsl_initialized_3) { + int __gen_e_acsl_valid_3; + __gen_e_acsl_valid_3 = __e_acsl_valid((void *)dest[0],sizeof(int), + (void *)dest[0],(void *)(dest)); + __gen_e_acsl_and_3 = __gen_e_acsl_valid_3; + } + else __gen_e_acsl_and_3 = 0; + __e_acsl_assert(__gen_e_acsl_and_3,(char *)"Assertion",(char *)"main", + (char *)"\\valid(dest[0])",27); + } + /*@ assert \valid(dest[1]); */ + { + int __gen_e_acsl_initialized_4; + int __gen_e_acsl_and_4; + __gen_e_acsl_initialized_4 = __e_acsl_initialized((void *)(& dest[1]), + sizeof(int *)); + if (__gen_e_acsl_initialized_4) { + int __gen_e_acsl_valid_4; + __gen_e_acsl_valid_4 = __e_acsl_valid((void *)dest[1],sizeof(int), + (void *)dest[1], + (void *)(& dest[1])); + __gen_e_acsl_and_4 = __gen_e_acsl_valid_4; + } + else __gen_e_acsl_and_4 = 0; + __e_acsl_assert(__gen_e_acsl_and_4,(char *)"Assertion",(char *)"main", + (char *)"\\valid(dest[1])",28); + } + __e_acsl_temporal_reset_parameters(); + __e_acsl_temporal_reset_return(); + __e_acsl_temporal_save_nblock_parameter((void *)(& dest),0U); + __gen_e_acsl_memset((void *)(& dest),0,(unsigned long)size); + /*@ assert ¬\valid(dest[0]); */ + { + int __gen_e_acsl_initialized_5; + int __gen_e_acsl_and_5; + __gen_e_acsl_initialized_5 = __e_acsl_initialized((void *)(dest), + sizeof(int *)); + if (__gen_e_acsl_initialized_5) { + int __gen_e_acsl_valid_5; + __gen_e_acsl_valid_5 = __e_acsl_valid((void *)dest[0],sizeof(int), + (void *)dest[0],(void *)(dest)); + __gen_e_acsl_and_5 = __gen_e_acsl_valid_5; + } + else __gen_e_acsl_and_5 = 0; + __e_acsl_assert(! __gen_e_acsl_and_5,(char *)"Assertion",(char *)"main", + (char *)"!\\valid(dest[0])",32); + } + /*@ assert ¬\valid(dest[1]); */ + { + int __gen_e_acsl_initialized_6; + int __gen_e_acsl_and_6; + __gen_e_acsl_initialized_6 = __e_acsl_initialized((void *)(& dest[1]), + sizeof(int *)); + if (__gen_e_acsl_initialized_6) { + int __gen_e_acsl_valid_6; + __gen_e_acsl_valid_6 = __e_acsl_valid((void *)dest[1],sizeof(int), + (void *)dest[1], + (void *)(& dest[1])); + __gen_e_acsl_and_6 = __gen_e_acsl_valid_6; + } + else __gen_e_acsl_and_6 = 0; + __e_acsl_assert(! __gen_e_acsl_and_6,(char *)"Assertion",(char *)"main", + (char *)"!\\valid(dest[1])",33); + } + __e_acsl_temporal_reset_parameters(); + __e_acsl_temporal_reset_return(); + int **p = malloc((unsigned long)size); + __e_acsl_store_block((void *)(& p),(size_t)8); + __e_acsl_full_init((void *)(& p)); + __e_acsl_temporal_store_nblock((void *)(& p),(void *)*(& p)); + __e_acsl_temporal_reset_parameters(); + __e_acsl_temporal_reset_return(); + int **q = malloc((unsigned long)size); + __e_acsl_store_block((void *)(& q),(size_t)8); + __e_acsl_full_init((void *)(& q)); + __e_acsl_temporal_store_nblock((void *)(& q),(void *)*(& q)); + __e_acsl_temporal_store_nblock((void *)p,(void *)(& a)); + __e_acsl_initialize((void *)p,sizeof(int *)); + *p = & a; + __e_acsl_temporal_store_nblock((void *)(p + 1),(void *)(& a)); + __e_acsl_initialize((void *)(p + 1),sizeof(int *)); + *(p + 1) = & a; + /*@ assert \valid(*p); */ + { + int __gen_e_acsl_initialized_7; + int __gen_e_acsl_and_8; + __gen_e_acsl_initialized_7 = __e_acsl_initialized((void *)p, + sizeof(int *)); + if (__gen_e_acsl_initialized_7) { + int __gen_e_acsl_initialized_8; + int __gen_e_acsl_and_7; + int __gen_e_acsl_valid_7; + __gen_e_acsl_initialized_8 = __e_acsl_initialized((void *)(& p), + sizeof(int **)); + if (__gen_e_acsl_initialized_8) { + int __gen_e_acsl_valid_read; + __gen_e_acsl_valid_read = __e_acsl_valid_read((void *)p, + sizeof(int *), + (void *)p, + (void *)(& p)); + __gen_e_acsl_and_7 = __gen_e_acsl_valid_read; + } + else __gen_e_acsl_and_7 = 0; + __e_acsl_assert(__gen_e_acsl_and_7,(char *)"RTE",(char *)"main", + (char *)"mem_access: \\valid_read(p)",42); + __gen_e_acsl_valid_7 = __e_acsl_valid((void *)*p,sizeof(int), + (void *)*p,(void *)p); + __gen_e_acsl_and_8 = __gen_e_acsl_valid_7; + } + else __gen_e_acsl_and_8 = 0; + __e_acsl_assert(__gen_e_acsl_and_8,(char *)"Assertion",(char *)"main", + (char *)"\\valid(*p)",42); + } + /*@ assert \valid(*(p + 1)); */ + { + int __gen_e_acsl_initialized_9; + int __gen_e_acsl_and_9; + __gen_e_acsl_initialized_9 = __e_acsl_initialized((void *)(p + 1), + sizeof(int *)); + if (__gen_e_acsl_initialized_9) { + int __gen_e_acsl_valid_read_2; + int __gen_e_acsl_valid_8; + __gen_e_acsl_valid_read_2 = __e_acsl_valid_read((void *)(p + 1), + sizeof(int *), + (void *)p, + (void *)(& p)); + __e_acsl_assert(__gen_e_acsl_valid_read_2,(char *)"RTE",(char *)"main", + (char *)"mem_access: \\valid_read(p + 1)",43); + __gen_e_acsl_valid_8 = __e_acsl_valid((void *)*(p + 1),sizeof(int), + (void *)*(p + 1),(void *)( + p + 1)); + __gen_e_acsl_and_9 = __gen_e_acsl_valid_8; + } + else __gen_e_acsl_and_9 = 0; + __e_acsl_assert(__gen_e_acsl_and_9,(char *)"Assertion",(char *)"main", + (char *)"\\valid(*(p + 1))",43); + } + /*@ assert ¬\valid(*q); */ + { + int __gen_e_acsl_initialized_10; + int __gen_e_acsl_and_11; + __gen_e_acsl_initialized_10 = __e_acsl_initialized((void *)q, + sizeof(int *)); + if (__gen_e_acsl_initialized_10) { + int __gen_e_acsl_initialized_11; + int __gen_e_acsl_and_10; + int __gen_e_acsl_valid_9; + __gen_e_acsl_initialized_11 = __e_acsl_initialized((void *)(& q), + sizeof(int **)); + if (__gen_e_acsl_initialized_11) { + int __gen_e_acsl_valid_read_3; + __gen_e_acsl_valid_read_3 = __e_acsl_valid_read((void *)q, + sizeof(int *), + (void *)q, + (void *)(& q)); + __gen_e_acsl_and_10 = __gen_e_acsl_valid_read_3; + } + else __gen_e_acsl_and_10 = 0; + __e_acsl_assert(__gen_e_acsl_and_10,(char *)"RTE",(char *)"main", + (char *)"mem_access: \\valid_read(q)",44); + __gen_e_acsl_valid_9 = __e_acsl_valid((void *)*q,sizeof(int), + (void *)*q,(void *)q); + __gen_e_acsl_and_11 = __gen_e_acsl_valid_9; + } + else __gen_e_acsl_and_11 = 0; + __e_acsl_assert(! __gen_e_acsl_and_11,(char *)"Assertion",(char *)"main", + (char *)"!\\valid(*q)",44); + } + /*@ assert ¬\valid(*(q + 1)); */ + { + int __gen_e_acsl_initialized_12; + int __gen_e_acsl_and_12; + __gen_e_acsl_initialized_12 = __e_acsl_initialized((void *)(q + 1), + sizeof(int *)); + if (__gen_e_acsl_initialized_12) { + int __gen_e_acsl_valid_read_4; + int __gen_e_acsl_valid_10; + __gen_e_acsl_valid_read_4 = __e_acsl_valid_read((void *)(q + 1), + sizeof(int *), + (void *)q, + (void *)(& q)); + __e_acsl_assert(__gen_e_acsl_valid_read_4,(char *)"RTE",(char *)"main", + (char *)"mem_access: \\valid_read(q + 1)",45); + __gen_e_acsl_valid_10 = __e_acsl_valid((void *)*(q + 1),sizeof(int), + (void *)*(q + 1), + (void *)(q + 1)); + __gen_e_acsl_and_12 = __gen_e_acsl_valid_10; + } + else __gen_e_acsl_and_12 = 0; + __e_acsl_assert(! __gen_e_acsl_and_12,(char *)"Assertion",(char *)"main", + (char *)"!\\valid(*(q + 1))",45); + } + __e_acsl_temporal_store_nblock((void *)(& tmp_1),(void *)0); + __e_acsl_full_init((void *)(& tmp_1)); + tmp_1 = (int *)0; + __e_acsl_temporal_store_nreferent((void *)(q + 1),(void *)(& tmp_1)); + __e_acsl_initialize((void *)(q + 1),sizeof(int *)); + *(q + 1) = tmp_1; + __e_acsl_temporal_store_nreferent((void *)q,(void *)(& tmp_1)); + __e_acsl_initialize((void *)q,sizeof(int *)); + *q = tmp_1; + __e_acsl_temporal_reset_parameters(); + __e_acsl_temporal_reset_return(); + __e_acsl_temporal_save_nreferent_parameter((void *)(& q),0U); + __e_acsl_temporal_save_nreferent_parameter((void *)(& p),1U); + __gen_e_acsl_memcpy((void *)q,(void const *)p,(unsigned long)size); + /*@ assert \valid(*q); */ + { + int __gen_e_acsl_initialized_13; + int __gen_e_acsl_and_14; + __gen_e_acsl_initialized_13 = __e_acsl_initialized((void *)q, + sizeof(int *)); + if (__gen_e_acsl_initialized_13) { + int __gen_e_acsl_initialized_14; + int __gen_e_acsl_and_13; + int __gen_e_acsl_valid_11; + __gen_e_acsl_initialized_14 = __e_acsl_initialized((void *)(& q), + sizeof(int **)); + if (__gen_e_acsl_initialized_14) { + int __gen_e_acsl_valid_read_5; + __gen_e_acsl_valid_read_5 = __e_acsl_valid_read((void *)q, + sizeof(int *), + (void *)q, + (void *)(& q)); + __gen_e_acsl_and_13 = __gen_e_acsl_valid_read_5; + } + else __gen_e_acsl_and_13 = 0; + __e_acsl_assert(__gen_e_acsl_and_13,(char *)"RTE",(char *)"main", + (char *)"mem_access: \\valid_read(q)",50); + __gen_e_acsl_valid_11 = __e_acsl_valid((void *)*q,sizeof(int), + (void *)*q,(void *)q); + __gen_e_acsl_and_14 = __gen_e_acsl_valid_11; + } + else __gen_e_acsl_and_14 = 0; + __e_acsl_assert(__gen_e_acsl_and_14,(char *)"Assertion",(char *)"main", + (char *)"\\valid(*q)",50); + } + /*@ assert \valid(*(q + 1)); */ + { + int __gen_e_acsl_initialized_15; + int __gen_e_acsl_and_15; + __gen_e_acsl_initialized_15 = __e_acsl_initialized((void *)(q + 1), + sizeof(int *)); + if (__gen_e_acsl_initialized_15) { + int __gen_e_acsl_valid_read_6; + int __gen_e_acsl_valid_12; + __gen_e_acsl_valid_read_6 = __e_acsl_valid_read((void *)(q + 1), + sizeof(int *), + (void *)q, + (void *)(& q)); + __e_acsl_assert(__gen_e_acsl_valid_read_6,(char *)"RTE",(char *)"main", + (char *)"mem_access: \\valid_read(q + 1)",51); + __gen_e_acsl_valid_12 = __e_acsl_valid((void *)*(q + 1),sizeof(int), + (void *)*(q + 1), + (void *)(q + 1)); + __gen_e_acsl_and_15 = __gen_e_acsl_valid_12; + } + else __gen_e_acsl_and_15 = 0; + __e_acsl_assert(__gen_e_acsl_and_15,(char *)"Assertion",(char *)"main", + (char *)"\\valid(*(q + 1))",51); + } + __retres = 0; + __e_acsl_delete_block((void *)(& tmp_1)); + __e_acsl_delete_block((void *)(& q)); + __e_acsl_delete_block((void *)(& p)); + __e_acsl_delete_block((void *)(dest)); + __e_acsl_delete_block((void *)(src)); + __e_acsl_delete_block((void *)(& b)); + __e_acsl_delete_block((void *)(& a)); + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/temporal/oracle_ci/gen_t_scope.c b/src/plugins/e-acsl/tests/temporal/oracle_ci/gen_t_scope.c new file mode 100644 index 0000000000000000000000000000000000000000..97a194255926be1246726597a6e88f902ee2c3a7 --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/oracle_ci/gen_t_scope.c @@ -0,0 +1,170 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +int main(void) +{ + int __retres; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + int *p = (int *)0; + __e_acsl_store_block((void *)(& p),(size_t)8); + __e_acsl_full_init((void *)(& p)); + __e_acsl_temporal_store_nblock((void *)(& p),(void *)0); + int *q = (int *)0; + __e_acsl_store_block((void *)(& q),(size_t)8); + __e_acsl_full_init((void *)(& q)); + __e_acsl_temporal_store_nblock((void *)(& q),(void *)0); + { + int i = 9; + __e_acsl_store_block((void *)(& i),(size_t)4); + __e_acsl_full_init((void *)(& i)); + __e_acsl_temporal_store_nblock((void *)(& p),(void *)(& i)); + __e_acsl_full_init((void *)(& p)); + p = & i; + __e_acsl_temporal_store_nreferent((void *)(& q),(void *)(& p)); + __e_acsl_full_init((void *)(& q)); + q = p; + __e_acsl_delete_block((void *)(& i)); + } + /*@ assert ¬\valid(p); */ + { + int __gen_e_acsl_initialized; + int __gen_e_acsl_and; + __gen_e_acsl_initialized = __e_acsl_initialized((void *)(& p), + sizeof(int *)); + if (__gen_e_acsl_initialized) { + int __gen_e_acsl_valid; + /*@ assert Eva: dangling_pointer: ¬\dangling(&p); */ + __gen_e_acsl_valid = __e_acsl_valid((void *)p,sizeof(int),(void *)p, + (void *)(& p)); + __gen_e_acsl_and = __gen_e_acsl_valid; + } + else __gen_e_acsl_and = 0; + __e_acsl_assert(! __gen_e_acsl_and,(char *)"Assertion",(char *)"main", + (char *)"!\\valid(p)",15); + } + /*@ assert ¬\valid(q); */ + { + int __gen_e_acsl_initialized_2; + int __gen_e_acsl_and_2; + __gen_e_acsl_initialized_2 = __e_acsl_initialized((void *)(& q), + sizeof(int *)); + if (__gen_e_acsl_initialized_2) { + int __gen_e_acsl_valid_2; + __gen_e_acsl_valid_2 = __e_acsl_valid((void *)q,sizeof(int),(void *)q, + (void *)(& q)); + __gen_e_acsl_and_2 = __gen_e_acsl_valid_2; + } + else __gen_e_acsl_and_2 = 0; + __e_acsl_assert(! __gen_e_acsl_and_2,(char *)"Assertion",(char *)"main", + (char *)"!\\valid(q)",16); + } + { + int j = 8; + __e_acsl_store_block((void *)(& j),(size_t)4); + __e_acsl_full_init((void *)(& j)); + __e_acsl_temporal_store_nblock((void *)(& p),(void *)(& j)); + __e_acsl_full_init((void *)(& p)); + p = & j; + /*@ assert \valid(p); */ + { + int __gen_e_acsl_initialized_3; + int __gen_e_acsl_and_3; + __gen_e_acsl_initialized_3 = __e_acsl_initialized((void *)(& p), + sizeof(int *)); + if (__gen_e_acsl_initialized_3) { + int __gen_e_acsl_valid_3; + __gen_e_acsl_valid_3 = __e_acsl_valid((void *)p,sizeof(int), + (void *)p,(void *)(& p)); + __gen_e_acsl_and_3 = __gen_e_acsl_valid_3; + } + else __gen_e_acsl_and_3 = 0; + __e_acsl_assert(__gen_e_acsl_and_3,(char *)"Assertion",(char *)"main", + (char *)"\\valid(p)",21); + } + __e_acsl_initialize((void *)p,sizeof(int)); + *p = 1; + /*@ assert ¬\valid(q); */ + { + int __gen_e_acsl_initialized_4; + int __gen_e_acsl_and_4; + __gen_e_acsl_initialized_4 = __e_acsl_initialized((void *)(& q), + sizeof(int *)); + if (__gen_e_acsl_initialized_4) { + int __gen_e_acsl_valid_4; + __gen_e_acsl_valid_4 = __e_acsl_valid((void *)q,sizeof(int), + (void *)q,(void *)(& q)); + __gen_e_acsl_and_4 = __gen_e_acsl_valid_4; + } + else __gen_e_acsl_and_4 = 0; + __e_acsl_assert(! __gen_e_acsl_and_4,(char *)"Assertion", + (char *)"main",(char *)"!\\valid(q)",24); + } + /*@ assert \valid(&j); */ + { + int __gen_e_acsl_valid_5; + __gen_e_acsl_valid_5 = __e_acsl_valid((void *)(& j),sizeof(int), + (void *)(& j),(void *)0); + __e_acsl_assert(__gen_e_acsl_valid_5,(char *)"Assertion", + (char *)"main",(char *)"\\valid(&j)",25); + __e_acsl_delete_block((void *)(& j)); + } + } + int len = 3; + __e_acsl_temporal_store_nblock((void *)(& p),(void *)0); + __e_acsl_full_init((void *)(& p)); + p = (int *)0; + __e_acsl_temporal_store_nblock((void *)(& q),(void *)0); + __e_acsl_full_init((void *)(& q)); + q = (int *)0; + while (len) { + int a; + __e_acsl_store_block((void *)(& a),(size_t)4); + /*@ assert ¬\valid(p); */ + { + int __gen_e_acsl_initialized_5; + int __gen_e_acsl_and_5; + __gen_e_acsl_initialized_5 = __e_acsl_initialized((void *)(& p), + sizeof(int *)); + if (__gen_e_acsl_initialized_5) { + int __gen_e_acsl_valid_6; + __gen_e_acsl_valid_6 = __e_acsl_valid((void *)p,sizeof(int), + (void *)p,(void *)(& p)); + __gen_e_acsl_and_5 = __gen_e_acsl_valid_6; + } + else __gen_e_acsl_and_5 = 0; + __e_acsl_assert(! __gen_e_acsl_and_5,(char *)"Assertion", + (char *)"main",(char *)"!\\valid(p)",34); + } + __e_acsl_temporal_store_nblock((void *)(& q),(void *)(& a)); + __e_acsl_full_init((void *)(& q)); + q = & a; + __e_acsl_temporal_store_nreferent((void *)(& p),(void *)(& q)); + __e_acsl_full_init((void *)(& p)); + p = q; + /*@ assert \valid(p); */ + { + int __gen_e_acsl_initialized_6; + int __gen_e_acsl_and_6; + __gen_e_acsl_initialized_6 = __e_acsl_initialized((void *)(& p), + sizeof(int *)); + if (__gen_e_acsl_initialized_6) { + int __gen_e_acsl_valid_7; + __gen_e_acsl_valid_7 = __e_acsl_valid((void *)p,sizeof(int), + (void *)p,(void *)(& p)); + __gen_e_acsl_and_6 = __gen_e_acsl_valid_7; + } + else __gen_e_acsl_and_6 = 0; + __e_acsl_assert(__gen_e_acsl_and_6,(char *)"Assertion",(char *)"main", + (char *)"\\valid(p)",37); + } + len --; + __e_acsl_delete_block((void *)(& a)); + } + __retres = 0; + __e_acsl_delete_block((void *)(& q)); + __e_acsl_delete_block((void *)(& p)); + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/temporal/oracle_ci/gen_t_struct.c b/src/plugins/e-acsl/tests/temporal/oracle_ci/gen_t_struct.c new file mode 100644 index 0000000000000000000000000000000000000000..7d490780a1bbd3802112f3a26d4d7e9d9358ddd4 --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/oracle_ci/gen_t_struct.c @@ -0,0 +1,334 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +struct temporal_t { + char *p ; + char *q ; +}; +struct larger_t { + char *p ; + char *q ; + struct temporal_t t ; +}; +typedef struct temporal_t temporal; +typedef struct larger_t larger; +int main(void) +{ + int __retres; + temporal t1; + temporal t2; + temporal *tp; + temporal tarr[2]; + larger l; + larger *lp; + larger larr[2]; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + __e_acsl_store_block((void *)(larr),(size_t)64); + __e_acsl_store_block((void *)(& lp),(size_t)8); + __e_acsl_store_block((void *)(& l),(size_t)32); + __e_acsl_store_block((void *)(tarr),(size_t)32); + __e_acsl_store_block((void *)(& t2),(size_t)16); + __e_acsl_store_block((void *)(& t1),(size_t)16); + int a = 1; + __e_acsl_store_block((void *)(& a),(size_t)4); + __e_acsl_full_init((void *)(& a)); + int b = 2; + __e_acsl_temporal_store_nblock((void *)(& t1.p),(void *)(& a)); + __e_acsl_initialize((void *)(& t1.p),sizeof(char *)); + t1.p = (char *)(& a); + __e_acsl_temporal_store_nreferent((void *)(& t1.q),(void *)(& t1.p)); + __e_acsl_initialize((void *)(& t1.q),sizeof(char *)); + t1.q = t1.p; + /*@ assert \valid(t1.p) ∧ \valid(t1.q); */ + { + int __gen_e_acsl_initialized; + int __gen_e_acsl_and; + int __gen_e_acsl_and_3; + __gen_e_acsl_initialized = __e_acsl_initialized((void *)(& t1.p), + sizeof(char *)); + if (__gen_e_acsl_initialized) { + int __gen_e_acsl_valid; + __gen_e_acsl_valid = __e_acsl_valid((void *)t1.p,sizeof(char), + (void *)t1.p,(void *)(& t1.p)); + __gen_e_acsl_and = __gen_e_acsl_valid; + } + else __gen_e_acsl_and = 0; + if (__gen_e_acsl_and) { + int __gen_e_acsl_initialized_2; + int __gen_e_acsl_and_2; + __gen_e_acsl_initialized_2 = __e_acsl_initialized((void *)(& t1.q), + sizeof(char *)); + if (__gen_e_acsl_initialized_2) { + int __gen_e_acsl_valid_2; + __gen_e_acsl_valid_2 = __e_acsl_valid((void *)t1.q,sizeof(char), + (void *)t1.q,(void *)(& t1.q)); + __gen_e_acsl_and_2 = __gen_e_acsl_valid_2; + } + else __gen_e_acsl_and_2 = 0; + __gen_e_acsl_and_3 = __gen_e_acsl_and_2; + } + else __gen_e_acsl_and_3 = 0; + __e_acsl_assert(__gen_e_acsl_and_3,(char *)"Assertion",(char *)"main", + (char *)"\\valid(t1.p) && \\valid(t1.q)",31); + } + /*@ assert ¬\valid(t2.p) ∧ ¬\valid(t2.q); */ + { + int __gen_e_acsl_initialized_3; + int __gen_e_acsl_and_4; + int __gen_e_acsl_and_6; + __gen_e_acsl_initialized_3 = __e_acsl_initialized((void *)(& t2.p), + sizeof(char *)); + if (__gen_e_acsl_initialized_3) { + int __gen_e_acsl_valid_3; + __gen_e_acsl_valid_3 = __e_acsl_valid((void *)t2.p,sizeof(char), + (void *)t2.p,(void *)(& t2.p)); + __gen_e_acsl_and_4 = __gen_e_acsl_valid_3; + } + else __gen_e_acsl_and_4 = 0; + if (! __gen_e_acsl_and_4) { + int __gen_e_acsl_initialized_4; + int __gen_e_acsl_and_5; + __gen_e_acsl_initialized_4 = __e_acsl_initialized((void *)(& t2.q), + sizeof(char *)); + if (__gen_e_acsl_initialized_4) { + int __gen_e_acsl_valid_4; + __gen_e_acsl_valid_4 = __e_acsl_valid((void *)t2.q,sizeof(char), + (void *)t2.q,(void *)(& t2.q)); + __gen_e_acsl_and_5 = __gen_e_acsl_valid_4; + } + else __gen_e_acsl_and_5 = 0; + __gen_e_acsl_and_6 = ! __gen_e_acsl_and_5; + } + else __gen_e_acsl_and_6 = 0; + __e_acsl_assert(__gen_e_acsl_and_6,(char *)"Assertion",(char *)"main", + (char *)"!\\valid(t2.p) && !\\valid(t2.q)",32); + } + __e_acsl_temporal_memcpy((void *)(& t2),(void *)(& t1),(size_t)16); + __e_acsl_full_init((void *)(& t2)); + t2 = t1; + /*@ assert \valid(t2.p) ∧ \valid(t2.q); */ + { + int __gen_e_acsl_initialized_5; + int __gen_e_acsl_and_7; + int __gen_e_acsl_and_9; + __gen_e_acsl_initialized_5 = __e_acsl_initialized((void *)(& t2.p), + sizeof(char *)); + if (__gen_e_acsl_initialized_5) { + int __gen_e_acsl_valid_5; + __gen_e_acsl_valid_5 = __e_acsl_valid((void *)t2.p,sizeof(char), + (void *)t2.p,(void *)(& t2.p)); + __gen_e_acsl_and_7 = __gen_e_acsl_valid_5; + } + else __gen_e_acsl_and_7 = 0; + if (__gen_e_acsl_and_7) { + int __gen_e_acsl_initialized_6; + int __gen_e_acsl_and_8; + __gen_e_acsl_initialized_6 = __e_acsl_initialized((void *)(& t2.q), + sizeof(char *)); + if (__gen_e_acsl_initialized_6) { + int __gen_e_acsl_valid_6; + __gen_e_acsl_valid_6 = __e_acsl_valid((void *)t2.q,sizeof(char), + (void *)t2.q,(void *)(& t2.q)); + __gen_e_acsl_and_8 = __gen_e_acsl_valid_6; + } + else __gen_e_acsl_and_8 = 0; + __gen_e_acsl_and_9 = __gen_e_acsl_and_8; + } + else __gen_e_acsl_and_9 = 0; + __e_acsl_assert(__gen_e_acsl_and_9,(char *)"Assertion",(char *)"main", + (char *)"\\valid(t2.p) && \\valid(t2.q)",35); + } + __e_acsl_temporal_store_nblock((void *)(& t2.p),(void *)0); + __e_acsl_initialize((void *)(& t2.p),sizeof(char *)); + t2.p = (char *)0; + __e_acsl_temporal_reset_parameters(); + __e_acsl_temporal_reset_return(); + __e_acsl_initialize((void *)(& t2.q),sizeof(char *)); + t2.q = (char *)malloc((unsigned long)4); + __e_acsl_temporal_store_nblock((void *)(& t2.q),(void *)*(& t2.q)); + /*@ assert ¬\valid(t2.p) ∧ \valid(t2.q); */ + { + int __gen_e_acsl_initialized_7; + int __gen_e_acsl_and_10; + int __gen_e_acsl_and_12; + __gen_e_acsl_initialized_7 = __e_acsl_initialized((void *)(& t2.p), + sizeof(char *)); + if (__gen_e_acsl_initialized_7) { + int __gen_e_acsl_valid_7; + __gen_e_acsl_valid_7 = __e_acsl_valid((void *)t2.p,sizeof(char), + (void *)t2.p,(void *)(& t2.p)); + __gen_e_acsl_and_10 = __gen_e_acsl_valid_7; + } + else __gen_e_acsl_and_10 = 0; + if (! __gen_e_acsl_and_10) { + int __gen_e_acsl_initialized_8; + int __gen_e_acsl_and_11; + __gen_e_acsl_initialized_8 = __e_acsl_initialized((void *)(& t2.q), + sizeof(char *)); + if (__gen_e_acsl_initialized_8) { + int __gen_e_acsl_valid_8; + __gen_e_acsl_valid_8 = __e_acsl_valid((void *)t2.q,sizeof(char), + (void *)t2.q,(void *)(& t2.q)); + __gen_e_acsl_and_11 = __gen_e_acsl_valid_8; + } + else __gen_e_acsl_and_11 = 0; + __gen_e_acsl_and_12 = __gen_e_acsl_and_11; + } + else __gen_e_acsl_and_12 = 0; + __e_acsl_assert(__gen_e_acsl_and_12,(char *)"Assertion",(char *)"main", + (char *)"!\\valid(t2.p) && \\valid(t2.q)",39); + } + __e_acsl_temporal_memcpy((void *)(& l.t),(void *)(& t2),(size_t)16); + __e_acsl_initialize((void *)(& l.t),sizeof(struct temporal_t)); + l.t = t2; + /*@ assert ¬\valid(l.t.p) ∧ \valid(l.t.q); */ + { + int __gen_e_acsl_initialized_9; + int __gen_e_acsl_and_13; + int __gen_e_acsl_and_15; + __gen_e_acsl_initialized_9 = __e_acsl_initialized((void *)(& l.t.p), + sizeof(char *)); + if (__gen_e_acsl_initialized_9) { + int __gen_e_acsl_valid_9; + __gen_e_acsl_valid_9 = __e_acsl_valid((void *)l.t.p,sizeof(char), + (void *)l.t.p,(void *)(& l.t.p)); + __gen_e_acsl_and_13 = __gen_e_acsl_valid_9; + } + else __gen_e_acsl_and_13 = 0; + if (! __gen_e_acsl_and_13) { + int __gen_e_acsl_initialized_10; + int __gen_e_acsl_and_14; + __gen_e_acsl_initialized_10 = __e_acsl_initialized((void *)(& l.t.q), + sizeof(char *)); + if (__gen_e_acsl_initialized_10) { + int __gen_e_acsl_valid_10; + __gen_e_acsl_valid_10 = __e_acsl_valid((void *)l.t.q,sizeof(char), + (void *)l.t.q, + (void *)(& l.t.q)); + __gen_e_acsl_and_14 = __gen_e_acsl_valid_10; + } + else __gen_e_acsl_and_14 = 0; + __gen_e_acsl_and_15 = __gen_e_acsl_and_14; + } + else __gen_e_acsl_and_15 = 0; + __e_acsl_assert(__gen_e_acsl_and_15,(char *)"Assertion",(char *)"main", + (char *)"!\\valid(l.t.p) && \\valid(l.t.q)",42); + } + __e_acsl_temporal_store_nblock((void *)(& lp),(void *)(& l)); + __e_acsl_full_init((void *)(& lp)); + lp = & l; + /*@ assert ¬\valid(lp->t.p); */ + { + int __gen_e_acsl_initialized_11; + int __gen_e_acsl_and_16; + __gen_e_acsl_initialized_11 = __e_acsl_initialized((void *)(& lp->t.p), + sizeof(char *)); + if (__gen_e_acsl_initialized_11) { + int __gen_e_acsl_valid_read; + int __gen_e_acsl_valid_11; + __gen_e_acsl_valid_read = __e_acsl_valid_read((void *)(& lp->t.p), + sizeof(char *), + (void *)(& lp->t.p), + (void *)0); + __e_acsl_assert(__gen_e_acsl_valid_read,(char *)"RTE",(char *)"main", + (char *)"mem_access: \\valid_read(&lp->t.p)",45); + __gen_e_acsl_valid_11 = __e_acsl_valid((void *)lp->t.p,sizeof(char), + (void *)lp->t.p, + (void *)(& lp->t.p)); + __gen_e_acsl_and_16 = __gen_e_acsl_valid_11; + } + else __gen_e_acsl_and_16 = 0; + __e_acsl_assert(! __gen_e_acsl_and_16,(char *)"Assertion",(char *)"main", + (char *)"!\\valid(lp->t.p)",45); + } + __e_acsl_temporal_memcpy((void *)(tarr),(void *)(& t2),(size_t)16); + __e_acsl_initialize((void *)(tarr),sizeof(temporal)); + tarr[0] = t2; + /*@ assert ¬\valid(tarr[0].p) ∧ \valid(tarr[0].q); */ + { + int __gen_e_acsl_initialized_12; + int __gen_e_acsl_and_17; + int __gen_e_acsl_and_19; + __gen_e_acsl_initialized_12 = __e_acsl_initialized((void *)(& tarr[0].p), + sizeof(char *)); + if (__gen_e_acsl_initialized_12) { + int __gen_e_acsl_valid_12; + __gen_e_acsl_valid_12 = __e_acsl_valid((void *)tarr[0].p,sizeof(char), + (void *)tarr[0].p, + (void *)(& tarr[0].p)); + __gen_e_acsl_and_17 = __gen_e_acsl_valid_12; + } + else __gen_e_acsl_and_17 = 0; + if (! __gen_e_acsl_and_17) { + int __gen_e_acsl_initialized_13; + int __gen_e_acsl_and_18; + __gen_e_acsl_initialized_13 = __e_acsl_initialized((void *)(& tarr[0].q), + sizeof(char *)); + if (__gen_e_acsl_initialized_13) { + int __gen_e_acsl_valid_13; + __gen_e_acsl_valid_13 = __e_acsl_valid((void *)tarr[0].q, + sizeof(char), + (void *)tarr[0].q, + (void *)(& tarr[0].q)); + __gen_e_acsl_and_18 = __gen_e_acsl_valid_13; + } + else __gen_e_acsl_and_18 = 0; + __gen_e_acsl_and_19 = __gen_e_acsl_and_18; + } + else __gen_e_acsl_and_19 = 0; + __e_acsl_assert(__gen_e_acsl_and_19,(char *)"Assertion",(char *)"main", + (char *)"!\\valid(tarr[0].p) && \\valid(tarr[0].q)",48); + } + __e_acsl_temporal_memcpy((void *)(larr),(void *)(& l),(size_t)32); + __e_acsl_initialize((void *)(larr),sizeof(larger)); + larr[0] = l; + /*@ assert ¬\valid(larr[0].t.p) ∧ \valid(larr[0].t.q); */ + { + int __gen_e_acsl_initialized_14; + int __gen_e_acsl_and_20; + int __gen_e_acsl_and_22; + __gen_e_acsl_initialized_14 = __e_acsl_initialized((void *)(& larr[0].t.p), + sizeof(char *)); + if (__gen_e_acsl_initialized_14) { + int __gen_e_acsl_valid_14; + __gen_e_acsl_valid_14 = __e_acsl_valid((void *)larr[0].t.p, + sizeof(char), + (void *)larr[0].t.p, + (void *)(& larr[0].t.p)); + __gen_e_acsl_and_20 = __gen_e_acsl_valid_14; + } + else __gen_e_acsl_and_20 = 0; + if (! __gen_e_acsl_and_20) { + int __gen_e_acsl_initialized_15; + int __gen_e_acsl_and_21; + __gen_e_acsl_initialized_15 = __e_acsl_initialized((void *)(& larr[0].t.q), + sizeof(char *)); + if (__gen_e_acsl_initialized_15) { + int __gen_e_acsl_valid_15; + __gen_e_acsl_valid_15 = __e_acsl_valid((void *)larr[0].t.q, + sizeof(char), + (void *)larr[0].t.q, + (void *)(& larr[0].t.q)); + __gen_e_acsl_and_21 = __gen_e_acsl_valid_15; + } + else __gen_e_acsl_and_21 = 0; + __gen_e_acsl_and_22 = __gen_e_acsl_and_21; + } + else __gen_e_acsl_and_22 = 0; + __e_acsl_assert(__gen_e_acsl_and_22,(char *)"Assertion",(char *)"main", + (char *)"!\\valid(larr[0].t.p) && \\valid(larr[0].t.q)", + 51); + } + __retres = 0; + __e_acsl_delete_block((void *)(larr)); + __e_acsl_delete_block((void *)(& lp)); + __e_acsl_delete_block((void *)(& l)); + __e_acsl_delete_block((void *)(tarr)); + __e_acsl_delete_block((void *)(& t2)); + __e_acsl_delete_block((void *)(& t1)); + __e_acsl_delete_block((void *)(& a)); + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/temporal/oracle_ci/gen_t_while.c b/src/plugins/e-acsl/tests/temporal/oracle_ci/gen_t_while.c new file mode 100644 index 0000000000000000000000000000000000000000..9937815b7dd006e5f3a1d742e57abeb456a02079 --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/oracle_ci/gen_t_while.c @@ -0,0 +1,69 @@ +/* Generated by Frama-C */ +#include "stdio.h" +#include "stdlib.h" +int main(void) +{ + int __retres; + __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8); + int i = 0; + int arr[4] = {1, 2, 3, 4}; + __e_acsl_store_block((void *)(arr),(size_t)16); + __e_acsl_full_init((void *)(& arr)); + int arr2[4] = {1, 2, 3, 4}; + if (! ((unsigned long)(& arr) + sizeof(arr) == (unsigned long)(& arr2))) { + __retres = 0; + goto return_label; + } + int *q = arr; + __e_acsl_store_block((void *)(& q),(size_t)8); + __e_acsl_full_init((void *)(& q)); + __e_acsl_temporal_store_nblock((void *)(& q),(void *)(arr)); + while (i < 4) { + /*@ assert \valid(q); */ + { + int __gen_e_acsl_initialized; + int __gen_e_acsl_and; + __gen_e_acsl_initialized = __e_acsl_initialized((void *)(& q), + sizeof(int *)); + if (__gen_e_acsl_initialized) { + int __gen_e_acsl_valid; + __gen_e_acsl_valid = __e_acsl_valid((void *)q,sizeof(int),(void *)q, + (void *)(& q)); + __gen_e_acsl_and = __gen_e_acsl_valid; + } + else __gen_e_acsl_and = 0; + __e_acsl_assert(__gen_e_acsl_and,(char *)"Assertion",(char *)"main", + (char *)"\\valid(q)",28); + } + __e_acsl_initialize((void *)q,sizeof(int)); + *q = 1; + i ++; + __e_acsl_temporal_store_nreferent((void *)(& q),(void *)(& q)); + __e_acsl_full_init((void *)(& q)); + q ++; + } + /*@ assert ¬\valid(q); */ + { + int __gen_e_acsl_initialized_2; + int __gen_e_acsl_and_2; + __gen_e_acsl_initialized_2 = __e_acsl_initialized((void *)(& q), + sizeof(int *)); + if (__gen_e_acsl_initialized_2) { + int __gen_e_acsl_valid_2; + __gen_e_acsl_valid_2 = __e_acsl_valid((void *)q,sizeof(int),(void *)q, + (void *)(& q)); + __gen_e_acsl_and_2 = __gen_e_acsl_valid_2; + } + else __gen_e_acsl_and_2 = 0; + __e_acsl_assert(! __gen_e_acsl_and_2,(char *)"Assertion",(char *)"main", + (char *)"!\\valid(q)",36); + } + __retres = 0; + return_label: __e_acsl_store_block_duplicate((void *)(& q),(size_t)8); + __e_acsl_delete_block((void *)(& q)); + __e_acsl_delete_block((void *)(arr)); + __e_acsl_memory_clean(); + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/temporal/oracle_ci/t_addr-by-val.res.oracle b/src/plugins/e-acsl/tests/temporal/oracle_ci/t_addr-by-val.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..efd026311297e55d8fefb674326118e6ece88624 --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/oracle_ci/t_addr-by-val.res.oracle @@ -0,0 +1,2 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". diff --git a/src/plugins/e-acsl/tests/temporal/oracle_ci/t_args.res.oracle b/src/plugins/e-acsl/tests/temporal/oracle_ci/t_args.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..109e6b127fbe65f35b5e3f35c9f57083f244e9c7 --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/oracle_ci/t_args.res.oracle @@ -0,0 +1,5 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". +[eva:alarm] tests/temporal/t_args.c:9: Warning: assertion got status unknown. +[eva:alarm] tests/temporal/t_args.c:10: Warning: + assertion got status invalid (stopping propagation). diff --git a/src/plugins/e-acsl/tests/temporal/oracle_ci/t_array.res.oracle b/src/plugins/e-acsl/tests/temporal/oracle_ci/t_array.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..efd026311297e55d8fefb674326118e6ece88624 --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/oracle_ci/t_array.res.oracle @@ -0,0 +1,2 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". diff --git a/src/plugins/e-acsl/tests/temporal/oracle_ci/t_char.res.oracle b/src/plugins/e-acsl/tests/temporal/oracle_ci/t_char.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..efd026311297e55d8fefb674326118e6ece88624 --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/oracle_ci/t_char.res.oracle @@ -0,0 +1,2 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". diff --git a/src/plugins/e-acsl/tests/temporal/oracle_ci/t_darray.res.oracle b/src/plugins/e-acsl/tests/temporal/oracle_ci/t_darray.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..efd026311297e55d8fefb674326118e6ece88624 --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/oracle_ci/t_darray.res.oracle @@ -0,0 +1,2 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". diff --git a/src/plugins/e-acsl/tests/temporal/oracle_ci/t_dpointer.res.oracle b/src/plugins/e-acsl/tests/temporal/oracle_ci/t_dpointer.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..21729109cb68251a57b9eff5cad0029b98846874 --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/oracle_ci/t_dpointer.res.oracle @@ -0,0 +1,23 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". +[eva:alarm] tests/temporal/t_dpointer.c:12: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/temporal/t_dpointer.c:13: Warning: + accessing uninitialized left-value. assert \initialized(p + i); +[eva:alarm] tests/temporal/t_dpointer.c:14: Warning: + assertion got status unknown. +[eva:alarm] tests/temporal/t_dpointer.c:14: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/temporal/t_dpointer.c:14: Warning: + accessing uninitialized left-value. assert \initialized(p + i); +[eva:alarm] tests/temporal/t_dpointer.c:14: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/temporal/t_dpointer.c:18: Warning: + accessing uninitialized left-value. assert \initialized(p + 2); +[eva:alarm] tests/temporal/t_dpointer.c:20: Warning: + assertion got status unknown. +[eva:alarm] tests/temporal/t_dpointer.c:20: Warning: + accessing left-value that contains escaping addresses. + assert ¬\dangling(p + 2); +[eva:alarm] tests/temporal/t_dpointer.c:20: Warning: + function __e_acsl_assert: precondition got status unknown. diff --git a/src/plugins/e-acsl/tests/temporal/oracle_ci/t_fptr.res.oracle b/src/plugins/e-acsl/tests/temporal/oracle_ci/t_fptr.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..3ebbc96533dfb8eb8fc1bc8ebeb7bf384333845b --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/oracle_ci/t_fptr.res.oracle @@ -0,0 +1,6 @@ +[e-acsl] beginning translation. +[e-acsl] tests/temporal/t_fptr.c:19: Warning: + function pointers may introduce too limited instrumentation. +[e-acsl] tests/temporal/t_fptr.c:17: Warning: + E-ACSL construct `\valid_function' is not yet supported. Ignoring annotation. +[e-acsl] translation done in project "e-acsl". diff --git a/src/plugins/e-acsl/tests/temporal/oracle_ci/t_fun_lib.res.oracle b/src/plugins/e-acsl/tests/temporal/oracle_ci/t_fun_lib.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..fc9ae49cf5d4eef82de513ee5baa9d6baa60ee18 --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/oracle_ci/t_fun_lib.res.oracle @@ -0,0 +1,12 @@ +[kernel:typing:implicit-function-declaration] tests/temporal/t_fun_lib.c:20: Warning: + Calling undeclared function realpath. Old style K&R code? +[e-acsl] beginning translation. +[kernel:annot:missing-spec] tests/temporal/t_fun_lib.c:20: Warning: + Neither code nor specification for function realpath, generating default assigns from the prototype +[e-acsl] translation done in project "e-acsl". +[eva:invalid-assigns] tests/temporal/t_fun_lib.c:20: + Completely invalid destination for assigns clause *(x_0 + (0 ..)). Ignoring. +[eva:invalid-assigns] tests/temporal/t_fun_lib.c:21: + Completely invalid destination for assigns clause *(x_0 + (0 ..)). Ignoring. +[eva:alarm] tests/temporal/t_fun_lib.c:23: Warning: + assertion got status invalid (stopping propagation). diff --git a/src/plugins/e-acsl/tests/temporal/oracle_ci/t_fun_ptr.res.oracle b/src/plugins/e-acsl/tests/temporal/oracle_ci/t_fun_ptr.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..efd026311297e55d8fefb674326118e6ece88624 --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/oracle_ci/t_fun_ptr.res.oracle @@ -0,0 +1,2 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". diff --git a/src/plugins/e-acsl/tests/temporal/oracle_ci/t_getenv.res.oracle b/src/plugins/e-acsl/tests/temporal/oracle_ci/t_getenv.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..5bf1e434ea0bef8969daa036635dbd2343a9a58c --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/oracle_ci/t_getenv.res.oracle @@ -0,0 +1,27 @@ +[e-acsl] beginning translation. +[e-acsl] Warning: annotating undefined function `getenv': + the generated program may miss memory instrumentation + if there are memory-related annotations. +[e-acsl] FRAMAC_SHARE/libc/stdlib.h:486: Warning: + E-ACSL construct `logic functions with labels' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/stdlib.h:486: Warning: + E-ACSL construct `assigns clause in behavior' is not yet supported. + Ignoring annotation. +[e-acsl] translation done in project "e-acsl". +[eva:alarm] FRAMAC_SHARE/libc/stdlib.h:488: Warning: + pointer comparison. assert \pointer_comparable((void *)__retres, (void *)0); +[eva:alarm] FRAMAC_SHARE/libc/stdlib.h:488: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] FRAMAC_SHARE/libc/stdlib.h:488: Warning: + function __gen_e_acsl_getenv: postcondition 'null_or_valid_result' got status unknown. +[eva:alarm] tests/temporal/t_getenv.c:13: Warning: assertion got status unknown. +[eva:alarm] tests/temporal/t_getenv.c:13: Warning: + pointer comparison. assert \pointer_comparable((void *)g1, (void *)0); +[eva:alarm] tests/temporal/t_getenv.c:13: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/temporal/t_getenv.c:14: Warning: assertion got status unknown. +[eva:alarm] tests/temporal/t_getenv.c:14: Warning: + pointer comparison. assert \pointer_comparable((void *)g2, (void *)0); +[eva:alarm] tests/temporal/t_getenv.c:14: Warning: + function __e_acsl_assert: precondition got status unknown. diff --git a/src/plugins/e-acsl/tests/temporal/oracle_ci/t_global_init.res.oracle b/src/plugins/e-acsl/tests/temporal/oracle_ci/t_global_init.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..efd026311297e55d8fefb674326118e6ece88624 --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/oracle_ci/t_global_init.res.oracle @@ -0,0 +1,2 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". diff --git a/src/plugins/e-acsl/tests/temporal/oracle_ci/t_labels.res.oracle b/src/plugins/e-acsl/tests/temporal/oracle_ci/t_labels.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..efd026311297e55d8fefb674326118e6ece88624 --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/oracle_ci/t_labels.res.oracle @@ -0,0 +1,2 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". diff --git a/src/plugins/e-acsl/tests/temporal/oracle_ci/t_lit_string.res.oracle b/src/plugins/e-acsl/tests/temporal/oracle_ci/t_lit_string.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..efd026311297e55d8fefb674326118e6ece88624 --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/oracle_ci/t_lit_string.res.oracle @@ -0,0 +1,2 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". diff --git a/src/plugins/e-acsl/tests/temporal/oracle_ci/t_local_init.res.oracle b/src/plugins/e-acsl/tests/temporal/oracle_ci/t_local_init.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..efd026311297e55d8fefb674326118e6ece88624 --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/oracle_ci/t_local_init.res.oracle @@ -0,0 +1,2 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". diff --git a/src/plugins/e-acsl/tests/temporal/oracle_ci/t_malloc-asan.res.oracle b/src/plugins/e-acsl/tests/temporal/oracle_ci/t_malloc-asan.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..724e589f6a9ab229a708dc2ee95bac42f01267ae --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/oracle_ci/t_malloc-asan.res.oracle @@ -0,0 +1,7 @@ +[e-acsl] beginning translation. +[kernel:annot:missing-spec] FRAMAC_SHARE/libc/stdio.h:169: Warning: + Neither code nor specification for function printf, generating default assigns from the prototype +[e-acsl] translation done in project "e-acsl". +[eva:alarm] tests/temporal/t_malloc-asan.c:28: Warning: + accessing left-value that contains escaping addresses. + assert ¬\dangling(&q); diff --git a/src/plugins/e-acsl/tests/temporal/oracle_ci/t_malloc.res.oracle b/src/plugins/e-acsl/tests/temporal/oracle_ci/t_malloc.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..01e8d6abf31a734a75a7b78bf851da3fd7fe38e2 --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/oracle_ci/t_malloc.res.oracle @@ -0,0 +1,5 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". +[eva:alarm] tests/temporal/t_malloc.c:22: Warning: + accessing left-value that contains escaping addresses. + assert ¬\dangling(&p); diff --git a/src/plugins/e-acsl/tests/temporal/oracle_ci/t_memcpy.res.oracle b/src/plugins/e-acsl/tests/temporal/oracle_ci/t_memcpy.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..c88bb93bb619661810e3435aa84bf288519fdd55 --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/oracle_ci/t_memcpy.res.oracle @@ -0,0 +1,38 @@ +[e-acsl] beginning translation. +[e-acsl] Warning: annotating undefined function `memcpy': + the generated program may miss memory instrumentation + if there are memory-related annotations. +[e-acsl] Warning: annotating undefined function `memset': + the generated program may miss memory instrumentation + if there are memory-related annotations. +[e-acsl] FRAMAC_SHARE/libc/string.h:92: Warning: + E-ACSL construct `\separated' is not yet supported. Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/string.h:115: Warning: + E-ACSL construct `logic functions with labels' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/string.h:115: Warning: + E-ACSL construct `assigns clause in behavior' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/string.h:118: Warning: + E-ACSL construct `user-defined logic type' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/string.h:92: Warning: + E-ACSL construct `logic functions with labels' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/string.h:93: Warning: + E-ACSL construct `logic functions with labels' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/string.h:95: Warning: + E-ACSL construct `\separated' is not yet supported. Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/string.h:95: Warning: + E-ACSL construct `assigns clause in behavior' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/string.h:98: Warning: + E-ACSL construct `logic functions performing read accesses' + is not yet supported. + Ignoring annotation. +[e-acsl] translation done in project "e-acsl". +[eva:alarm] FRAMAC_SHARE/libc/string.h:98: Warning: + function __gen_e_acsl_memcpy: postcondition 'copied_contents' got status unknown. +[eva:alarm] FRAMAC_SHARE/libc/string.h:118: Warning: + function __gen_e_acsl_memset: postcondition 'acsl_c_equiv' got status unknown. diff --git a/src/plugins/e-acsl/tests/temporal/oracle_ci/t_scope.res.oracle b/src/plugins/e-acsl/tests/temporal/oracle_ci/t_scope.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..9826a53ef7efbcc35395480a2eb83765489302ab --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/oracle_ci/t_scope.res.oracle @@ -0,0 +1,9 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". +[eva:locals-escaping] tests/temporal/t_scope.c:10: Warning: + locals {i} escaping the scope of a block of main through p +[eva:locals-escaping] tests/temporal/t_scope.c:10: Warning: + locals {i} escaping the scope of a block of main through q +[eva:alarm] tests/temporal/t_scope.c:15: Warning: + accessing left-value that contains escaping addresses. + assert ¬\dangling(&p); diff --git a/src/plugins/e-acsl/tests/temporal/oracle_ci/t_struct.res.oracle b/src/plugins/e-acsl/tests/temporal/oracle_ci/t_struct.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..efd026311297e55d8fefb674326118e6ece88624 --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/oracle_ci/t_struct.res.oracle @@ -0,0 +1,2 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". diff --git a/src/plugins/e-acsl/tests/temporal/oracle_ci/t_while.res.oracle b/src/plugins/e-acsl/tests/temporal/oracle_ci/t_while.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..bd8576fda63776eee412e843db616eec38e8cc45 --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/oracle_ci/t_while.res.oracle @@ -0,0 +1,8 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". +[eva:alarm] tests/temporal/t_while.c:28: Warning: + function __e_acsl_assert: precondition got status unknown. +[eva:alarm] tests/temporal/t_while.c:28: Warning: assertion got status unknown. +[eva:alarm] tests/temporal/t_while.c:36: Warning: assertion got status unknown. +[eva:alarm] tests/temporal/t_while.c:36: Warning: + function __e_acsl_assert: precondition got status unknown. diff --git a/src/plugins/e-acsl/tests/temporal/oracle_dev/t_addr-by-val.res.oracle b/src/plugins/e-acsl/tests/temporal/oracle_dev/t_addr-by-val.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..6c6987459b8f35382cf162b4814d67a73001e3e5 --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/oracle_dev/t_addr-by-val.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/temporal/t_addr-by-val.c (with preprocessing) diff --git a/src/plugins/e-acsl/tests/temporal/oracle_dev/t_args.res.oracle b/src/plugins/e-acsl/tests/temporal/oracle_dev/t_args.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..5416bcc06c1764cde8f9851606aef790b17ba138 --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/oracle_dev/t_args.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/temporal/t_args.c (with preprocessing) diff --git a/src/plugins/e-acsl/tests/temporal/oracle_dev/t_array.res.oracle b/src/plugins/e-acsl/tests/temporal/oracle_dev/t_array.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..08a70fa93d302403de8b8e4dc4bf959cbc698a19 --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/oracle_dev/t_array.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/temporal/t_array.c (with preprocessing) diff --git a/src/plugins/e-acsl/tests/temporal/oracle_dev/t_char.res.oracle b/src/plugins/e-acsl/tests/temporal/oracle_dev/t_char.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..0e80917c3d153c8b123d3b1802a11b12735d2a94 --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/oracle_dev/t_char.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/temporal/t_char.c (with preprocessing) diff --git a/src/plugins/e-acsl/tests/temporal/oracle_dev/t_darray.res.oracle b/src/plugins/e-acsl/tests/temporal/oracle_dev/t_darray.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..63872161277dfbf0ebb5b2ac19593e308ce6f94e --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/oracle_dev/t_darray.res.oracle @@ -0,0 +1,12 @@ +[kernel] Parsing tests/temporal/t_darray.c (with preprocessing) +[kernel] tests/temporal/t_darray.c:17: User Error: + empty initializers only allowed for GCC/MSVC + 15 + 16 double Vertices[3][4]; + 17 double Vertices2[3][4] = {}; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 18 + 19 int main(int argc, const char **argv) { +[kernel] User Error: stopping on file "tests/temporal/t_darray.c" that has errors. Add + '-kernel-msg-key pp' for preprocessing command. +[kernel] Frama-C aborted: invalid user input. diff --git a/src/plugins/e-acsl/tests/temporal/oracle_dev/t_dpointer.res.oracle b/src/plugins/e-acsl/tests/temporal/oracle_dev/t_dpointer.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..0e725129643c7b30e93ea6195c25aba9922e6972 --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/oracle_dev/t_dpointer.res.oracle @@ -0,0 +1,5 @@ +[kernel] User Error: cannot load plug-in 'frama-c-e_acsl': cannot load module + Details: error loading shared library: Dynlink.Error (Dynlink.Cannot_open_dll "Failure(\"./top/E_ACSL.cmxs: cannot open shared object file: No such file or directory\")") +[kernel] User Error: compilation of './tests/print.ml' failed +[kernel] User Error: Deferred error message was emitted during execution. See above messages for more information. +[kernel] Frama-C aborted: invalid user input. diff --git a/src/plugins/e-acsl/tests/temporal/oracle_dev/t_fptr.res.oracle b/src/plugins/e-acsl/tests/temporal/oracle_dev/t_fptr.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..0d1fede17ec74668949362f9d42a73335964b48c --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/oracle_dev/t_fptr.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/temporal/t_fptr.c (with preprocessing) diff --git a/src/plugins/e-acsl/tests/temporal/oracle_dev/t_fun_lib.res.oracle b/src/plugins/e-acsl/tests/temporal/oracle_dev/t_fun_lib.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..5d97f1e4656d14e5379908861e5cdb1ab98995ba --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/oracle_dev/t_fun_lib.res.oracle @@ -0,0 +1,3 @@ +[kernel] Parsing tests/temporal/t_fun_lib.c (with preprocessing) +[kernel:typing:implicit-function-declaration] tests/temporal/t_fun_lib.c:20: Warning: + Calling undeclared function realpath. Old style K&R code? diff --git a/src/plugins/e-acsl/tests/temporal/oracle_dev/t_fun_ptr.res.oracle b/src/plugins/e-acsl/tests/temporal/oracle_dev/t_fun_ptr.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..0b50d95b38f263d8b94551a2bed66f9101f29029 --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/oracle_dev/t_fun_ptr.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/temporal/t_fun_ptr.c (with preprocessing) diff --git a/src/plugins/e-acsl/tests/temporal/oracle_dev/t_getenv.res.oracle b/src/plugins/e-acsl/tests/temporal/oracle_dev/t_getenv.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..45c2b6834f7254653cfc96bd1f7cb4f8a53ea163 --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/oracle_dev/t_getenv.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/temporal/t_getenv.c (with preprocessing) diff --git a/src/plugins/e-acsl/tests/temporal/oracle_dev/t_global_init.res.oracle b/src/plugins/e-acsl/tests/temporal/oracle_dev/t_global_init.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..33a7eb427f45fb397dce6f04cdee3d8e4de325fe --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/oracle_dev/t_global_init.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/temporal/t_global_init.c (with preprocessing) diff --git a/src/plugins/e-acsl/tests/temporal/oracle_dev/t_labels.res.oracle b/src/plugins/e-acsl/tests/temporal/oracle_dev/t_labels.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..4246bf9d0533032254f2253d85e4129696e99379 --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/oracle_dev/t_labels.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/temporal/t_labels.c (with preprocessing) diff --git a/src/plugins/e-acsl/tests/temporal/oracle_dev/t_lit_string.res.oracle b/src/plugins/e-acsl/tests/temporal/oracle_dev/t_lit_string.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..6992e96210c075574977992126484a978ab93aa2 --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/oracle_dev/t_lit_string.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/temporal/t_lit_string.c (with preprocessing) diff --git a/src/plugins/e-acsl/tests/temporal/oracle_dev/t_local_init.res.oracle b/src/plugins/e-acsl/tests/temporal/oracle_dev/t_local_init.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..195b9e93c1fee84731bf7f97cb54e18760ccd095 --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/oracle_dev/t_local_init.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/temporal/t_local_init.c (with preprocessing) diff --git a/src/plugins/e-acsl/tests/temporal/oracle_dev/t_malloc-asan.res.oracle b/src/plugins/e-acsl/tests/temporal/oracle_dev/t_malloc-asan.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..0186cd4c1e3d0e5ac636ade4077be6f342ebe920 --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/oracle_dev/t_malloc-asan.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/temporal/t_malloc-asan.c (with preprocessing) diff --git a/src/plugins/e-acsl/tests/temporal/oracle_dev/t_malloc.res.oracle b/src/plugins/e-acsl/tests/temporal/oracle_dev/t_malloc.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..0e725129643c7b30e93ea6195c25aba9922e6972 --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/oracle_dev/t_malloc.res.oracle @@ -0,0 +1,5 @@ +[kernel] User Error: cannot load plug-in 'frama-c-e_acsl': cannot load module + Details: error loading shared library: Dynlink.Error (Dynlink.Cannot_open_dll "Failure(\"./top/E_ACSL.cmxs: cannot open shared object file: No such file or directory\")") +[kernel] User Error: compilation of './tests/print.ml' failed +[kernel] User Error: Deferred error message was emitted during execution. See above messages for more information. +[kernel] Frama-C aborted: invalid user input. diff --git a/src/plugins/e-acsl/tests/temporal/oracle_dev/t_memcpy.res.oracle b/src/plugins/e-acsl/tests/temporal/oracle_dev/t_memcpy.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..a2ea974992bd8ead8978265b8bc93ada317e795d --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/oracle_dev/t_memcpy.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/temporal/t_memcpy.c (with preprocessing) diff --git a/src/plugins/e-acsl/tests/temporal/oracle_dev/t_scope.res.oracle b/src/plugins/e-acsl/tests/temporal/oracle_dev/t_scope.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..6af29643dcce11eb46a179d0074b4071c5fda849 --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/oracle_dev/t_scope.res.oracle @@ -0,0 +1,6 @@ +[kernel] User Error: cannot load plug-in 'frama-c-e_acsl': cannot load module + Details: error loading shared library: Dynlink.Error (Dynlink.Cannot_open_dll "Failure(\"./top/E_ACSL.cmxs: cannot open shared object file: No such file or directory\")") +[kernel] User Error: cannot load plug-in 'print': cannot load module + Details: error loading shared library: Dynlink.Error (Dynlink.Cannot_open_dll "Failure(\"./tests/print.cmxs: cannot open shared object file: No such file or directory\")") +[kernel] User Error: Deferred error message was emitted during execution. See above messages for more information. +[kernel] Frama-C aborted: invalid user input. diff --git a/src/plugins/e-acsl/tests/temporal/oracle_dev/t_struct.res.oracle b/src/plugins/e-acsl/tests/temporal/oracle_dev/t_struct.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..364bbe79ba49ad4e18fd601d0a6ae50a7f616985 --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/oracle_dev/t_struct.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/temporal/t_struct.c (with preprocessing) diff --git a/src/plugins/e-acsl/tests/temporal/oracle_dev/t_while.res.oracle b/src/plugins/e-acsl/tests/temporal/oracle_dev/t_while.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..2cc42109513b2955f1424545ef0d5d38224f8409 --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/oracle_dev/t_while.res.oracle @@ -0,0 +1 @@ +[kernel] Parsing tests/temporal/t_while.c (with preprocessing) diff --git a/src/plugins/e-acsl/tests/temporal/t_addr-by-val.c b/src/plugins/e-acsl/tests/temporal/t_addr-by-val.c new file mode 100644 index 0000000000000000000000000000000000000000..562cc4e026c35f45fdeb94e9e2c0b3aa32a65bf2 --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/t_addr-by-val.c @@ -0,0 +1,18 @@ +/* run.config + COMMENT: Case when a pointer is taking address by value. +*/ + +#include <stdint.h> + +int main (int argc, char **argv) { + uintptr_t addr = (uintptr_t)&argc; + char *p; + int *q; + q = &argc; + /* Here the referent of p should be assigned from the value of addr */ + p = (char*)addr; + p = (char*)0x123456; + p = (char*)q; +} + + diff --git a/src/plugins/e-acsl/tests/temporal/t_args.c b/src/plugins/e-acsl/tests/temporal/t_args.c new file mode 100644 index 0000000000000000000000000000000000000000..c48b3e093e24048261d1b2db5c1b19ca0a608591 --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/t_args.c @@ -0,0 +1,12 @@ +/* run.config + COMMENT: Check that command line parameters are properly tracked +*/ + +#include <stdio.h> + +int main(int argc, const char **argv) { + /*@assert \valid(&argc); */ + /*@assert \valid(argv); */ + /*@assert \valid(*argv); */ + return 0; +} diff --git a/src/plugins/e-acsl/tests/temporal/t_array.c b/src/plugins/e-acsl/tests/temporal/t_array.c new file mode 100644 index 0000000000000000000000000000000000000000..ff2e8be836240ac5e912b987a75f6279d755f697 --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/t_array.c @@ -0,0 +1,18 @@ +/* run.config + COMMENT: Check temporal timestamps of arrays +*/ + +int main() { + int a = 111, + b = 222; + + int *src[3]; + src[0] = &a; + src[1] = &b; + + /*@assert \valid(src[0]); */ + /*@assert \valid(src[1]); */ + /*@assert ! \valid(src[2]); */ + return 0; +} + diff --git a/src/plugins/e-acsl/tests/temporal/t_char.c b/src/plugins/e-acsl/tests/temporal/t_char.c new file mode 100644 index 0000000000000000000000000000000000000000..e8f001a3a72234a6f6a1a7073b8ce02c82d9cd1f --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/t_char.c @@ -0,0 +1,20 @@ +/* run.config + COMMENT: Check that when small blocks (such as char) are used the + COMMENT: instrumentation adds alignment sufficient for tracking + COMMENT: block origin number via shadowing +*/ + +int main(int argc, const char **argv) { + char a = '1', + b = '2'; + /* Should fail here in debug mode due to overlapping shadow spaces + of [a] and [b]*/ + + char *p = &a, + *q = &b; + + p = q; + /*@assert \valid(p); */ + /*@assert \valid(q); */ + return 0; +} diff --git a/src/plugins/e-acsl/tests/temporal/t_darray.c b/src/plugins/e-acsl/tests/temporal/t_darray.c new file mode 100644 index 0000000000000000000000000000000000000000..88c1cf9712022c1c32ccf47259fe968c4f633f5b --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/t_darray.c @@ -0,0 +1,38 @@ +/* run.config + COMMENT: Checking propagation of referent numbers in arrays +*/ + +void area_triangle(double (*vertices)[4]) { + /*@ assert rte: mem_access: \valid_read((double *)*(vertices + 0)); */ + /*@ assert rte: mem_access: \valid_read((double *)*(vertices + 1)); */ + return; +} + +void abe_matrix(double (*vertices)[4]) { + area_triangle(vertices); + return; +} + +double Vertices[3][4]; +double Vertices2[3][4] = {}; + +int main(int argc, const char **argv) { + double vertices[3][4] = { + { 1.0, 2.0, 3.0, 4.0 }, + { 5.0, 6.0, 7.0, 8.0 }, + { 9.0, 10.0, 11.0, 12.0 } + }; + double vertices2[3][4]; + double vertices3[3][4]; + double triple_vertices[2][3][4]; + double triple_vertices2[2][3][4] = {}; + + abe_matrix(vertices); + abe_matrix(vertices2); + abe_matrix(vertices3); + abe_matrix(Vertices); + abe_matrix(Vertices2); + abe_matrix(triple_vertices[0]); + abe_matrix(triple_vertices2[0]); + return 0; +} diff --git a/src/plugins/e-acsl/tests/temporal/t_dpointer.c b/src/plugins/e-acsl/tests/temporal/t_dpointer.c new file mode 100644 index 0000000000000000000000000000000000000000..215ede69a5ac728d2b0a61f805a1711ed12f1d45 --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/t_dpointer.c @@ -0,0 +1,22 @@ +/* run.config + COMMENT: Simple case of double pointer dereference +*/ + +#include <stdlib.h> + +int main(void) { + int **p = malloc(sizeof(int*)*3); + int i = 0; + + while (i < 3) { + /*@assert \valid(p+i); */ + *(p+i) = malloc(sizeof(int)); + /*@assert \valid(*(p+i)); */ + i++; + } + + free(*(p+2)); + malloc(sizeof(int)); + /*@assert ! \valid(*(p+2)); */ + return 0; +} diff --git a/src/plugins/e-acsl/tests/temporal/t_fptr.c b/src/plugins/e-acsl/tests/temporal/t_fptr.c new file mode 100644 index 0000000000000000000000000000000000000000..0afcc96640d51099799db3fc1e9b96033fbb43a2 --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/t_fptr.c @@ -0,0 +1,22 @@ +/* run.config + COMMENT: Check simple case of calling functions via pointer derefernce +*/ + +int* foo(int *p) { + int *q = p; + return q; +} + +int main(int argc, const char **argv) { + int *p = &argc, + *q; + + int* (*fp)(int*) = &foo; + + fp = &foo; + /*@assert \valid_function(fp); */ + + q = (*fp)(p); + /*@assert \valid(q); */ + return 0; +} diff --git a/src/plugins/e-acsl/tests/temporal/t_fun_lib.c b/src/plugins/e-acsl/tests/temporal/t_fun_lib.c new file mode 100644 index 0000000000000000000000000000000000000000..d98643937bbd1161685ee1a6b7e265d41f53e0c1 --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/t_fun_lib.c @@ -0,0 +1,32 @@ +/* run.config + COMMENT: Check handling library functions (without definitions) +*/ + +#include <stdlib.h> +#include <limits.h> + +int main(void) { + char *c = "."; + /* Allocating function (such as malloc, recognized by name): + - take block number of the returned pointer (after) */ + char *p = malloc(PATH_MAX), + *q = NULL; + q = malloc(PATH_MAX); + + /*@assert \valid(q) && \valid(p); */ + + /* Function with no definition returning a pointer: + same treatment as allocating function */ + char *path = realpath(c, q); + path = realpath(c, q); + + /*@assert \valid(path); */ + + /* Function with no definition and no return value: + do nothing */ + free(p); + free(path); + + /*@assert ! \valid(p) && !\valid(path); */ + return 0; +} diff --git a/src/plugins/e-acsl/tests/temporal/t_fun_ptr.c b/src/plugins/e-acsl/tests/temporal/t_fun_ptr.c new file mode 100644 index 0000000000000000000000000000000000000000..d0637544973e1bac493f0bc6e51b672fe7863aba --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/t_fun_ptr.c @@ -0,0 +1,32 @@ +/* run.config + COMMENT: Check handling function definitions with pointer parameters +*/ + +#include <stdint.h> +#include <stdlib.h> + +int* pfun(char c, int *p, int *p2, int *p3, int *p4, int i) { + int *q = p; + return q; +} + +int main(int argc, const char **argv) { + int a = 1; + int *p = &a; + uintptr_t addr = (uintptr_t)&addr; + + /* Function with definition returning a pointer: + - save all pointer parameters + + call via pointer - save referent number + + call via addressof - sabe block number + + call via NULL - save invalid + + call via value - save block number + - store return referent in return handler + - take referent number of the return value (via return handler) */ + p = pfun('a', p, &a, NULL, (int*)addr, 2); + + /*@assert \valid(p); */ + return 0; +} + + diff --git a/src/plugins/e-acsl/tests/temporal/t_getenv.c b/src/plugins/e-acsl/tests/temporal/t_getenv.c new file mode 100644 index 0000000000000000000000000000000000000000..1f5066ee368a1ddccbb1c7773329bae6ab84d13c --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/t_getenv.c @@ -0,0 +1,16 @@ +/* run.config + COMMENT: Check temporal validity of environment string (via getenv function) +*/ +#include <stdlib.h> +#include <errno.h> + + +int main(int argc, const char **argv) { + char *g1 = NULL; + g1 = getenv("HOME"); + char *g2 = getenv("PATH"); + + /*@assert g1 == \null || \valid(g1); */ + /*@assert g2 == \null || \valid(g2); */ + return 0; +} diff --git a/src/plugins/e-acsl/tests/temporal/t_global_init.c b/src/plugins/e-acsl/tests/temporal/t_global_init.c new file mode 100644 index 0000000000000000000000000000000000000000..12db105293a830e83debcc59b873cf392cd3eb37 --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/t_global_init.c @@ -0,0 +1,64 @@ +/* run.config + COMMENT: Check global compound variable initializers +*/ + +struct tree_desc { + int *extra_bits ; +}; + +typedef struct tree_desc tree_desc; + +struct tree_desc2 { + struct tree_desc desc; +}; + +typedef struct tree_desc2 tree_desc2; + +static int extra_lbits[] = {0}; + +static tree_desc l_desc = + /* This bit should be tracked via globals_init function */ + { .extra_bits = extra_lbits }; + +static tree_desc descs [2] = { + { .extra_bits = extra_lbits }, + { .extra_bits = extra_lbits } +}; + +static tree_desc2 l_desc2 = + { .desc = { .extra_bits = extra_lbits } }; + +static tree_desc2 descs2 [2] = { + { .desc = { .extra_bits = extra_lbits } }, + { .desc = { .extra_bits = extra_lbits } } +}; + +void build_tree(tree_desc *desc) { + int *extra; + extra = desc->extra_bits; + /*@assert \valid(extra); */ +} + +const char * strings [2][2] = { + { "the", "tha" }, + { "thi", "tho" } +}; + +int main(int argc, const char **argv) { + build_tree(&l_desc); + build_tree(&descs[0]); + build_tree(&descs[1]); + build_tree(&l_desc2.desc); + build_tree(&descs2[0].desc); + build_tree(&descs2[1].desc); + + char **p = (char**)&strings[0]; + + /*@assert \valid_read(p); */ + /*@assert \valid_read(*p); */ + + return 0; +} + + + diff --git a/src/plugins/e-acsl/tests/temporal/t_labels.c b/src/plugins/e-acsl/tests/temporal/t_labels.c new file mode 100644 index 0000000000000000000000000000000000000000..5d82c469b0fca0fea19e9c8867e9f6d1d05a8d60 --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/t_labels.c @@ -0,0 +1,34 @@ +/* run.config + COMMENT: Check that statements generated via temporal analysis are handled + COMMENT: properly, i.e., if a statement has a label attached then all + COMMENT: the generated statements are inserted after that label +*/ + +void foo(int *a, int *b) { + int t = *a; + *a = *b; + *b = t; +} + +int *Q; +int* bar() { +RET: + return Q; +} + +int main(int argc, const char **argv) { + int a = 11, + b = 12; + + int *p = &a, + *q = &b; + +LAB: + foo(p, q); + /*@assert \valid(p) && \valid(q); */ + +LAB2: + q = p; + /*@assert \valid(p); */ + return 0; +} diff --git a/src/plugins/e-acsl/tests/temporal/t_lit_string.c b/src/plugins/e-acsl/tests/temporal/t_lit_string.c new file mode 100644 index 0000000000000000000000000000000000000000..2469f352b4105cbdafccc9422054e0724ad84100 --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/t_lit_string.c @@ -0,0 +1,20 @@ +/* run.config + COMMENT: Check handling of literal strings. Because literal strings are + COMMENT: replaced by variables we need to make sure that we take block + COMMENT: numbers and not referent numbers in assignments +*/ + +int main(void) { + char *f = "f"; + /*@assert \valid_read(f) && !\valid(f); */ + char *g; + g = "g"; + /*@assert \valid_read(g) && !\valid(g); */ + + char *p = f; + /*@assert \valid_read(p) && !\valid(p); */ + char *q; + q = f; + /*@assert \valid_read(q) && !\valid(q); */ + return 0; +} diff --git a/src/plugins/e-acsl/tests/temporal/t_local_init.c b/src/plugins/e-acsl/tests/temporal/t_local_init.c new file mode 100644 index 0000000000000000000000000000000000000000..01afaf3dbcc4216c7b0c5d3d85ef91fb51e63a5d --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/t_local_init.c @@ -0,0 +1,86 @@ +/* run.config + COMMENT: Check local compound variable initializers +*/ + +#include <stdio.h> +#include <stddef.h> + +struct tree_desc { + int *extra_bits ; +}; + +typedef struct tree_desc tree_desc; + +struct tree_desc2 { + struct tree_desc desc; +}; + +typedef struct tree_desc2 tree_desc2; + +void build_tree(tree_desc *desc) { + int *extra; + extra = desc->extra_bits; + /*@assert \valid(extra); */ +} + +char * Strings [2][2] = { + { "the", "tha" }, + { "thi", "tho" } +}; + +char * Str [4] = { "foo", "bar", "baz", NULL }; + +int main(int argc, const char **argv) { + char * strings [2][2] = { + { "the", "tha" }, + { "thi", "tho" } + }; + + char **p = (char**)&strings[0]; + + /*@assert \valid_read(p); */ + /*@assert \valid_read(*p); */ + + char * str [4] = { "foo", "bar", "baz", NULL }; + + p = (char**)&str; + + /*@assert \valid_read(p); */ + /*@assert \valid_read(*p); */ + + char **P = (char**)&Strings[0]; + + /*@assert \valid_read(P); */ + /*@assert \valid_read(*P); */ + + P = (char**)&Str; + + /*@assert \valid_read(P); */ + /*@assert \valid_read(*P); */ + + int extra_lbits[] = {0}; + + tree_desc l_desc = + { .extra_bits = extra_lbits }; + + tree_desc descs [2] = { + { .extra_bits = extra_lbits }, + { .extra_bits = extra_lbits } + }; + + tree_desc2 l_desc2 = + { .desc = { .extra_bits = extra_lbits } }; + + tree_desc2 descs2 [2] = { + { .desc = { .extra_bits = extra_lbits } }, + { .desc = { .extra_bits = extra_lbits } } + }; + + build_tree(&l_desc); + build_tree(&descs[0]); + build_tree(&descs[1]); + build_tree(&l_desc2.desc); + build_tree(&descs2[0].desc); + build_tree(&descs2[1].desc); + return 0; +} diff --git a/src/plugins/e-acsl/tests/temporal/t_malloc-asan.c b/src/plugins/e-acsl/tests/temporal/t_malloc-asan.c new file mode 100644 index 0000000000000000000000000000000000000000..78f96e9145f8a1189dab9aad45a56ea0b1da1fd4 --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/t_malloc-asan.c @@ -0,0 +1,45 @@ +/* run.config + COMMENT: Temporal analysis with respect dynamic memory allocation. + COMMENT: malloc-free-malloc errors + COMMENT: This test is a modification aiming targeting AddressSanitizer and + COMMENT: Valgrind tools who are not capable of catching this bug +*/ + +#include <stdlib.h> +#include <stdio.h> + +#define MB (1024*1024) + +int main(void) { + int *p, *q; + int counter = 0; + size_t limit = 10000; + + p = (int*)malloc(MB); + q = p; + + free(p); + + /* Allocate and de-allocate a chunk of + memory until allocator reuses address */ + while (counter < limit) { + p = (int*)malloc(MB); + counter++; + if (p != q) + free(p); + else { + printf("Same address %p in %d steps\n", p, counter); + break; + } + p = NULL; + } + + if (p) { + *q = 1; /* temporally invalid */ + *p = 2; + } + + free(p); + return 0; +} + diff --git a/src/plugins/e-acsl/tests/temporal/t_malloc.c b/src/plugins/e-acsl/tests/temporal/t_malloc.c new file mode 100644 index 0000000000000000000000000000000000000000..9ae3b5d0a280fb86e55ce5f5f18fc32bc2022c58 --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/t_malloc.c @@ -0,0 +1,41 @@ +/* run.config + COMMENT: Temporal analysis with respect dynamic memory allocation. + COMMENT: malloc-free-malloc errors +*/ + +#include <stdlib.h> + +int main(void) { + int *p, *q; + + /*@assert ! \valid(p); */ + /*@assert ! \valid(q); */ + + p = (int*)malloc(sizeof(int)); + q = p; + + /*@assert \valid(p); */ + /*@assert \valid(q); */ + + free(q); + + /*@assert ! \valid(p); */ + /*@assert ! \valid(q); */ + + p = (int*)malloc(sizeof(int)); + /* q is temporally invalid: points to the block allocated by the first malloc + call which has been deallocated, while p is valid */ + /*@assert \valid(p); */ + /*@assert ! \valid(q);*/ + *q = 1; + *p = 2; + + /* ... and for calloc .. */ + q = (char*)calloc(4096,1); + /*@assert \valid(q); */ + + /* ... and and realloc */ + q = (char*)realloc(q, 8192); + /*@assert \valid(q); */ + return 0; +} diff --git a/src/plugins/e-acsl/tests/temporal/t_memcpy.c b/src/plugins/e-acsl/tests/temporal/t_memcpy.c new file mode 100644 index 0000000000000000000000000000000000000000..c18b0fcc2504f613fc472eeb72ab0a85947b6465 --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/t_memcpy.c @@ -0,0 +1,53 @@ +#include <string.h> +#include <stdlib.h> + +int main() { + /* ********** STACK ********** */ + int a = 111, + b = 222; + + int *src[2], + *dest[2]; + + int size = sizeof(int*)*2; + + src[0] = &a; + src[1] = &b; + + /* FIXME: memcpy should initialize, + since so far it does not do the initialization by hand */ + dest[0] = NULL; + dest[1] = NULL; + + /*@assert \valid(*src); */ + /*@assert \valid(*(src + 1)); */ + + memcpy(&dest, &src, size); + + /*@ assert \valid(*dest); */ + /*@ assert \valid(*(dest + 1)); */ + + memset(&dest, 0, size); + + /*@assert ! \valid(*dest); */ + /*@assert ! \valid(*(dest + 1)); */ + + /* ********** HEAP ********** */ + int **p = malloc(size); + int **q = malloc(size); + + *p = &a; + *(p+1) = &a; + + /*@assert \valid(*p); */ + /*@assert \valid(*(p+1)); */ + /*@assert ! \valid(*q); */ + /*@assert ! \valid(*(q+1)); */ + + *q = *(q+1) = NULL; + memcpy(q, p, size); + + /*@assert \valid(*q); */ + /*@assert \valid(*(q+1)); */ + return 0; +} diff --git a/src/plugins/e-acsl/tests/temporal/t_scope.c b/src/plugins/e-acsl/tests/temporal/t_scope.c new file mode 100644 index 0000000000000000000000000000000000000000..d023e0fb4971bc3bba5d01a973b341698a94751b --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/t_scope.c @@ -0,0 +1,41 @@ +/* run.config + COMMENT: Temporal analysis with respect to scopes +*/ +#include <stddef.h> + +int main() { + int *p = NULL, + *q = NULL; + { + int i = 9; + p = &i; + q = p; + } + + /*@assert ! \valid(p); */ + /*@assert ! \valid(q); */ + + { + int j = 8; + p = &j; + /*@assert \valid(p); */ + *p = 1; + /* `q` now may point to `j`, bit not necessarily */ + /*@assert ! \valid(q); */ + /*@assert \valid(&j); */ + } + + /* Example from Arvid's report (Listing 3.12) */ + int len = 3; + p = NULL, + q = NULL; + while (len) { + int a; + /*@assert ! \valid(p); */ + q = &a; + p = q; + /*@assert \valid(p); */ + len--; + } + return 0; +} diff --git a/src/plugins/e-acsl/tests/temporal/t_struct.c b/src/plugins/e-acsl/tests/temporal/t_struct.c new file mode 100644 index 0000000000000000000000000000000000000000..e72e879cf605c315e6b69d6579dc479e4e6648f2 --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/t_struct.c @@ -0,0 +1,53 @@ +/* run.config + COMMENT: Several basic cases involving assignments of structs +*/ + +/* Data types and typedefs {{{ */ +#include <stdlib.h> + +struct temporal_t { + char *p; + char *q; +}; + +struct larger_t { + char *p; + char *q; + struct temporal_t t; +}; + +typedef struct temporal_t temporal; +typedef struct larger_t larger; +/* }}} */ + +int main(void) { + int a = 1, + b = 2; + temporal t1, t2, *tp, tarr[2]; + larger l, *lp, larr[2]; + + t1.p = &a; + t1.q = t1.p; + /*@assert \valid(t1.p) && \valid(t1.q); */ + /*@assert !\valid(t2.p) && !\valid(t2.q); */ + + t2 = t1; + /*@assert \valid(t2.p) && \valid(t2.q); */ + + t2.p = NULL; + t2.q = malloc(4); + /*@assert ! \valid(t2.p) && \valid(t2.q); */ + + l.t = t2; + /*@assert ! \valid(l.t.p) && \valid(l.t.q); */ + + lp = &l; + /*@assert ! \valid(lp->t.p); */ + + tarr[0] = t2; + /*@assert ! \valid(tarr[0].p) && \valid(tarr[0].q) ; */ + + larr[0] = l; + /*@assert ! \valid(larr[0].t.p) && \valid(larr[0].t.q) ; */ + return 0; +} diff --git a/src/plugins/e-acsl/tests/temporal/t_while.c b/src/plugins/e-acsl/tests/temporal/t_while.c new file mode 100644 index 0000000000000000000000000000000000000000..7f39075385affd69ef3175b72ce9090142ca9b59 --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/t_while.c @@ -0,0 +1,39 @@ +/* run.config + COMMENT: Off-by-one error where a pointer is made point to an adjacent block + COMMENT: Note that this behaviour is not quaranteed by likely due to the + COMMENT: way compiler allocates stack blocks +*/ + +#include <stdint.h> + +#define intaddr(_x) ((uintptr_t)&_x) + +int main(void) { + int i = 0; + /* Assuming here that arr is allocated first, and arr2 is allocated second + and that there is no gap betwee [arr] and [arr2]. This behaviour is + compiler specific but still likely. At least this is the case for some + current versions of GCC/Clang */ + int arr [] = {1, 2, 3, 4}; + int arr2 [] = {1, 2, 3, 4}; + + /* Check that the above condition holds, otherwise there is no point + having this test */ + if (!(intaddr(arr) + sizeof(arr) == intaddr(arr2))) + return 0; + + int *q = arr; + + while (i < 4) { + /*@assert \valid(q); */ + *q = 1; /* This dereference of [q] is valid but the last [q++] */ + i++; /* makes [q] point to [arr2] */ + q++; + } + + /* At this point the dereference is temporally invalid since [q] should store + the referent number of [arr1] while in fact it points to [arr2] */ + /*@assert ! \valid(q); */ + // *q = 1; + return 0; +} diff --git a/src/plugins/e-acsl/tests/temporal/test_config_ci b/src/plugins/e-acsl/tests/temporal/test_config_ci new file mode 100644 index 0000000000000000000000000000000000000000..97ef89959b1fa033cd7f606ab27baf37085b81a5 --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/test_config_ci @@ -0,0 +1 @@ +STDOPT: #"-e-acsl-temporal-validity" diff --git a/src/plugins/e-acsl/tests/temporal/test_config_dev b/src/plugins/e-acsl/tests/temporal/test_config_dev new file mode 100644 index 0000000000000000000000000000000000000000..3e4efa8f66f6c143ffd1a88b850d8f87a29c7314 --- /dev/null +++ b/src/plugins/e-acsl/tests/temporal/test_config_dev @@ -0,0 +1,5 @@ +DONTRUN: +MACRO: DEST @PTEST_RESULT@/gen_@PTEST_NAME@ +MACRO: OUT @PTEST_NAME@.res.log +MACRO: ERR @PTEST_NAME@.err.log +EXEC: ./scripts/e-acsl-gcc.sh --temporal -q -c -X --frama-c-extra="-journal-disable -verbose 0 -kernel-warn-key *=inactive" -o @DEST@.run.c -O @DEST@.out @PTEST_FILE@ > @PTEST_RESULT@/@OUT@ 2> @PTEST_RESULT@/@ERR@ && ./@DEST@.e-acsl > /dev/null diff --git a/src/plugins/e-acsl/tests/test_config_ci.in b/src/plugins/e-acsl/tests/test_config_ci.in new file mode 100644 index 0000000000000000000000000000000000000000..7bf6bf598f0dca59d1ae6b98e7ade86a58bcceef --- /dev/null +++ b/src/plugins/e-acsl/tests/test_config_ci.in @@ -0,0 +1,11 @@ +MACRO: DEST @PTEST_RESULT@/gen_@PTEST_NAME@ +MACRO: GLOBAL -machdep gcc_x86_64 -variadic-no-translation -verbose 0 +MACRO: EACSL -e-acsl -e-acsl-share ./share/e-acsl -e-acsl-verbose 1 +MACRO: EVA -eva -eva-no-alloc-returns-null -eva-no-results -eva-no-print -eva-warn-key libc:unsupported-spec=inactive +MACRO: EVENTUALLY -print -ocode @DEST@.c -load-script ./tests/print.cmxs +LOG: gen_@PTEST_NAME@.c +OPT: @GLOBAL@ @EACSL@ -then-last @EVA@ @EVENTUALLY@ +FILTER:@SEDCMD@ -e "s|[a-zA-Z/\\]\+frama_c_project_e-acsl_[a-z0-9]*|PROJECT_FILE|" -e "s|$FRAMAC_SHARE|FRAMAC_SHARE|g" -e "s|../../share|FRAMAC_SHARE|g" -e "s|./share/e-acsl|FRAMAC_SHARE/e-acsl|g" -e "s|share/e-acsl|FRAMAC_SHARE/e-acsl|g" +COMMENT: This regex works around the tendency of Frama-C to transform +COMMENT: absolute path into relative ones whenever the file is not too far +COMMENT: away from cwd. diff --git a/src/plugins/e-acsl/tests/test_config_dev.in b/src/plugins/e-acsl/tests/test_config_dev.in new file mode 100644 index 0000000000000000000000000000000000000000..3285052cca07ca1f06e1e0964335a5ebf139c797 --- /dev/null +++ b/src/plugins/e-acsl/tests/test_config_dev.in @@ -0,0 +1,4 @@ +MACRO: DEST @PTEST_RESULT@/@PTEST_NAME@ +MACRO: OUT @PTEST_NAME@.res.log +MACRO: ERR @PTEST_NAME@.err.log +EXEC: BIN @DEST@.gcc.c ./scripts/e-acsl-gcc.sh -q -c -X --frama-c-extra="-journal-disable -verbose 0 -kernel-warn-key *=inactive" -o @DEST@.gcc.c -O @DEST@ @PTEST_FILE@ > @PTEST_RESULT@/@OUT@ 2> @PTEST_RESULT@/@ERR@ && ./@DEST@.e-acsl > /dev/null