diff --git a/headers/header_spec.txt b/headers/header_spec.txt index 36de74a9f38df23c208828edc7d84fa141a14027..509d0627ae8b5724d772b34288850461b48a0cf7 100644 --- a/headers/header_spec.txt +++ b/headers/header_spec.txt @@ -293,6 +293,7 @@ share/libc/syslog.h: CEA_LGPL share/libc/termios.h: CEA_LGPL share/libc/tgmath.h: CEA_LGPL share/libc/time.h: CEA_LGPL +share/libc/time.c: CEA_LGPL share/libc/uchar.h: CEA_LGPL share/libc/unistd.h: CEA_LGPL share/libc/utime.h: CEA_LGPL diff --git a/share/libc/time.c b/share/libc/time.c new file mode 100644 index 0000000000000000000000000000000000000000..5873b4c76d2491dc09ccb183b21a81a34b41045f --- /dev/null +++ b/share/libc/time.c @@ -0,0 +1,37 @@ +/**************************************************************************/ +/* */ +/* This file is part of Frama-C. */ +/* */ +/* Copyright (C) 2007-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 "time.h" +#include "__fc_builtin.h" +__PUSH_FC_STDLIB + +extern char __fc_ctime[26]; + +extern char *ctime(const time_t *timer) { + //@ assert \valid_read(timer); + //@ assert \initialized(timer); + Frama_C_make_unknown(__fc_ctime, 26); + __fc_ctime[25] = 0; + return __fc_ctime; +} + +__POP_FC_STDLIB diff --git a/share/libc/time.h b/share/libc/time.h index eaedd90b305382315161acbbb68cf4a79c3960cb..9ca1d0cadab05c06e25d70c1771262e87be61a89 100644 --- a/share/libc/time.h +++ b/share/libc/time.h @@ -104,8 +104,19 @@ extern time_t mktime(struct tm *timeptr); */ extern time_t time(time_t *timer); +char __fc_ctime[26]; +char * const __fc_p_ctime = &__fc_ctime; + extern char *asctime(const struct tm *timeptr); +/*@ + requires valid_timer: \valid_read(timer); + requires initialization:init_timer: \initialized(timer); + assigns __fc_ctime[0..25] \from indirect:*timer, indirect:__fc_time; + assigns \result \from indirect:*timer, indirect:__fc_time, __fc_p_ctime; + ensures result_points_to_ctime: \result == __fc_p_ctime; + ensures result_valid_string: valid_read_string(__fc_p_ctime); +*/ extern char *ctime(const time_t *timer); struct tm __fc_time_tm; diff --git a/tests/libc/oracle/fc_libc.0.res.oracle b/tests/libc/oracle/fc_libc.0.res.oracle index c20ad3c51dd3215ec23183ee400ac4ffd9809d77..ffa163ed517ced7ae131d1bd9f87f61300909256 100644 --- a/tests/libc/oracle/fc_libc.0.res.oracle +++ b/tests/libc/oracle/fc_libc.0.res.oracle @@ -37,7 +37,7 @@ wcslen (2 calls); wcsncat (0 call); wcsncpy (0 call); wmemcpy (0 call); wmemset (0 call); - Undefined functions (357) + Undefined functions (358) ========================= FD_CLR (0 call); FD_ISSET (0 call); FD_SET (0 call); FD_ZERO (0 call); Frama_C_abort (1 call); Frama_C_char_interval (0 call); @@ -74,29 +74,29 @@ clearerr (0 call); clearerr_unlocked (0 call); clock (0 call); clock_gettime (0 call); clock_nanosleep (0 call); close (0 call); closedir (0 call); closelog (0 call); connect (0 call); cos (0 call); - cosf (0 call); cosl (0 call); creat (0 call); difftime (0 call); - div (0 call); dup (0 call); dup2 (0 call); execl (0 call); execle (0 call); - execlp (0 call); execv (0 call); execve (0 call); execvp (0 call); - exit (0 call); exp (0 call); expf (0 call); fabsl (0 call); fclose (0 call); - fcntl (0 call); fdopen (0 call); feof (2 calls); feof_unlocked (0 call); - ferror (2 calls); ferror_unlocked (0 call); fflush (0 call); fgetc (1 call); - fgetpos (0 call); fgets (0 call); fgetws (0 call); fileno (0 call); - fileno_unlocked (0 call); flock (0 call); flockfile (0 call); - floor (0 call); floorf (0 call); floorl (0 call); fmod (0 call); - fmodf (0 call); fopen (0 call); fork (0 call); fputc (0 call); - fputs (0 call); fread (0 call); free (1 call); freeaddrinfo (0 call); - freopen (0 call); fseek (0 call); fsetpos (0 call); ftell (0 call); - ftrylockfile (0 call); funlockfile (0 call); fwrite (0 call); - gai_strerror (0 call); getc (0 call); getc_unlocked (0 call); - getchar (0 call); getchar_unlocked (0 call); getcwd (0 call); - getegid (0 call); geteuid (0 call); getgid (0 call); gethostname (0 call); - getitimer (0 call); getopt (0 call); getopt_long (0 call); - getopt_long_only (0 call); getpid (0 call); getppid (0 call); - getpriority (0 call); getpwuid (0 call); getresgid (0 call); - getresuid (0 call); getrlimit (0 call); getrusage (0 call); gets (0 call); - getsid (0 call); getsockopt (0 call); gettimeofday (0 call); - getuid (0 call); gmtime (0 call); htonl (0 call); htons (0 call); - iconv (0 call); iconv_close (0 call); iconv_open (0 call); + cosf (0 call); cosl (0 call); creat (0 call); ctime (0 call); + difftime (0 call); div (0 call); dup (0 call); dup2 (0 call); + execl (0 call); execle (0 call); execlp (0 call); execv (0 call); + execve (0 call); execvp (0 call); exit (0 call); exp (0 call); + expf (0 call); fabsl (0 call); fclose (0 call); fcntl (0 call); + fdopen (0 call); feof (2 calls); feof_unlocked (0 call); ferror (2 calls); + ferror_unlocked (0 call); fflush (0 call); fgetc (1 call); fgetpos (0 call); + fgets (0 call); fgetws (0 call); fileno (0 call); fileno_unlocked (0 call); + flock (0 call); flockfile (0 call); floor (0 call); floorf (0 call); + floorl (0 call); fmod (0 call); fmodf (0 call); fopen (0 call); + fork (0 call); fputc (0 call); fputs (0 call); fread (0 call); + free (1 call); freeaddrinfo (0 call); freopen (0 call); fseek (0 call); + fsetpos (0 call); ftell (0 call); ftrylockfile (0 call); + funlockfile (0 call); fwrite (0 call); gai_strerror (0 call); getc (0 call); + getc_unlocked (0 call); getchar (0 call); getchar_unlocked (0 call); + getcwd (0 call); getegid (0 call); geteuid (0 call); getgid (0 call); + gethostname (0 call); getitimer (0 call); getopt (0 call); + getopt_long (0 call); getopt_long_only (0 call); getpid (0 call); + getppid (0 call); getpriority (0 call); getpwuid (0 call); + getresgid (0 call); getresuid (0 call); getrlimit (0 call); + getrusage (0 call); gets (0 call); getsid (0 call); getsockopt (0 call); + gettimeofday (0 call); getuid (0 call); gmtime (0 call); htonl (0 call); + htons (0 call); iconv (0 call); iconv_close (0 call); iconv_open (0 call); inet_addr (0 call); inet_ntoa (0 call); inet_ntop (0 call); inet_pton (0 call); isascii (0 call); kill (0 call); labs (0 call); ldiv (0 call); listen (0 call); llabs (0 call); lldiv (0 call); @@ -163,13 +163,13 @@ ============== Sloc = 948 Decision point = 183 - Global variables = 52 + Global variables = 54 If = 174 Loop = 40 Goto = 78 Assignment = 379 Exit point = 73 - Function = 430 + Function = 431 Function call = 73 Pointer dereferencing = 146 Cyclomatic complexity = 256 diff --git a/tests/libc/oracle/fc_libc.1.res.oracle b/tests/libc/oracle/fc_libc.1.res.oracle index 7df313ff573d895684146f84abed98e0fc6a2906..067e748dee0d9bac5c07fd617c82abee7f0a29b4 100644 --- a/tests/libc/oracle/fc_libc.1.res.oracle +++ b/tests/libc/oracle/fc_libc.1.res.oracle @@ -5137,6 +5137,20 @@ extern time_t mktime(struct tm *timeptr); */ extern time_t time(time_t *timer); +char __fc_ctime[26]; +char * const __fc_p_ctime = (char *)(& __fc_ctime); +/*@ requires valid_timer: \valid_read(timer); + requires initialization: init_timer: \initialized(timer); + ensures result_points_to_ctime: \result ≡ __fc_p_ctime; + ensures result_valid_string: valid_read_string(__fc_p_ctime); + assigns __fc_ctime[0 .. 25], \result; + assigns __fc_ctime[0 .. 25] + \from (indirect: *timer), (indirect: __fc_time); + assigns \result + \from (indirect: *timer), (indirect: __fc_time), __fc_p_ctime; + */ +extern char *ctime(time_t const *timer); + struct tm __fc_time_tm; struct tm * const __fc_p_time_tm = & __fc_time_tm; /*@ ensures diff --git a/tests/libc/oracle/time_c.res.oracle b/tests/libc/oracle/time_c.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..2b6021a7f03a5dd174de37138c6d674ede2e1b88 --- /dev/null +++ b/tests/libc/oracle/time_c.res.oracle @@ -0,0 +1,34 @@ +[kernel] Parsing tests/libc/time_c.c (with preprocessing) +[eva] Analyzing a complete application starting at main +[eva] Computing initial state +[eva] Initial state computed +[eva:initial-state] Values of globals at initialization + v ∈ [--..--] +[eva] computing for function ctime <- main. + Called from tests/libc/time_c.c:8. +[eva] share/libc/time.c:30: assertion got status valid. +[eva:alarm] share/libc/time.c:31: Warning: assertion got status unknown. +[eva] computing for function Frama_C_make_unknown <- ctime <- main. + Called from share/libc/time.c:32. +[eva] using specification for function Frama_C_make_unknown +[eva] share/libc/time.c:32: + function Frama_C_make_unknown: precondition 'valid_p' got status valid. +[eva] Done for function Frama_C_make_unknown +[eva] Recording results for ctime +[eva] Done for function ctime +[eva] tests/libc/time_c.c:9: assertion got status valid. +[eva] Recording results for main +[eva] done for function main +[eva] ====== VALUES COMPUTED ====== +[eva:final-states] Values at end of function ctime: + __fc_ctime[0..24] ∈ [--..--] + [25] ∈ {0} + Frama_C_entropy_source ∈ [--..--] + __retres ∈ {{ &__fc_ctime[0] }} +[eva:final-states] Values at end of function main: + __fc_ctime[0..24] ∈ [--..--] + [25] ∈ {0} + Frama_C_entropy_source ∈ [--..--] + t ∈ {42} + s ∈ {{ &__fc_ctime[0] }} + __retres ∈ {0} diff --git a/tests/libc/oracle/time_h.res.oracle b/tests/libc/oracle/time_h.res.oracle index dd05409c1abbb38d6e69d462c654f258af058285..5fcd6c6d027bc01e634adfc623934e6e724e7607 100644 --- a/tests/libc/oracle/time_h.res.oracle +++ b/tests/libc/oracle/time_h.res.oracle @@ -102,14 +102,29 @@ [eva] computing for function clock_nanosleep <- main. Called from tests/libc/time_h.c:36. [eva] Done for function clock_nanosleep +[eva] computing for function ctime <- main. + Called from tests/libc/time_h.c:43. +[eva] using specification for function ctime +[eva] tests/libc/time_h.c:43: + function ctime: precondition 'valid_timer' got status valid. +[eva] tests/libc/time_h.c:43: + function ctime: precondition 'initialization,init_timer' got status valid. +[eva] Done for function ctime +[eva] computing for function ctime <- main. + Called from tests/libc/time_h.c:43. +[eva] Done for function ctime +[eva:alarm] tests/libc/time_h.c:44: Warning: assertion got status unknown. [eva] Recording results for main [eva] done for function main [eva] ====== VALUES COMPUTED ====== [eva:final-states] Values at end of function main: + __fc_ctime[0..25] ∈ [--..--] req.tv_sec ∈ [--..--] .tv_nsec ∈ [0..999999999] rem ∈ [--..--] or UNINITIALIZED r ∈ {-1; 0; 4; 22} creq.tv_sec ∈ [--..--] or UNINITIALIZED .tv_nsec ∈ [0..999999999] or UNINITIALIZED + tt ∈ {42} + time_str ∈ {{ &__fc_ctime[0] }} __retres ∈ {0; 1; 2} diff --git a/tests/libc/oracle/time_misc.res.oracle b/tests/libc/oracle/time_misc.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..11b3437a14bb4490511094ca437543e11a7ed99e --- /dev/null +++ b/tests/libc/oracle/time_misc.res.oracle @@ -0,0 +1,71 @@ +[kernel] Parsing tests/libc/time_misc.c (with preprocessing) +[eva] Analyzing a complete application starting at main +[eva] Computing initial state +[eva] Initial state computed +[eva:initial-state] Values of globals at initialization + v ∈ [--..--] +[eva] computing for function test_gettimeofday <- main. + Called from tests/libc/time_misc.c:37. +[eva] computing for function gettimeofday <- test_gettimeofday <- main. + Called from tests/libc/time_misc.c:7. +[eva] using specification for function gettimeofday +[eva] Done for function gettimeofday +[eva] tests/libc/time_misc.c:8: assertion got status valid. +[eva] tests/libc/time_misc.c:9: assertion got status valid. +[eva] Recording results for test_gettimeofday +[eva] Done for function test_gettimeofday +[eva] computing for function test_strftime <- main. + Called from tests/libc/time_misc.c:38. +[eva] computing for function time <- test_strftime <- main. + Called from tests/libc/time_misc.c:18. +[eva] using specification for function time +[eva] Done for function time +[eva] computing for function localtime <- test_strftime <- main. + Called from tests/libc/time_misc.c:19. +[eva] using specification for function localtime +[eva] Done for function localtime +[eva] computing for function strftime <- test_strftime <- main. + Called from tests/libc/time_misc.c:21. +[eva] using specification for function strftime +[eva] tests/libc/time_misc.c:21: + function strftime: precondition 'dst_has_room' got status valid. +[eva] tests/libc/time_misc.c:21: + function strftime: precondition 'valid_format' got status valid. +[eva] tests/libc/time_misc.c:21: + function strftime: precondition 'valid_tm' got status valid. +[eva] Done for function strftime +[eva] Recording results for test_strftime +[eva] Done for function test_strftime +[eva] computing for function test_ctime <- main. + Called from tests/libc/time_misc.c:39. +[eva] computing for function ctime <- test_ctime <- main. + Called from tests/libc/time_misc.c:31. +[eva] using specification for function ctime +[eva] tests/libc/time_misc.c:31: + function ctime: precondition 'valid_timer' got status valid. +[eva:alarm] tests/libc/time_misc.c:31: Warning: + function ctime: precondition 'initialization,init_timer' got status unknown. +[eva] Done for function ctime +[eva:alarm] tests/libc/time_misc.c:32: Warning: assertion got status unknown. +[eva] Recording results for test_ctime +[eva] Done for function test_ctime +[eva] Recording results for main +[eva] done for function main +[eva] ====== VALUES COMPUTED ====== +[eva:final-states] Values at end of function test_ctime: + __fc_ctime[0..25] ∈ [--..--] + t ∈ {42} + s ∈ {{ &__fc_ctime[0] }} +[eva:final-states] Values at end of function test_gettimeofday: + tv.tv_sec ∈ [--..--] + .tv_usec ∈ [0..999999] +[eva:final-states] Values at end of function test_strftime: + __fc_time_tm ∈ [--..--] + outstr[0..199] ∈ [--..--] or UNINITIALIZED + t ∈ [--..--] + tmp ∈ {{ NULL ; &__fc_time_tm }} + res ∈ [0..200] or UNINITIALIZED +[eva:final-states] Values at end of function main: + __fc_ctime[0..25] ∈ [--..--] + __fc_time_tm ∈ [--..--] + __retres ∈ {0} diff --git a/tests/libc/time_c.c b/tests/libc/time_c.c new file mode 100644 index 0000000000000000000000000000000000000000..c833527b0c07b22bd568457b94bd7dcfd628de3a --- /dev/null +++ b/tests/libc/time_c.c @@ -0,0 +1,12 @@ +#include "time.c" + +volatile int v; + +int main() { + time_t t; + if (v) t = 42; + char *s = ctime(&t); // warn about initialization + //@ assert valid_read_string(s); + + return 0; +} diff --git a/tests/libc/time_h.c b/tests/libc/time_h.c index a265f44be03db228fa54b67a63d79090dc19650a..0ce0180a8c7a2892d0da7f2dafafa7c3fd04bc8b 100644 --- a/tests/libc/time_h.c +++ b/tests/libc/time_h.c @@ -38,5 +38,9 @@ int main() { return 1; } } + + time_t tt = 42; + char *time_str = ctime(&tt); + //@ assert valid_string(time_str); return 0; } diff --git a/tests/libc/time.c b/tests/libc/time_misc.c similarity index 78% rename from tests/libc/time.c rename to tests/libc/time_misc.c index 5cec32d3ff1ffa35b917686439a78c60f5a807df..8123a1641dc5e5ff829cde5f958e3b14d5f24656 100644 --- a/tests/libc/time.c +++ b/tests/libc/time_misc.c @@ -22,10 +22,21 @@ void test_strftime(void) } } +volatile int v; + +void test_ctime(void) +{ + time_t t; + if (v) t = 42; + char *s = ctime(&t); // warn about initialization + //@ assert valid_read_string(s); +} + int main(int argc, char **argv) { test_gettimeofday(); test_strftime(); + test_ctime(); return 0; }