From 322bb488bb73c68e00a9377a1bf43af503f1bea1 Mon Sep 17 00:00:00 2001 From: Andre Maroneze <andre.maroneze@cea.fr> Date: Thu, 18 Nov 2021 10:36:26 +0100 Subject: [PATCH] [Libc] add test and update test oracles --- tests/libc/fc_libc.c | 2 +- tests/libc/oracle/fc_builtin_c.res.oracle | 60 ++-- tests/libc/oracle/fc_libc.0.res.oracle | 1 + tests/libc/oracle/fc_libc.1.res.oracle | 374 +++++++++++++++++----- tests/libc/oracle/pwd_c.res.oracle | 314 ++++++++++++++++++ tests/libc/oracle/pwd_h.res.oracle | 11 +- tests/libc/pwd_c.c | 38 +++ 7 files changed, 680 insertions(+), 120 deletions(-) create mode 100644 tests/libc/oracle/pwd_c.res.oracle create mode 100644 tests/libc/pwd_c.c diff --git a/tests/libc/fc_libc.c b/tests/libc/fc_libc.c index f69e8856f26..8df9bf49c33 100644 --- a/tests/libc/fc_libc.c +++ b/tests/libc/fc_libc.c @@ -12,7 +12,7 @@ MODULE: check_compliance OPT: -kernel-msg-key printer:attrs MODULE: - OPT: -load %{dep:@PTEST_NAME@.sav} -metrics -metrics-libc -then -lib-entry -metrics-no-libc | %{dep:./check_some_metrics.sh} "> 100" "> 400" "< 2" "> 20" "= 1" "= 1" "= 0" "= 0" "= 0" "= 1" + OPT: -load %{dep:@PTEST_NAME@.sav} -metrics -metrics-libc -then -lib-entry -metrics-no-libc | %{dep:./check_some_metrics.sh} "> 100" "> 400" "< 2" "> 0" "= 1" "= 1" "= 0" "= 0" "= 0" "= 1" CMD: %{dep:./check_full_libc.sh} @FRAMAC_SHARE@/libc OPT: **/ diff --git a/tests/libc/oracle/fc_builtin_c.res.oracle b/tests/libc/oracle/fc_builtin_c.res.oracle index ff75607cc47..d922ab4e1ef 100644 --- a/tests/libc/oracle/fc_builtin_c.res.oracle +++ b/tests/libc/oracle/fc_builtin_c.res.oracle @@ -1,77 +1,77 @@ -[kernel] Parsing tests/libc/fc_builtin_c.c (with preprocessing) +[kernel] Parsing fc_builtin_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 [eva] computing for function Frama_C_interval <- main. - Called from tests/libc/fc_builtin_c.c:8. + Called from fc_builtin_c.c:8. [eva] computing for function Frama_C_update_entropy <- Frama_C_interval <- main. - Called from share/libc/__fc_builtin.c:66. + Called from FRAMAC_SHARE/libc/__fc_builtin.c:66. [eva] Recording results for Frama_C_update_entropy [eva] Done for function Frama_C_update_entropy [eva] Recording results for Frama_C_interval [eva] Done for function Frama_C_interval -[eva] tests/libc/fc_builtin_c.c:9: assertion 'bounds' got status valid. -[eva:alarm] tests/libc/fc_builtin_c.c:10: Warning: +[eva] fc_builtin_c.c:9: assertion 'bounds' got status valid. +[eva:alarm] fc_builtin_c.c:10: Warning: assertion 'sampling,unknown' got status unknown. [eva] computing for function Frama_C_char_interval <- main. - Called from tests/libc/fc_builtin_c.c:12. + Called from fc_builtin_c.c:12. [eva] computing for function Frama_C_interval <- Frama_C_char_interval <- main. - Called from share/libc/__fc_builtin.c:77. -[eva] share/libc/__fc_builtin.c:66: + Called from FRAMAC_SHARE/libc/__fc_builtin.c:77. +[eva] FRAMAC_SHARE/libc/__fc_builtin.c:66: Reusing old results for call to Frama_C_update_entropy [eva] Recording results for Frama_C_interval [eva] Done for function Frama_C_interval [eva] Recording results for Frama_C_char_interval [eva] Done for function Frama_C_char_interval -[eva] tests/libc/fc_builtin_c.c:13: assertion 'bounds' got status valid. -[eva:alarm] tests/libc/fc_builtin_c.c:14: Warning: +[eva] fc_builtin_c.c:13: assertion 'bounds' got status valid. +[eva:alarm] fc_builtin_c.c:14: Warning: assertion 'sampling,unknown' got status unknown. [eva] computing for function Frama_C_unsigned_int_interval <- main. - Called from tests/libc/fc_builtin_c.c:16. -[eva] share/libc/__fc_builtin.c:100: + Called from fc_builtin_c.c:16. +[eva] FRAMAC_SHARE/libc/__fc_builtin.c:100: Reusing old results for call to Frama_C_update_entropy [eva] Recording results for Frama_C_unsigned_int_interval [eva] Done for function Frama_C_unsigned_int_interval -[eva] tests/libc/fc_builtin_c.c:17: assertion 'bounds' got status valid. -[eva:alarm] tests/libc/fc_builtin_c.c:18: Warning: +[eva] fc_builtin_c.c:17: assertion 'bounds' got status valid. +[eva:alarm] fc_builtin_c.c:18: Warning: assertion 'sampling,unknown' got status unknown. [eva] computing for function Frama_C_float_interval <- main. - Called from tests/libc/fc_builtin_c.c:20. -[eva] share/libc/__fc_builtin.c:82: + Called from fc_builtin_c.c:20. +[eva] FRAMAC_SHARE/libc/__fc_builtin.c:82: Reusing old results for call to Frama_C_update_entropy [eva] Recording results for Frama_C_float_interval [eva] Done for function Frama_C_float_interval -[eva] tests/libc/fc_builtin_c.c:21: assertion 'bounds' got status valid. -[eva:alarm] tests/libc/fc_builtin_c.c:22: Warning: +[eva] fc_builtin_c.c:21: assertion 'bounds' got status valid. +[eva:alarm] fc_builtin_c.c:22: Warning: assertion 'sampling,unknown' got status unknown. [eva] computing for function Frama_C_double_interval <- main. - Called from tests/libc/fc_builtin_c.c:25. -[eva] share/libc/__fc_builtin.c:88: + Called from fc_builtin_c.c:25. +[eva] FRAMAC_SHARE/libc/__fc_builtin.c:88: Reusing old results for call to Frama_C_update_entropy [eva] Recording results for Frama_C_double_interval [eva] Done for function Frama_C_double_interval -[eva] tests/libc/fc_builtin_c.c:26: assertion 'bounds' got status valid. -[eva:alarm] tests/libc/fc_builtin_c.c:27: Warning: +[eva] fc_builtin_c.c:26: assertion 'bounds' got status valid. +[eva:alarm] fc_builtin_c.c:27: Warning: assertion 'sampling,unknown' got status unknown. [eva] computing for function Frama_C_long_interval <- main. - Called from tests/libc/fc_builtin_c.c:29. -[eva] share/libc/__fc_builtin.c:112: + Called from fc_builtin_c.c:29. +[eva] FRAMAC_SHARE/libc/__fc_builtin.c:112: Reusing old results for call to Frama_C_update_entropy [eva] Recording results for Frama_C_long_interval [eva] Done for function Frama_C_long_interval -[eva] tests/libc/fc_builtin_c.c:30: assertion 'bounds' got status valid. -[eva:alarm] tests/libc/fc_builtin_c.c:31: Warning: +[eva] fc_builtin_c.c:30: assertion 'bounds' got status valid. +[eva:alarm] fc_builtin_c.c:31: Warning: assertion 'sampling,unknown' got status unknown. [eva] computing for function Frama_C_unsigned_long_interval <- main. - Called from tests/libc/fc_builtin_c.c:34. -[eva] share/libc/__fc_builtin.c:124: + Called from fc_builtin_c.c:34. +[eva] FRAMAC_SHARE/libc/__fc_builtin.c:124: Reusing old results for call to Frama_C_update_entropy [eva] Recording results for Frama_C_unsigned_long_interval [eva] Done for function Frama_C_unsigned_long_interval -[eva] tests/libc/fc_builtin_c.c:35: assertion 'bounds' got status valid. -[eva:alarm] tests/libc/fc_builtin_c.c:36: Warning: +[eva] fc_builtin_c.c:35: assertion 'bounds' got status valid. +[eva:alarm] fc_builtin_c.c:36: Warning: assertion 'sampling,unknown' got status unknown. [eva] Recording results for main [eva] done for function main diff --git a/tests/libc/oracle/fc_libc.0.res.oracle b/tests/libc/oracle/fc_libc.0.res.oracle index 1309a406e29..4cc020e5cf6 100644 --- a/tests/libc/oracle/fc_libc.0.res.oracle +++ b/tests/libc/oracle/fc_libc.0.res.oracle @@ -55,6 +55,7 @@ #include "netinet/in.h" #include "poll.h" #include "pthread.h" +#include "pwd.c" #include "pwd.h" #include "setjmp.h" #include "signal.c" diff --git a/tests/libc/oracle/fc_libc.1.res.oracle b/tests/libc/oracle/fc_libc.1.res.oracle index 703535ed601..a2690ea17ce 100644 --- a/tests/libc/oracle/fc_libc.1.res.oracle +++ b/tests/libc/oracle/fc_libc.1.res.oracle @@ -235,6 +235,15 @@ struct __fc_gethostbyname { char *host_aliases[2] ; char hostbuf[128] ; }; +struct passwd { + char *pw_name ; + char *pw_passwd ; + uid_t pw_uid ; + gid_t pw_gid ; + char *pw_gecos ; + char *pw_dir ; + char *pw_shell ; +}; typedef unsigned int ino_t; typedef long time_t; typedef unsigned int blkcnt_t; @@ -340,15 +349,6 @@ struct pollfd { short revents ; }; typedef unsigned long nfds_t; -struct passwd { - char *pw_name ; - char *pw_passwd ; - uid_t pw_uid ; - gid_t pw_gid ; - char *pw_gecos ; - char *pw_dir ; - char *pw_shell ; -}; typedef int jmp_buf[5]; struct __fc_sigjmp_buf { jmp_buf buf ; @@ -417,14 +417,8 @@ int Frama_C_interval(int min, int max); */ extern int Frama_C_interval_split(int min, int max); -/*@ requires order: min ≤ max; - ensures result_bounded: \old(min) ≤ \result ≤ \old(max); - assigns \result, Frama_C_entropy_source; - assigns \result \from min, max, Frama_C_entropy_source; - assigns Frama_C_entropy_source \from Frama_C_entropy_source; - */ -extern unsigned char Frama_C_unsigned_char_interval(unsigned char min, - unsigned char max); +unsigned char Frama_C_unsigned_char_interval(unsigned char min, + unsigned char max); char Frama_C_char_interval(char min, char max); @@ -445,14 +439,7 @@ extern unsigned short Frama_C_unsigned_short_interval(unsigned short min, */ extern short Frama_C_short_interval(short min, short max); -/*@ requires order: min ≤ max; - ensures result_bounded: \old(min) ≤ \result ≤ \old(max); - assigns \result, Frama_C_entropy_source; - assigns \result \from min, max, Frama_C_entropy_source; - assigns Frama_C_entropy_source \from Frama_C_entropy_source; - */ -extern unsigned int Frama_C_unsigned_int_interval(unsigned int min, - unsigned int max); +unsigned int Frama_C_unsigned_int_interval(unsigned int min, unsigned int max); /*@ requires order: min ≤ max; ensures result_bounded: \old(min) ≤ \result ≤ \old(max); @@ -462,22 +449,10 @@ extern unsigned int Frama_C_unsigned_int_interval(unsigned int min, */ extern int Frama_C_int_interval(int min, int max); -/*@ requires order: min ≤ max; - ensures result_bounded: \old(min) ≤ \result ≤ \old(max); - assigns \result, Frama_C_entropy_source; - assigns \result \from min, max, Frama_C_entropy_source; - assigns Frama_C_entropy_source \from Frama_C_entropy_source; - */ -extern unsigned long Frama_C_unsigned_long_interval(unsigned long min, - unsigned long max); +unsigned long Frama_C_unsigned_long_interval(unsigned long min, + unsigned long max); -/*@ requires order: min ≤ max; - ensures result_bounded: \old(min) ≤ \result ≤ \old(max); - assigns \result, Frama_C_entropy_source; - assigns \result \from min, max, Frama_C_entropy_source; - assigns Frama_C_entropy_source \from Frama_C_entropy_source; - */ -extern long Frama_C_long_interval(long min, long max); +long Frama_C_long_interval(long min, long max); /*@ requires order: min ≤ max; ensures result_bounded: \old(min) ≤ \result ≤ \old(max); @@ -537,6 +512,9 @@ extern long long Frama_C_abstract_max(long long i); assigns \result \from i; */ extern long long Frama_C_abstract_min(long long i); +unsigned int volatile __fc_unsigned_int_entropy; +long volatile __fc_long_entropy; +unsigned long volatile __fc_unsigned_long_entropy; /*@ assigns Frama_C_entropy_source; assigns Frama_C_entropy_source \from Frama_C_entropy_source; */ @@ -618,14 +596,9 @@ int Frama_C_interval(int min, int max) char Frama_C_char_interval(char min, char max) { char __retres; - int r; - char aux; - Frama_C_update_entropy(); - aux = (char)Frama_C_entropy_source; - if ((int)aux >= (int)min) - if ((int)aux <= (int)max) r = (int)aux; else r = (int)min; - else r = (int)min; - __retres = (char)r; + int tmp; + tmp = Frama_C_interval((int)min,(int)max); + __retres = (char)tmp; return __retres; } @@ -663,6 +636,77 @@ double Frama_C_double_interval(double min, double max) return tmp; } +/*@ requires order: min ≤ max; + ensures result_bounded: \old(min) ≤ \result ≤ \old(max); + assigns \result, Frama_C_entropy_source; + assigns \result \from min, max, Frama_C_entropy_source; + assigns Frama_C_entropy_source \from Frama_C_entropy_source; + */ +unsigned char Frama_C_unsigned_char_interval(unsigned char min, + unsigned char max) +{ + unsigned char __retres; + int tmp; + tmp = Frama_C_interval((int)min,(int)max); + __retres = (unsigned char)tmp; + return __retres; +} + +/*@ requires order: min ≤ max; + ensures result_bounded: \old(min) ≤ \result ≤ \old(max); + assigns \result, Frama_C_entropy_source; + assigns \result \from min, max, Frama_C_entropy_source; + assigns Frama_C_entropy_source \from Frama_C_entropy_source; + */ +unsigned int Frama_C_unsigned_int_interval(unsigned int min, unsigned int max) +{ + unsigned int r; + unsigned int aux; + Frama_C_update_entropy(); + aux = __fc_unsigned_int_entropy; + if (aux >= min) + if (aux <= max) r = aux; else r = min; + else r = min; + return r; +} + +/*@ requires order: min ≤ max; + ensures result_bounded: \old(min) ≤ \result ≤ \old(max); + assigns \result, Frama_C_entropy_source; + assigns \result \from min, max, Frama_C_entropy_source; + assigns Frama_C_entropy_source \from Frama_C_entropy_source; + */ +long Frama_C_long_interval(long min, long max) +{ + long r; + long aux; + Frama_C_update_entropy(); + aux = __fc_long_entropy; + if (aux >= min) + if (aux <= max) r = aux; else r = min; + else r = min; + return r; +} + +/*@ requires order: min ≤ max; + ensures result_bounded: \old(min) ≤ \result ≤ \old(max); + assigns \result, Frama_C_entropy_source; + assigns \result \from min, max, Frama_C_entropy_source; + assigns Frama_C_entropy_source \from Frama_C_entropy_source; + */ +unsigned long Frama_C_unsigned_long_interval(unsigned long min, + unsigned long max) +{ + unsigned long r; + unsigned long aux; + Frama_C_update_entropy(); + aux = __fc_unsigned_long_entropy; + if (aux >= min) + if (aux <= max) r = aux; else r = min; + else r = min; + return r; +} + extern __attribute__((__noreturn__)) void __builtin_abort(void); /*@ terminates \false; @@ -5218,6 +5262,204 @@ struct in6_addr const in6addr_loopback = (unsigned char)0, (unsigned char)0, (unsigned char)1}}; +char __fc_getpw_pw_name[64]; +char __fc_getpw_pw_passwd[64]; +char __fc_getpw_pw_gecos[64]; +char __fc_getpw_pw_dir[64]; +char __fc_getpw_pw_shell[64]; +struct passwd __fc_pwd = + {.pw_name = __fc_getpw_pw_name, + .pw_passwd = __fc_getpw_pw_passwd, + .pw_uid = 0U, + .pw_gid = 0U, + .pw_gecos = __fc_getpw_pw_gecos, + .pw_dir = __fc_getpw_pw_dir, + .pw_shell = __fc_getpw_pw_shell}; +struct passwd *__fc_p_pwd = & __fc_pwd; +/*@ requires valid_name: valid_read_string(name); + ensures + result_null_or_internal_struct: + \result ≡ \null ∨ \result ≡ __fc_p_pwd; + assigns \result, __fc_pwd; + assigns \result \from __fc_p_pwd, (indirect: *(name + (0 ..))); + assigns __fc_pwd \from (indirect: *(name + (0 ..))); + */ +extern struct passwd *getpwnam(char const *name); + +/*@ ensures + result_null_or_internal_struct: + \result ≡ \null ∨ \result ≡ __fc_p_pwd; + assigns \result, __fc_pwd; + assigns \result \from __fc_p_pwd, (indirect: uid); + assigns __fc_pwd \from (indirect: uid); + */ +extern struct passwd *getpwuid(uid_t uid); + +int getpwnam_r(char const *name, struct passwd *pwd, char *buf, + size_t buflen, struct passwd **result); + +int getpwuid_r(uid_t uid, struct passwd *pwd, char *buf, size_t buflen, + struct passwd **result); + +static int __fc_getpw_init; +static int __fc_getpw_r(struct passwd *pwd, char *buf, size_t buflen, + struct passwd **result) +{ + int __retres; + int tmp_2; + if (! __fc_getpw_init) { + __fc_getpw_init = 1; + Frama_C_make_unknown(__fc_getpw_pw_name,(unsigned int)63); + __fc_getpw_pw_name[63] = (char)0; + Frama_C_make_unknown(__fc_getpw_pw_passwd,(unsigned int)63); + __fc_getpw_pw_passwd[63] = (char)0; + Frama_C_make_unknown(__fc_getpw_pw_gecos,(unsigned int)63); + __fc_getpw_pw_gecos[63] = (char)0; + Frama_C_make_unknown(__fc_getpw_pw_dir,(unsigned int)63); + __fc_getpw_pw_dir[63] = (char)0; + Frama_C_make_unknown(__fc_getpw_pw_shell,(unsigned int)63); + __fc_getpw_pw_shell[63] = (char)0; + } + tmp_2 = Frama_C_interval(0,1); + if (tmp_2) { + int tmp; + int tmp_0; + int tmp_1; + *result = (struct passwd *)0; + tmp = Frama_C_interval(0,1); + if (tmp) { + __retres = 5; + goto return_label; + } + tmp_0 = Frama_C_interval(0,1); + if (tmp_0) { + __retres = 24; + goto return_label; + } + tmp_1 = Frama_C_interval(0,1); + if (tmp_1) { + __retres = 23; + goto return_label; + } + __retres = 0; + goto return_label; + } + else { + size_t len; + size_t remaining = buflen; + len = strlen((char const *)__fc_pwd.pw_name); + if (remaining <= len) { + *result = (struct passwd *)0; + __retres = 34; + goto return_label; + } + strcpy(buf,(char const *)__fc_pwd.pw_name); + *(buf + len) = (char)0; + pwd->pw_name = buf; + buf += len + (size_t)1; + remaining -= len; + len = strlen((char const *)__fc_pwd.pw_passwd); + if (remaining <= len) { + *result = (struct passwd *)0; + __retres = 34; + goto return_label; + } + strcpy(buf,(char const *)__fc_pwd.pw_passwd); + *(buf + len) = (char)0; + pwd->pw_passwd = buf; + buf += len + (size_t)1; + remaining -= len; + len = strlen((char const *)__fc_pwd.pw_gecos); + if (remaining <= len) { + *result = (struct passwd *)0; + __retres = 34; + goto return_label; + } + strcpy(buf,(char const *)__fc_pwd.pw_gecos); + *(buf + len) = (char)0; + pwd->pw_gecos = buf; + buf += len + (size_t)1; + remaining -= len; + len = strlen((char const *)__fc_pwd.pw_dir); + if (remaining <= len) { + *result = (struct passwd *)0; + __retres = 34; + goto return_label; + } + strcpy(buf,(char const *)__fc_pwd.pw_dir); + *(buf + len) = (char)0; + pwd->pw_dir = buf; + buf += len + (size_t)1; + remaining -= len; + len = strlen((char const *)__fc_pwd.pw_shell); + if (remaining <= len) { + *result = (struct passwd *)0; + __retres = 34; + goto return_label; + } + strcpy(buf,(char const *)__fc_pwd.pw_shell); + *(buf + len) = (char)0; + pwd->pw_shell = buf; + buf += len + (size_t)1; + remaining -= len; + pwd->pw_uid = Frama_C_unsigned_int_interval((unsigned int)0,4294967295U); + pwd->pw_gid = Frama_C_unsigned_int_interval((unsigned int)0,4294967295U); + *result = pwd; + __retres = 0; + goto return_label; + } + return_label: return __retres; +} + +/*@ requires valid_name: valid_read_string(name); + requires valid_buf: \valid(buf + (0 .. buflen - 1)); + requires valid_pwd: \valid(pwd); + requires valid_result: \valid(result); + ensures + result_null_or_assigned: + *\old(result) ≡ \null ∨ *\old(result) ≡ \old(pwd); + ensures + result_ok_or_error: \result ≡ 0 ∨ \result ∈ {5, 24, 23, 34}; + assigns \result, __fc_pwd, *pwd, *result, *(buf + (0 .. buflen - 1)); + assigns \result + \from (indirect: __fc_p_pwd), (indirect: *(name + (0 ..))); + assigns __fc_pwd \from (indirect: *(name + (0 ..))); + assigns *pwd \from __fc_p_pwd; + assigns *result \from __fc_p_pwd; + assigns *(buf + (0 .. buflen - 1)) \from (indirect: *__fc_p_pwd); + */ +int getpwnam_r(char const *name, struct passwd *pwd, char *buf, + size_t buflen, struct passwd **result) +{ + int tmp; + /*@ assert valid_read_string(name); */ ; + tmp = __fc_getpw_r(pwd,buf,buflen,result); + return tmp; +} + +/*@ requires valid_buf: \valid(buf + (0 .. buflen - 1)); + requires valid_pwd: \valid(pwd); + requires valid_result: \valid(result); + ensures + result_null_or_assigned: + *\old(result) ≡ \null ∨ *\old(result) ≡ \old(pwd); + ensures + result_ok_or_error: \result ≡ 0 ∨ \result ∈ {5, 24, 23, 34}; + assigns \result, __fc_pwd, *pwd, *result, *(buf + (0 .. buflen - 1)); + assigns \result \from (indirect: __fc_p_pwd); + assigns __fc_pwd \from (indirect: uid); + assigns *pwd \from __fc_p_pwd; + assigns *result \from __fc_p_pwd; + assigns *(buf + (0 .. buflen - 1)) \from (indirect: *__fc_p_pwd); + */ +int getpwuid_r(uid_t uid, struct passwd *pwd, char *buf, size_t buflen, + struct passwd **result) +{ + int tmp; + tmp = __fc_getpw_r(pwd,buf,buflen,result); + return tmp; +} + /*@ ghost unsigned int volatile __fc_time; */ /*@ assigns \result; assigns \result \from __fc_time; */ @@ -9310,42 +9552,6 @@ int pthread_setname_np(pthread_t thread, char const *name); */ int pthread_getname_np(pthread_t thread, char *name, size_t len); -extern char __fc_getpwuid_pw_name[64]; - -extern char __fc_getpwuid_pw_passwd[64]; - -extern char __fc_getpwuid_pw_dir[64]; - -extern char __fc_getpwuid_pw_shell[64]; - -struct passwd __fc_pwd = - {.pw_name = __fc_getpwuid_pw_name, - .pw_passwd = __fc_getpwuid_pw_passwd, - .pw_uid = 0U, - .pw_gid = 0U, - .pw_gecos = (char *)0, - .pw_dir = __fc_getpwuid_pw_dir, - .pw_shell = __fc_getpwuid_pw_shell}; -struct passwd *__fc_p_pwd = & __fc_pwd; -/*@ requires valid_name: valid_read_string(name); - ensures - result_null_or_internal_struct: - \result ≡ \null ∨ \result ≡ __fc_p_pwd; - assigns \result, __fc_pwd; - assigns \result \from __fc_p_pwd, (indirect: *(name + (0 ..))); - assigns __fc_pwd \from (indirect: *(name + (0 ..))); - */ -extern struct passwd *getpwnam(char const *name); - -/*@ ensures - result_null_or_internal_struct: - \result ≡ \null ∨ \result ≡ __fc_p_pwd; - assigns \result, __fc_pwd; - assigns \result \from __fc_p_pwd, (indirect: uid); - assigns __fc_pwd \from (indirect: uid); - */ -extern struct passwd *getpwuid(uid_t uid); - /*@ assigns *(env + (0 .. 4)); */ extern int setjmp(int env[5]); diff --git a/tests/libc/oracle/pwd_c.res.oracle b/tests/libc/oracle/pwd_c.res.oracle new file mode 100644 index 00000000000..d2523bf304f --- /dev/null +++ b/tests/libc/oracle/pwd_c.res.oracle @@ -0,0 +1,314 @@ +[kernel] Parsing pwd_c.c (with preprocessing) +[eva] Option -eva-precision 1 detected, automatic configuration of the analysis: + option -eva-min-loop-unroll set to 0 (default value). + option -eva-auto-loop-unroll set to 16. + option -eva-widening-delay set to 1. + option -eva-partition-history set to 0 (default value). + option -eva-slevel set to 10. + option -eva-ilevel set to 12. + option -eva-plevel set to 20. + option -eva-subdivide-non-linear set to 20. + option -eva-remove-redundant-alarms set to true (default value). + option -eva-domains set to 'cvalue,symbolic-locations'. + option -eva-split-return already set to 'full' (not modified). + option -eva-equality-through-calls set to 'none'. + option -eva-octagon-through-calls set to false (default value). +[eva] Splitting return states on: + \full_split(@all) +[eva] Analyzing a complete application starting at main +[eva] Computing initial state +[eva] Initial state computed +[eva:initial-state] Values of globals at initialization + uid ∈ [--..--] +[eva] computing for function getpwuid_r <- main. + Called from pwd_c.c:14. +[eva] computing for function __fc_getpw_r <- getpwuid_r <- main. + Called from FRAMAC_SHARE/libc/pwd.c:102. +[eva] computing for function Frama_C_make_unknown <- __fc_getpw_r <- getpwuid_r <- + main. + Called from FRAMAC_SHARE/libc/pwd.c:56. +[eva] using specification for function Frama_C_make_unknown +[eva] FRAMAC_SHARE/libc/pwd.c:56: + function Frama_C_make_unknown: precondition 'valid_p' got status valid. +[eva] Done for function Frama_C_make_unknown +[eva] computing for function Frama_C_make_unknown <- __fc_getpw_r <- getpwuid_r <- + main. + Called from FRAMAC_SHARE/libc/pwd.c:58. +[eva] FRAMAC_SHARE/libc/pwd.c:58: + function Frama_C_make_unknown: precondition 'valid_p' got status valid. +[eva] Done for function Frama_C_make_unknown +[eva] computing for function Frama_C_make_unknown <- __fc_getpw_r <- getpwuid_r <- + main. + Called from FRAMAC_SHARE/libc/pwd.c:60. +[eva] FRAMAC_SHARE/libc/pwd.c:60: + function Frama_C_make_unknown: precondition 'valid_p' got status valid. +[eva] Done for function Frama_C_make_unknown +[eva] computing for function Frama_C_make_unknown <- __fc_getpw_r <- getpwuid_r <- + main. + Called from FRAMAC_SHARE/libc/pwd.c:62. +[eva] FRAMAC_SHARE/libc/pwd.c:62: + function Frama_C_make_unknown: precondition 'valid_p' got status valid. +[eva] Done for function Frama_C_make_unknown +[eva] computing for function Frama_C_make_unknown <- __fc_getpw_r <- getpwuid_r <- + main. + Called from FRAMAC_SHARE/libc/pwd.c:64. +[eva] FRAMAC_SHARE/libc/pwd.c:64: + function Frama_C_make_unknown: precondition 'valid_p' got status valid. +[eva] Done for function Frama_C_make_unknown +[eva] computing for function Frama_C_interval <- __fc_getpw_r <- getpwuid_r <- main. + Called from FRAMAC_SHARE/libc/pwd.c:69. +[eva] using specification for function Frama_C_interval +[eva] FRAMAC_SHARE/libc/pwd.c:69: + function Frama_C_interval: precondition 'order' got status valid. +[eva] Done for function Frama_C_interval +[eva] computing for function Frama_C_interval <- __fc_getpw_r <- getpwuid_r <- main. + Called from FRAMAC_SHARE/libc/pwd.c:72. +[eva] FRAMAC_SHARE/libc/pwd.c:72: + function Frama_C_interval: precondition 'order' got status valid. +[eva] Done for function Frama_C_interval +[eva] computing for function Frama_C_interval <- __fc_getpw_r <- getpwuid_r <- main. + Called from FRAMAC_SHARE/libc/pwd.c:73. +[eva] FRAMAC_SHARE/libc/pwd.c:73: + function Frama_C_interval: precondition 'order' got status valid. +[eva] Done for function Frama_C_interval +[eva] computing for function Frama_C_interval <- __fc_getpw_r <- getpwuid_r <- main. + Called from FRAMAC_SHARE/libc/pwd.c:74. +[eva] FRAMAC_SHARE/libc/pwd.c:74: + function Frama_C_interval: precondition 'order' got status valid. +[eva] Done for function Frama_C_interval +[eva] FRAMAC_SHARE/libc/pwd.c:82: Call to builtin strlen +[eva] FRAMAC_SHARE/libc/pwd.c:82: + function strlen: precondition 'valid_string_s' got status valid. +[eva] computing for function strcpy <- __fc_getpw_r <- getpwuid_r <- main. + Called from FRAMAC_SHARE/libc/pwd.c:82. +[eva] using specification for function strcpy +[eva] FRAMAC_SHARE/libc/pwd.c:82: + function strcpy: precondition 'valid_string_src' got status valid. +[eva] FRAMAC_SHARE/libc/pwd.c:82: + function strcpy: precondition 'room_string' got status valid. +[eva] FRAMAC_SHARE/libc/pwd.c:82: + function strcpy: precondition 'separation' got status valid. +[eva] FRAMAC_SHARE/libc/string.h:373: + cannot evaluate ACSL term, unsupported ACSL construct: logic function strcmp +[eva] Done for function strcpy +[eva] FRAMAC_SHARE/libc/pwd.c:83: Call to builtin strlen +[eva] FRAMAC_SHARE/libc/pwd.c:83: + function strlen: precondition 'valid_string_s' got status valid. +[eva] computing for function strcpy <- __fc_getpw_r <- getpwuid_r <- main. + Called from FRAMAC_SHARE/libc/pwd.c:83. +[eva] FRAMAC_SHARE/libc/pwd.c:83: + function strcpy: precondition 'valid_string_src' got status valid. +[eva] FRAMAC_SHARE/libc/pwd.c:83: + function strcpy: precondition 'room_string' got status valid. +[eva] FRAMAC_SHARE/libc/pwd.c:83: + function strcpy: precondition 'separation' got status valid. +[eva] Done for function strcpy +[eva] FRAMAC_SHARE/libc/pwd.c:84: Call to builtin strlen +[eva] FRAMAC_SHARE/libc/pwd.c:84: + function strlen: precondition 'valid_string_s' got status valid. +[eva] computing for function strcpy <- __fc_getpw_r <- getpwuid_r <- main. + Called from FRAMAC_SHARE/libc/pwd.c:84. +[eva] FRAMAC_SHARE/libc/pwd.c:84: + function strcpy: precondition 'valid_string_src' got status valid. +[eva] FRAMAC_SHARE/libc/pwd.c:84: + function strcpy: precondition 'room_string' got status valid. +[eva] FRAMAC_SHARE/libc/pwd.c:84: + function strcpy: precondition 'separation' got status valid. +[eva] Done for function strcpy +[eva] FRAMAC_SHARE/libc/pwd.c:85: Call to builtin strlen +[eva] FRAMAC_SHARE/libc/pwd.c:85: + function strlen: precondition 'valid_string_s' got status valid. +[eva] computing for function strcpy <- __fc_getpw_r <- getpwuid_r <- main. + Called from FRAMAC_SHARE/libc/pwd.c:85. +[eva] FRAMAC_SHARE/libc/pwd.c:85: + function strcpy: precondition 'valid_string_src' got status valid. +[eva] FRAMAC_SHARE/libc/pwd.c:85: + function strcpy: precondition 'room_string' got status valid. +[eva] FRAMAC_SHARE/libc/pwd.c:85: + function strcpy: precondition 'separation' got status valid. +[eva] Done for function strcpy +[eva] FRAMAC_SHARE/libc/pwd.c:86: Call to builtin strlen +[eva] FRAMAC_SHARE/libc/pwd.c:86: + function strlen: precondition 'valid_string_s' got status valid. +[eva] computing for function strcpy <- __fc_getpw_r <- getpwuid_r <- main. + Called from FRAMAC_SHARE/libc/pwd.c:86. +[eva] FRAMAC_SHARE/libc/pwd.c:86: + function strcpy: precondition 'valid_string_src' got status valid. +[eva] FRAMAC_SHARE/libc/pwd.c:86: + function strcpy: precondition 'room_string' got status valid. +[eva] FRAMAC_SHARE/libc/pwd.c:86: + function strcpy: precondition 'separation' got status valid. +[eva] Done for function strcpy +[eva] computing for function Frama_C_unsigned_int_interval <- __fc_getpw_r <- + getpwuid_r <- main. + Called from FRAMAC_SHARE/libc/pwd.c:87. +[eva] using specification for function Frama_C_unsigned_int_interval +[eva] FRAMAC_SHARE/libc/pwd.c:87: + function Frama_C_unsigned_int_interval: precondition 'order' got status valid. +[eva] Done for function Frama_C_unsigned_int_interval +[eva] computing for function Frama_C_unsigned_int_interval <- __fc_getpw_r <- + getpwuid_r <- main. + Called from FRAMAC_SHARE/libc/pwd.c:88. +[eva] FRAMAC_SHARE/libc/pwd.c:88: + function Frama_C_unsigned_int_interval: precondition 'order' got status valid. +[eva] Done for function Frama_C_unsigned_int_interval +[eva] Recording results for __fc_getpw_r +[eva] Done for function __fc_getpw_r +[eva] Recording results for getpwuid_r +[eva] Done for function getpwuid_r +[eva] pwd_c.c:16: assertion got status valid. +[eva] pwd_c.c:17: assertion got status valid. +[eva] pwd_c.c:18: assertion got status valid. +[eva:alarm] pwd_c.c:20: Warning: assertion got status unknown. +[eva:alarm] pwd_c.c:21: Warning: assertion got status unknown. +[eva:alarm] pwd_c.c:22: Warning: assertion got status unknown. +[eva:alarm] pwd_c.c:23: Warning: assertion got status unknown. +[eva] computing for function getpwnam_r <- main. + Called from pwd_c.c:27. +[eva] FRAMAC_SHARE/libc/pwd.c:96: assertion got status valid. +[eva] computing for function __fc_getpw_r <- getpwnam_r <- main. + Called from FRAMAC_SHARE/libc/pwd.c:97. +[eva] computing for function Frama_C_interval <- __fc_getpw_r <- getpwnam_r <- main. + Called from FRAMAC_SHARE/libc/pwd.c:69. +[eva] Done for function Frama_C_interval +[eva] computing for function Frama_C_interval <- __fc_getpw_r <- getpwnam_r <- main. + Called from FRAMAC_SHARE/libc/pwd.c:72. +[eva] Done for function Frama_C_interval +[eva] computing for function Frama_C_interval <- __fc_getpw_r <- getpwnam_r <- main. + Called from FRAMAC_SHARE/libc/pwd.c:73. +[eva] Done for function Frama_C_interval +[eva] computing for function Frama_C_interval <- __fc_getpw_r <- getpwnam_r <- main. + Called from FRAMAC_SHARE/libc/pwd.c:74. +[eva] Done for function Frama_C_interval +[eva] FRAMAC_SHARE/libc/pwd.c:82: Call to builtin strlen +[eva] computing for function strcpy <- __fc_getpw_r <- getpwnam_r <- main. + Called from FRAMAC_SHARE/libc/pwd.c:82. +[eva] Done for function strcpy +[eva] FRAMAC_SHARE/libc/pwd.c:83: Call to builtin strlen +[eva] computing for function strcpy <- __fc_getpw_r <- getpwnam_r <- main. + Called from FRAMAC_SHARE/libc/pwd.c:83. +[eva] Done for function strcpy +[eva] FRAMAC_SHARE/libc/pwd.c:84: Call to builtin strlen +[eva] computing for function strcpy <- __fc_getpw_r <- getpwnam_r <- main. + Called from FRAMAC_SHARE/libc/pwd.c:84. +[eva] Done for function strcpy +[eva] FRAMAC_SHARE/libc/pwd.c:85: Call to builtin strlen +[eva] computing for function strcpy <- __fc_getpw_r <- getpwnam_r <- main. + Called from FRAMAC_SHARE/libc/pwd.c:85. +[eva] Done for function strcpy +[eva] FRAMAC_SHARE/libc/pwd.c:86: Call to builtin strlen +[eva] computing for function strcpy <- __fc_getpw_r <- getpwnam_r <- main. + Called from FRAMAC_SHARE/libc/pwd.c:86. +[eva] Done for function strcpy +[eva] computing for function Frama_C_unsigned_int_interval <- __fc_getpw_r <- + getpwnam_r <- main. + Called from FRAMAC_SHARE/libc/pwd.c:87. +[eva] Done for function Frama_C_unsigned_int_interval +[eva] computing for function Frama_C_unsigned_int_interval <- __fc_getpw_r <- + getpwnam_r <- main. + Called from FRAMAC_SHARE/libc/pwd.c:88. +[eva] Done for function Frama_C_unsigned_int_interval +[eva] Recording results for __fc_getpw_r +[eva] Done for function __fc_getpw_r +[eva] Recording results for getpwnam_r +[eva] Done for function getpwnam_r +[eva] pwd_c.c:29: assertion got status valid. +[eva] pwd_c.c:30: assertion got status valid. +[eva] pwd_c.c:31: assertion got status valid. +[eva:alarm] pwd_c.c:33: Warning: assertion 'unknown_for_now' got status unknown. +[eva:alarm] pwd_c.c:34: Warning: assertion 'unknown_for_now' got status unknown. +[eva:alarm] pwd_c.c:35: Warning: assertion 'unknown_for_now' got status unknown. +[eva:alarm] pwd_c.c:36: Warning: assertion 'unknown_for_now' got status unknown. +[eva] Recording results for main +[eva] done for function main +[eva] ====== VALUES COMPUTED ====== +[eva:final-states] Values at end of function __fc_getpw_r: + Frama_C_entropy_source ∈ [--..--] + __fc_getpw_pw_name[0..62] ∈ [--..--] + [63] ∈ {0} + __fc_getpw_pw_passwd[0..62] ∈ [--..--] + [63] ∈ {0} + __fc_getpw_pw_gecos[0..62] ∈ [--..--] + [63] ∈ {0} + __fc_getpw_pw_dir[0..62] ∈ [--..--] + [63] ∈ {0} + __fc_getpw_pw_shell[0..62] ∈ [--..--] + [63] ∈ {0} + buf ∈ {{ &buf + [0..320] }} + pwd_out.pw_name ∈ {{ &buf[0] }} or UNINITIALIZED + .pw_passwd ∈ {{ &buf + [1..64] }} or UNINITIALIZED + {.pw_uid; .pw_gid} ∈ [--..--] or UNINITIALIZED + .pw_gecos ∈ {{ &buf + [2..128] }} or UNINITIALIZED + .pw_dir ∈ {{ &buf + [3..192] }} or UNINITIALIZED + .pw_shell ∈ {{ &buf + [4..256] }} or UNINITIALIZED + result ∈ {{ NULL ; &pwd_out ; &pwd_out2 }} + buf[0..319] ∈ [--..--] or UNINITIALIZED + pwd_out2.pw_name ∈ {{ &buf[0] }} or UNINITIALIZED + .pw_passwd ∈ {{ &buf + [1..64] }} or UNINITIALIZED + {.pw_uid; .pw_gid} ∈ [--..--] or UNINITIALIZED + .pw_gecos ∈ {{ &buf + [2..128] }} or UNINITIALIZED + .pw_dir ∈ {{ &buf + [3..192] }} or UNINITIALIZED + .pw_shell ∈ {{ &buf + [4..256] }} or UNINITIALIZED + __fc_getpw_init ∈ {1} + __retres ∈ {0; 5; 23; 24} +[eva:final-states] Values at end of function getpwnam_r: + Frama_C_entropy_source ∈ [--..--] + result ∈ {{ NULL ; &pwd_out2 }} + buf[0..319] ∈ [--..--] or UNINITIALIZED + pwd_out2.pw_name ∈ {{ &buf[0] }} or UNINITIALIZED + .pw_passwd ∈ {{ &buf + [1..64] }} or UNINITIALIZED + {.pw_uid; .pw_gid} ∈ [--..--] or UNINITIALIZED + .pw_gecos ∈ {{ &buf + [2..128] }} or UNINITIALIZED + .pw_dir ∈ {{ &buf + [3..192] }} or UNINITIALIZED + .pw_shell ∈ {{ &buf + [4..256] }} or UNINITIALIZED +[eva:final-states] Values at end of function getpwuid_r: + Frama_C_entropy_source ∈ [--..--] + __fc_getpw_pw_name[0..62] ∈ [--..--] + [63] ∈ {0} + __fc_getpw_pw_passwd[0..62] ∈ [--..--] + [63] ∈ {0} + __fc_getpw_pw_gecos[0..62] ∈ [--..--] + [63] ∈ {0} + __fc_getpw_pw_dir[0..62] ∈ [--..--] + [63] ∈ {0} + __fc_getpw_pw_shell[0..62] ∈ [--..--] + [63] ∈ {0} + pwd_out.pw_name ∈ {{ &buf[0] }} or UNINITIALIZED + .pw_passwd ∈ {{ &buf + [1..64] }} or UNINITIALIZED + {.pw_uid; .pw_gid} ∈ [--..--] or UNINITIALIZED + .pw_gecos ∈ {{ &buf + [2..128] }} or UNINITIALIZED + .pw_dir ∈ {{ &buf + [3..192] }} or UNINITIALIZED + .pw_shell ∈ {{ &buf + [4..256] }} or UNINITIALIZED + result ∈ {{ NULL ; &pwd_out }} + buf[0..319] ∈ [--..--] or UNINITIALIZED + __fc_getpw_init ∈ {1} +[eva:final-states] Values at end of function main: + Frama_C_entropy_source ∈ [--..--] + __fc_getpw_pw_name[0..62] ∈ [--..--] + [63] ∈ {0} + __fc_getpw_pw_passwd[0..62] ∈ [--..--] + [63] ∈ {0} + __fc_getpw_pw_gecos[0..62] ∈ [--..--] + [63] ∈ {0} + __fc_getpw_pw_dir[0..62] ∈ [--..--] + [63] ∈ {0} + __fc_getpw_pw_shell[0..62] ∈ [--..--] + [63] ∈ {0} + pwd_out.pw_name ∈ {{ &buf[0] }} or UNINITIALIZED + .pw_passwd ∈ {{ &buf + [1..64] }} or UNINITIALIZED + {.pw_uid; .pw_gid} ∈ [--..--] or UNINITIALIZED + .pw_gecos ∈ {{ &buf + [2..128] }} or UNINITIALIZED + .pw_dir ∈ {{ &buf + [3..192] }} or UNINITIALIZED + .pw_shell ∈ {{ &buf + [4..256] }} or UNINITIALIZED + result ∈ {{ NULL ; &pwd_out2 }} + buf[0..319] ∈ [--..--] or UNINITIALIZED + buflen ∈ {320} + res ∈ {0; 5; 23; 24} + pwd_out2.pw_name ∈ {{ &buf[0] }} or UNINITIALIZED + .pw_passwd ∈ {{ &buf + [1..64] }} or UNINITIALIZED + {.pw_uid; .pw_gid} ∈ [--..--] or UNINITIALIZED + .pw_gecos ∈ {{ &buf + [2..128] }} or UNINITIALIZED + .pw_dir ∈ {{ &buf + [3..192] }} or UNINITIALIZED + .pw_shell ∈ {{ &buf + [4..256] }} or UNINITIALIZED + __fc_getpw_init ∈ {1} + __retres ∈ {0} diff --git a/tests/libc/oracle/pwd_h.res.oracle b/tests/libc/oracle/pwd_h.res.oracle index 9d329cca5b9..1ef5e0ebc0b 100644 --- a/tests/libc/oracle/pwd_h.res.oracle +++ b/tests/libc/oracle/pwd_h.res.oracle @@ -25,10 +25,11 @@ [eva] done for function main [eva] ====== VALUES COMPUTED ====== [eva:final-states] Values at end of function main: - __fc_pwd.pw_name ∈ {{ NULL + [--..--] ; &__fc_getpwuid_pw_name[0] }} - .pw_passwd ∈ {{ NULL + [--..--] ; &__fc_getpwuid_pw_passwd[0] }} - {.pw_uid; .pw_gid; .pw_gecos} ∈ [--..--] - .pw_dir ∈ {{ NULL + [--..--] ; &__fc_getpwuid_pw_dir[0] }} - .pw_shell ∈ {{ NULL + [--..--] ; &__fc_getpwuid_pw_shell[0] }} + __fc_pwd.pw_name ∈ {{ NULL + [--..--] ; &__fc_getpw_pw_name[0] }} + .pw_passwd ∈ {{ NULL + [--..--] ; &__fc_getpw_pw_passwd[0] }} + {.pw_uid; .pw_gid} ∈ [--..--] + .pw_gecos ∈ {{ NULL + [--..--] ; &__fc_getpw_pw_gecos[0] }} + .pw_dir ∈ {{ NULL + [--..--] ; &__fc_getpw_pw_dir[0] }} + .pw_shell ∈ {{ NULL + [--..--] ; &__fc_getpw_pw_shell[0] }} pw ∈ {{ NULL ; &__fc_pwd }} __retres ∈ {0} diff --git a/tests/libc/pwd_c.c b/tests/libc/pwd_c.c new file mode 100644 index 00000000000..d60731f7f10 --- /dev/null +++ b/tests/libc/pwd_c.c @@ -0,0 +1,38 @@ +/*run.config + STDOPT: #"-eva-precision 1 -eva-split-return full" +*/ +#include "pwd.c" +#include "__fc_string_axiomatic.h" + +extern uid_t uid; + +int main() { + struct passwd pwd_out; + struct passwd *result; + char buf[320]; + size_t buflen = sizeof(buf); + int res = getpwuid_r(uid, &pwd_out, buf, buflen, &result); + if (result) { + //@ assert res == 0; + //@ assert \initialized(&pwd_out.pw_uid); + //@ assert \initialized(&pwd_out.pw_gid); + //Note: ideally, the following assertions will be 'true' someday + //@ assert valid_read_string(pwd_out.pw_name); + //@ assert valid_read_string(pwd_out.pw_passwd); + //@ assert valid_read_string(pwd_out.pw_dir); + //@ assert valid_read_string(pwd_out.pw_shell); + } + //@ slevel merge; + struct passwd pwd_out2; + res = getpwnam_r("root", &pwd_out2, buf, buflen, &result); + if (result) { + //@ assert res == 0; + //@ assert \initialized(&pwd_out2.pw_uid); + //@ assert \initialized(&pwd_out2.pw_gid); + //Note: ideally, the following assertions will be 'true' someday + //@ assert unknown_for_now: valid_read_string(pwd_out2.pw_name); + //@ assert unknown_for_now: valid_read_string(pwd_out2.pw_passwd); + //@ assert unknown_for_now: valid_read_string(pwd_out2.pw_dir); + //@ assert unknown_for_now: valid_read_string(pwd_out2.pw_shell); + } +} -- GitLab