From 8be52d82bfcaac30e309aeabba978b483b91f7ff Mon Sep 17 00:00:00 2001 From: Andre Maroneze <andre.maroneze@cea.fr> Date: Tue, 12 Sep 2023 16:29:17 +0200 Subject: [PATCH] [libc] add spec to realpath --- share/libc/stdlib.h | 31 +- .../tests/memory/oracle/gen_hidden_malloc.c | 200 +++++- .../memory/oracle/hidden_malloc.res.oracle | 38 +- .../tests/temporal/oracle/gen_t_fun_lib.c | 214 +++++- .../temporal/oracle/t_fun_lib.res.oracle | 52 +- .../tests/sarif/oracle/std_string.sarif | 670 ++++++++++++++++++ tests/libc/oracle/argz_c.res.oracle | 1 + tests/libc/oracle/coverage.res.oracle | 2 +- tests/libc/oracle/fc_libc.1.res.oracle | 41 ++ tests/libc/oracle/netdb_c.res.oracle | 1 + 10 files changed, 1223 insertions(+), 27 deletions(-) diff --git a/share/libc/stdlib.h b/share/libc/stdlib.h index dc22e5eeb14..8e21ad8b05f 100644 --- a/share/libc/stdlib.h +++ b/share/libc/stdlib.h @@ -748,9 +748,38 @@ extern int mkstemp(char *templat); */ extern int mkstemps(char *templat, int suffixlen); -// This function may allocate memory for the result, which is not supported by +// 'realpath' may allocate memory for the result, which is not supported by // some plugins such as Eva. In such cases, it is preferable to use the stub // provided in stdlib.c. +/*@ + requires valid_file_name: valid_read_string(file_name); + requires resolved_name_null_or_allocated: + resolved_name == \null || \valid(resolved_name+(0 .. PATH_MAX-1)); + assigns __fc_heap_status \from indirect:resolved_name, __fc_heap_status; + assigns \result, resolved_name[0 .. PATH_MAX-1] \from + indirect:__fc_heap_status, indirect:resolved_name, indirect:file_name[0..]; + behavior allocate_resolved_name: + assumes resolved_name_null: resolved_name == \null; + assumes can_allocate: is_allocable(PATH_MAX); + assigns __fc_heap_status \from __fc_heap_status; + assigns \result \from indirect:__fc_heap_status; + ensures allocation: \fresh(\result,PATH_MAX); + behavior not_enough_memory: + assumes resolved_name_null: resolved_name == \null; + assigns \result \from \nothing; + allocates \nothing; + ensures null_result: \result == \null; + behavior resolved_name_buffer: + assumes allocated_resolved_name_or_fail: + \valid(resolved_name+(0 .. PATH_MAX-1)); + assigns \result \from \nothing; + assigns resolved_name[0 .. PATH_MAX-1] \from indirect:file_name[0..]; + ensures valid_string_resolved_name: valid_string(resolved_name); + // missing: assigns \result, + // resolved_name[0 .. PATH_MAX-1] \from 'filesystem'; + ensures resolved_result: \result == resolved_name; + allocates \nothing; + */ extern char *realpath(const char *restrict file_name, char *restrict resolved_name); diff --git a/src/plugins/e-acsl/tests/memory/oracle/gen_hidden_malloc.c b/src/plugins/e-acsl/tests/memory/oracle/gen_hidden_malloc.c index f264c45b599..e38b61a985d 100644 --- a/src/plugins/e-acsl/tests/memory/oracle/gen_hidden_malloc.c +++ b/src/plugins/e-acsl/tests/memory/oracle/gen_hidden_malloc.c @@ -10,6 +10,204 @@ char *__gen_e_acsl_literal_string; extern __attribute__((__FC_BUILTIN__)) int __e_acsl_sound_verdict; +/*@ requires valid_file_name: valid_read_string(file_name); + requires + resolved_name_null_or_allocated: + resolved_name == \null || \valid(resolved_name + (0 .. 4096 - 1)); + assigns __fc_heap_status, \result, *(resolved_name + (0 .. 4096 - 1)); + assigns __fc_heap_status + \from (indirect: resolved_name), __fc_heap_status; + assigns \result + \from (indirect: __fc_heap_status), (indirect: resolved_name), + (indirect: *(file_name + (0 ..))); + assigns *(resolved_name + (0 .. 4096 - 1)) + \from (indirect: __fc_heap_status), (indirect: resolved_name), + (indirect: *(file_name + (0 ..))); + + behavior allocate_resolved_name: + assumes resolved_name_null: resolved_name == \null; + assumes can_allocate: is_allocable(4096); + ensures allocation: \fresh{Old, Here}(\result,4096); + assigns __fc_heap_status, \result; + assigns __fc_heap_status \from __fc_heap_status; + assigns \result \from (indirect: __fc_heap_status); + + behavior not_enough_memory: + assumes resolved_name_null: resolved_name == \null; + ensures null_result: \result == \null; + assigns \result; + assigns \result \from \nothing; + allocates \nothing; + + behavior resolved_name_buffer: + assumes + allocated_resolved_name_or_fail: + \valid(resolved_name + (0 .. 4096 - 1)); + ensures valid_string_resolved_name: valid_string(\old(resolved_name)); + ensures resolved_result: \result == \old(resolved_name); + assigns \result, *(resolved_name + (0 .. 4096 - 1)); + assigns \result \from \nothing; + assigns *(resolved_name + (0 .. 4096 - 1)) + \from (indirect: *(file_name + (0 ..))); + allocates \nothing; + */ +char *__gen_e_acsl_realpath(char const * restrict file_name, + char * restrict resolved_name); + +/*@ requires valid_file_name: valid_read_string(file_name); + requires + resolved_name_null_or_allocated: + resolved_name == \null || \valid(resolved_name + (0 .. 4096 - 1)); + assigns __fc_heap_status, \result, *(resolved_name + (0 .. 4096 - 1)); + assigns __fc_heap_status + \from (indirect: resolved_name), __fc_heap_status; + assigns \result + \from (indirect: __fc_heap_status), (indirect: resolved_name), + (indirect: *(file_name + (0 ..))); + assigns *(resolved_name + (0 .. 4096 - 1)) + \from (indirect: __fc_heap_status), (indirect: resolved_name), + (indirect: *(file_name + (0 ..))); + + behavior allocate_resolved_name: + assumes resolved_name_null: resolved_name == \null; + assumes can_allocate: is_allocable(4096); + ensures allocation: \fresh{Old, Here}(\result,4096); + assigns __fc_heap_status, \result; + assigns __fc_heap_status \from __fc_heap_status; + assigns \result \from (indirect: __fc_heap_status); + + behavior not_enough_memory: + assumes resolved_name_null: resolved_name == \null; + ensures null_result: \result == \null; + assigns \result; + assigns \result \from \nothing; + allocates \nothing; + + behavior resolved_name_buffer: + assumes + allocated_resolved_name_or_fail: + \valid(resolved_name + (0 .. 4096 - 1)); + ensures valid_string_resolved_name: valid_string(\old(resolved_name)); + ensures resolved_result: \result == \old(resolved_name); + assigns \result, *(resolved_name + (0 .. 4096 - 1)); + assigns \result \from \nothing; + assigns *(resolved_name + (0 .. 4096 - 1)) + \from (indirect: *(file_name + (0 ..))); + allocates \nothing; + */ +char *__gen_e_acsl_realpath(char const * restrict file_name, + char * restrict resolved_name) +{ + __e_acsl_contract_t *__gen_e_acsl_contract; + char *__gen_e_acsl_at; + char *__retres; + { + int __gen_e_acsl_or; + int __gen_e_acsl_size_2; + int __gen_e_acsl_if_2; + int __gen_e_acsl_valid_2; + __e_acsl_store_block((void *)(& resolved_name),8UL); + __gen_e_acsl_at = resolved_name; + __gen_e_acsl_contract = __e_acsl_contract_init(3UL); + __e_acsl_assert_data_t __gen_e_acsl_assert_data_2 = + {.values = (void *)0}; + __e_acsl_assert_register_ptr(& __gen_e_acsl_assert_data_2, + "resolved_name",(void *)resolved_name); + if (resolved_name == (char *)0) __gen_e_acsl_or = 1; + else { + int __gen_e_acsl_size; + int __gen_e_acsl_if; + int __gen_e_acsl_valid; + __gen_e_acsl_size = 1 * (((4096 - 1) - 0) + 1); + if (__gen_e_acsl_size <= 0) __gen_e_acsl_if = 0; + else __gen_e_acsl_if = __gen_e_acsl_size; + __gen_e_acsl_valid = __e_acsl_valid((void *)(resolved_name + 1 * 0), + (size_t)__gen_e_acsl_if, + (void *)resolved_name, + (void *)(& resolved_name)); + __e_acsl_assert_register_ptr(& __gen_e_acsl_assert_data_2, + "resolved_name",(void *)resolved_name); + __e_acsl_assert_register_int(& __gen_e_acsl_assert_data_2, + "sizeof(char)",0,1); + __e_acsl_assert_register_int(& __gen_e_acsl_assert_data_2, + "sizeof(char)",0,1); + __e_acsl_assert_register_int(& __gen_e_acsl_assert_data_2,"size",0, + __gen_e_acsl_size); + __e_acsl_assert_register_int(& __gen_e_acsl_assert_data_2,"size",0, + __gen_e_acsl_size); + __e_acsl_assert_register_int(& __gen_e_acsl_assert_data_2, + "\\valid(resolved_name + (0 .. 4096 - 1))", + 0,__gen_e_acsl_valid); + __gen_e_acsl_or = __gen_e_acsl_valid; + } + __gen_e_acsl_assert_data_2.blocking = 1; + __gen_e_acsl_assert_data_2.kind = "Precondition"; + __gen_e_acsl_assert_data_2.pred_txt = "resolved_name == \\null || \\valid(resolved_name + (0 .. 4096 - 1))"; + __gen_e_acsl_assert_data_2.file = "FRAMAC_SHARE/libc/stdlib.h"; + __gen_e_acsl_assert_data_2.fct = "realpath"; + __gen_e_acsl_assert_data_2.line = 757; + __gen_e_acsl_assert_data_2.name = "resolved_name_null_or_allocated"; + __e_acsl_assert(__gen_e_acsl_or,& __gen_e_acsl_assert_data_2); + __e_acsl_assert_clean(& __gen_e_acsl_assert_data_2); + __e_acsl_contract_set_behavior_assumes(__gen_e_acsl_contract,1UL, + resolved_name == (char *)0); + __gen_e_acsl_size_2 = 1 * (((4096 - 1) - 0) + 1); + if (__gen_e_acsl_size_2 <= 0) __gen_e_acsl_if_2 = 0; + else __gen_e_acsl_if_2 = __gen_e_acsl_size_2; + __gen_e_acsl_valid_2 = __e_acsl_valid((void *)(resolved_name + 1 * 0), + (size_t)__gen_e_acsl_if_2, + (void *)resolved_name, + (void *)(& resolved_name)); + __e_acsl_contract_set_behavior_assumes(__gen_e_acsl_contract,2UL, + __gen_e_acsl_valid_2); + } + __retres = realpath(file_name,resolved_name); + { + int __gen_e_acsl_assumes_value; + __gen_e_acsl_assumes_value = __e_acsl_contract_get_behavior_assumes + ((__e_acsl_contract_t const *)__gen_e_acsl_contract,1UL); + if (__gen_e_acsl_assumes_value) { + __e_acsl_assert_data_t __gen_e_acsl_assert_data_4 = + {.values = (void *)0}; + __e_acsl_assert_register_ptr(& __gen_e_acsl_assert_data_4,"\\result", + (void *)__retres); + __gen_e_acsl_assert_data_4.blocking = 1; + __gen_e_acsl_assert_data_4.kind = "Postcondition"; + __gen_e_acsl_assert_data_4.pred_txt = "\\result == \\null"; + __gen_e_acsl_assert_data_4.file = "FRAMAC_SHARE/libc/stdlib.h"; + __gen_e_acsl_assert_data_4.fct = "realpath"; + __gen_e_acsl_assert_data_4.line = 771; + __gen_e_acsl_assert_data_4.name = "not_enough_memory/null_result"; + __e_acsl_assert(__retres == (char *)0,& __gen_e_acsl_assert_data_4); + __e_acsl_assert_clean(& __gen_e_acsl_assert_data_4); + } + __gen_e_acsl_assumes_value = __e_acsl_contract_get_behavior_assumes + ((__e_acsl_contract_t const *)__gen_e_acsl_contract,2UL); + if (__gen_e_acsl_assumes_value) { + __e_acsl_assert_data_t __gen_e_acsl_assert_data_6 = + {.values = (void *)0}; + __e_acsl_assert_register_ptr(& __gen_e_acsl_assert_data_6,"\\result", + (void *)__retres); + __e_acsl_assert_register_ptr(& __gen_e_acsl_assert_data_6, + "\\old(resolved_name)", + (void *)__gen_e_acsl_at); + __gen_e_acsl_assert_data_6.blocking = 1; + __gen_e_acsl_assert_data_6.kind = "Postcondition"; + __gen_e_acsl_assert_data_6.pred_txt = "\\result == \\old(resolved_name)"; + __gen_e_acsl_assert_data_6.file = "FRAMAC_SHARE/libc/stdlib.h"; + __gen_e_acsl_assert_data_6.fct = "realpath"; + __gen_e_acsl_assert_data_6.line = 780; + __gen_e_acsl_assert_data_6.name = "resolved_name_buffer/resolved_result"; + __e_acsl_assert(__retres == __gen_e_acsl_at, + & __gen_e_acsl_assert_data_6); + __e_acsl_assert_clean(& __gen_e_acsl_assert_data_6); + } + __e_acsl_contract_clean(__gen_e_acsl_contract); + __e_acsl_delete_block((void *)(& resolved_name)); + return __retres; + } +} + void __e_acsl_globals_init(void) { static char __e_acsl_already_run = 0; @@ -28,7 +226,7 @@ int main(int argc, char const **argv) int __retres; __e_acsl_memory_init(& argc,(char ***)(& argv),8UL); __e_acsl_globals_init(); - char *cwd = realpath(__gen_e_acsl_literal_string,(char *)0); + char *cwd = __gen_e_acsl_realpath(__gen_e_acsl_literal_string,(char *)0); __retres = 0; __e_acsl_memory_clean(); return __retres; diff --git a/src/plugins/e-acsl/tests/memory/oracle/hidden_malloc.res.oracle b/src/plugins/e-acsl/tests/memory/oracle/hidden_malloc.res.oracle index aa890a27d2e..526a044a539 100644 --- a/src/plugins/e-acsl/tests/memory/oracle/hidden_malloc.res.oracle +++ b/src/plugins/e-acsl/tests/memory/oracle/hidden_malloc.res.oracle @@ -1,5 +1,37 @@ [e-acsl] beginning translation. +[e-acsl] Warning: annotating undefined function `realpath': + the generated program may miss memory instrumentation + if there are memory-related annotations. +[e-acsl] FRAMAC_SHARE/libc/stdlib.h:754: Warning: + E-ACSL construct `\fresh' is not yet supported. Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/stdlib.h:755: Warning: + no assigns clause generated for function valid_read_string because pointers as arguments is not yet supported +[e-acsl] FRAMAC_SHARE/libc/__fc_string_axiomatic.h:281: Warning: + E-ACSL construct `logic functions or predicates performing read accesses' + is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/stdlib.h:763: Warning: + E-ACSL construct `logic functions or predicates performing read accesses' + is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/stdlib.h:754: Warning: + Some assumes clauses could not be translated. + Ignoring complete and disjoint behaviors annotations. +[e-acsl] FRAMAC_SHARE/libc/stdlib.h:754: Warning: + E-ACSL construct `assigns clause in behavior' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/stdlib.h:766: Warning: + E-ACSL construct `\fresh' is not yet supported. Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/stdlib.h:766: Warning: + E-ACSL construct `assigns clause in behavior' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/stdlib.h:771: Warning: + E-ACSL construct `assigns clause in behavior' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/stdlib.h:777: Warning: + no assigns clause generated for function valid_string because pointers as arguments is not yet supported +[e-acsl] FRAMAC_SHARE/libc/__fc_string_axiomatic.h:278: Warning: + E-ACSL construct `logic functions or predicates performing read accesses' + is not yet supported. + Ignoring annotation. [e-acsl] translation done in project "e-acsl". -[kernel:annot:missing-spec] hidden_malloc.c:11: Warning: - Neither code nor specification for function realpath, - generating default assigns. See -generated-spec-* options for more info diff --git a/src/plugins/e-acsl/tests/temporal/oracle/gen_t_fun_lib.c b/src/plugins/e-acsl/tests/temporal/oracle/gen_t_fun_lib.c index 354f67ce51f..acadb73bba2 100644 --- a/src/plugins/e-acsl/tests/temporal/oracle/gen_t_fun_lib.c +++ b/src/plugins/e-acsl/tests/temporal/oracle/gen_t_fun_lib.c @@ -10,6 +10,212 @@ char *__gen_e_acsl_literal_string; extern __attribute__((__FC_BUILTIN__)) int __e_acsl_sound_verdict; +/*@ requires valid_file_name: valid_read_string(file_name); + requires + resolved_name_null_or_allocated: + resolved_name == \null || \valid(resolved_name + (0 .. 4096 - 1)); + assigns __fc_heap_status, \result, *(resolved_name + (0 .. 4096 - 1)); + assigns __fc_heap_status + \from (indirect: resolved_name), __fc_heap_status; + assigns \result + \from (indirect: __fc_heap_status), (indirect: resolved_name), + (indirect: *(file_name + (0 ..))); + assigns *(resolved_name + (0 .. 4096 - 1)) + \from (indirect: __fc_heap_status), (indirect: resolved_name), + (indirect: *(file_name + (0 ..))); + + behavior allocate_resolved_name: + assumes resolved_name_null: resolved_name == \null; + assumes can_allocate: is_allocable(4096); + ensures allocation: \fresh{Old, Here}(\result,4096); + assigns __fc_heap_status, \result; + assigns __fc_heap_status \from __fc_heap_status; + assigns \result \from (indirect: __fc_heap_status); + + behavior not_enough_memory: + assumes resolved_name_null: resolved_name == \null; + ensures null_result: \result == \null; + assigns \result; + assigns \result \from \nothing; + allocates \nothing; + + behavior resolved_name_buffer: + assumes + allocated_resolved_name_or_fail: + \valid(resolved_name + (0 .. 4096 - 1)); + ensures valid_string_resolved_name: valid_string(\old(resolved_name)); + ensures resolved_result: \result == \old(resolved_name); + assigns \result, *(resolved_name + (0 .. 4096 - 1)); + assigns \result \from \nothing; + assigns *(resolved_name + (0 .. 4096 - 1)) + \from (indirect: *(file_name + (0 ..))); + allocates \nothing; + */ +char *__gen_e_acsl_realpath(char const * restrict file_name, + char * restrict resolved_name); + +/*@ requires valid_file_name: valid_read_string(file_name); + requires + resolved_name_null_or_allocated: + resolved_name == \null || \valid(resolved_name + (0 .. 4096 - 1)); + assigns __fc_heap_status, \result, *(resolved_name + (0 .. 4096 - 1)); + assigns __fc_heap_status + \from (indirect: resolved_name), __fc_heap_status; + assigns \result + \from (indirect: __fc_heap_status), (indirect: resolved_name), + (indirect: *(file_name + (0 ..))); + assigns *(resolved_name + (0 .. 4096 - 1)) + \from (indirect: __fc_heap_status), (indirect: resolved_name), + (indirect: *(file_name + (0 ..))); + + behavior allocate_resolved_name: + assumes resolved_name_null: resolved_name == \null; + assumes can_allocate: is_allocable(4096); + ensures allocation: \fresh{Old, Here}(\result,4096); + assigns __fc_heap_status, \result; + assigns __fc_heap_status \from __fc_heap_status; + assigns \result \from (indirect: __fc_heap_status); + + behavior not_enough_memory: + assumes resolved_name_null: resolved_name == \null; + ensures null_result: \result == \null; + assigns \result; + assigns \result \from \nothing; + allocates \nothing; + + behavior resolved_name_buffer: + assumes + allocated_resolved_name_or_fail: + \valid(resolved_name + (0 .. 4096 - 1)); + ensures valid_string_resolved_name: valid_string(\old(resolved_name)); + ensures resolved_result: \result == \old(resolved_name); + assigns \result, *(resolved_name + (0 .. 4096 - 1)); + assigns \result \from \nothing; + assigns *(resolved_name + (0 .. 4096 - 1)) + \from (indirect: *(file_name + (0 ..))); + allocates \nothing; + */ +char *__gen_e_acsl_realpath(char const * restrict file_name, + char * restrict resolved_name) +{ + __e_acsl_contract_t *__gen_e_acsl_contract; + char *__gen_e_acsl_at; + char *__retres; + __e_acsl_store_block((void *)(& __retres),8UL); + { + int __gen_e_acsl_or; + int __gen_e_acsl_size_2; + int __gen_e_acsl_if_2; + int __gen_e_acsl_valid_2; + __e_acsl_store_block((void *)(& resolved_name),8UL); + __e_acsl_temporal_pull_parameter((void *)(& resolved_name),1U,8UL); + __gen_e_acsl_at = resolved_name; + __gen_e_acsl_contract = __e_acsl_contract_init(3UL); + __e_acsl_assert_data_t __gen_e_acsl_assert_data_2 = + {.values = (void *)0}; + __e_acsl_assert_register_ptr(& __gen_e_acsl_assert_data_2, + "resolved_name",(void *)resolved_name); + if (resolved_name == (char *)0) __gen_e_acsl_or = 1; + else { + int __gen_e_acsl_size; + int __gen_e_acsl_if; + int __gen_e_acsl_valid; + __gen_e_acsl_size = 1 * (((4096 - 1) - 0) + 1); + if (__gen_e_acsl_size <= 0) __gen_e_acsl_if = 0; + else __gen_e_acsl_if = __gen_e_acsl_size; + __gen_e_acsl_valid = __e_acsl_valid((void *)(resolved_name + 1 * 0), + (size_t)__gen_e_acsl_if, + (void *)resolved_name, + (void *)(& resolved_name)); + __e_acsl_assert_register_ptr(& __gen_e_acsl_assert_data_2, + "resolved_name",(void *)resolved_name); + __e_acsl_assert_register_int(& __gen_e_acsl_assert_data_2, + "sizeof(char)",0,1); + __e_acsl_assert_register_int(& __gen_e_acsl_assert_data_2, + "sizeof(char)",0,1); + __e_acsl_assert_register_int(& __gen_e_acsl_assert_data_2,"size",0, + __gen_e_acsl_size); + __e_acsl_assert_register_int(& __gen_e_acsl_assert_data_2,"size",0, + __gen_e_acsl_size); + __e_acsl_assert_register_int(& __gen_e_acsl_assert_data_2, + "\\valid(resolved_name + (0 .. 4096 - 1))", + 0,__gen_e_acsl_valid); + __gen_e_acsl_or = __gen_e_acsl_valid; + } + __gen_e_acsl_assert_data_2.blocking = 1; + __gen_e_acsl_assert_data_2.kind = "Precondition"; + __gen_e_acsl_assert_data_2.pred_txt = "resolved_name == \\null || \\valid(resolved_name + (0 .. 4096 - 1))"; + __gen_e_acsl_assert_data_2.file = "FRAMAC_SHARE/libc/stdlib.h"; + __gen_e_acsl_assert_data_2.fct = "realpath"; + __gen_e_acsl_assert_data_2.line = 757; + __gen_e_acsl_assert_data_2.name = "resolved_name_null_or_allocated"; + __e_acsl_assert(__gen_e_acsl_or,& __gen_e_acsl_assert_data_2); + __e_acsl_assert_clean(& __gen_e_acsl_assert_data_2); + __e_acsl_contract_set_behavior_assumes(__gen_e_acsl_contract,1UL, + resolved_name == (char *)0); + __gen_e_acsl_size_2 = 1 * (((4096 - 1) - 0) + 1); + if (__gen_e_acsl_size_2 <= 0) __gen_e_acsl_if_2 = 0; + else __gen_e_acsl_if_2 = __gen_e_acsl_size_2; + __gen_e_acsl_valid_2 = __e_acsl_valid((void *)(resolved_name + 1 * 0), + (size_t)__gen_e_acsl_if_2, + (void *)resolved_name, + (void *)(& resolved_name)); + __e_acsl_contract_set_behavior_assumes(__gen_e_acsl_contract,2UL, + __gen_e_acsl_valid_2); + __e_acsl_temporal_reset_parameters(); + __e_acsl_temporal_reset_return(); + __e_acsl_temporal_save_nreferent_parameter((void *)(& resolved_name),1U); + } + __retres = realpath(file_name,resolved_name); + __e_acsl_temporal_store_nblock((void *)(& __retres),(void *)*(& __retres)); + { + int __gen_e_acsl_assumes_value; + __e_acsl_temporal_save_return((void *)(& __retres)); + __gen_e_acsl_assumes_value = __e_acsl_contract_get_behavior_assumes + ((__e_acsl_contract_t const *)__gen_e_acsl_contract,1UL); + if (__gen_e_acsl_assumes_value) { + __e_acsl_assert_data_t __gen_e_acsl_assert_data_4 = + {.values = (void *)0}; + __e_acsl_assert_register_ptr(& __gen_e_acsl_assert_data_4,"\\result", + (void *)__retres); + __gen_e_acsl_assert_data_4.blocking = 1; + __gen_e_acsl_assert_data_4.kind = "Postcondition"; + __gen_e_acsl_assert_data_4.pred_txt = "\\result == \\null"; + __gen_e_acsl_assert_data_4.file = "FRAMAC_SHARE/libc/stdlib.h"; + __gen_e_acsl_assert_data_4.fct = "realpath"; + __gen_e_acsl_assert_data_4.line = 771; + __gen_e_acsl_assert_data_4.name = "not_enough_memory/null_result"; + __e_acsl_assert(__retres == (char *)0,& __gen_e_acsl_assert_data_4); + __e_acsl_assert_clean(& __gen_e_acsl_assert_data_4); + } + __gen_e_acsl_assumes_value = __e_acsl_contract_get_behavior_assumes + ((__e_acsl_contract_t const *)__gen_e_acsl_contract,2UL); + if (__gen_e_acsl_assumes_value) { + __e_acsl_assert_data_t __gen_e_acsl_assert_data_6 = + {.values = (void *)0}; + __e_acsl_assert_register_ptr(& __gen_e_acsl_assert_data_6,"\\result", + (void *)__retres); + __e_acsl_assert_register_ptr(& __gen_e_acsl_assert_data_6, + "\\old(resolved_name)", + (void *)__gen_e_acsl_at); + __gen_e_acsl_assert_data_6.blocking = 1; + __gen_e_acsl_assert_data_6.kind = "Postcondition"; + __gen_e_acsl_assert_data_6.pred_txt = "\\result == \\old(resolved_name)"; + __gen_e_acsl_assert_data_6.file = "FRAMAC_SHARE/libc/stdlib.h"; + __gen_e_acsl_assert_data_6.fct = "realpath"; + __gen_e_acsl_assert_data_6.line = 780; + __gen_e_acsl_assert_data_6.name = "resolved_name_buffer/resolved_result"; + __e_acsl_assert(__retres == __gen_e_acsl_at, + & __gen_e_acsl_assert_data_6); + __e_acsl_assert_clean(& __gen_e_acsl_assert_data_6); + } + __e_acsl_contract_clean(__gen_e_acsl_contract); + __e_acsl_delete_block((void *)(& resolved_name)); + __e_acsl_delete_block((void *)(& __retres)); + return __retres; + } +} + void __e_acsl_globals_init(void) { static char __e_acsl_already_run = 0; @@ -111,16 +317,16 @@ int main(void) __e_acsl_temporal_reset_parameters(); __e_acsl_temporal_reset_return(); __e_acsl_temporal_save_nreferent_parameter((void *)(& q),1U); - char *path = realpath((char const *)c,q); - __e_acsl_temporal_store_nblock((void *)(& path),(void *)*(& path)); + char *path = __gen_e_acsl_realpath((char const *)c,q); + __e_acsl_temporal_pull_return((void *)(& path)); __e_acsl_store_block((void *)(& path),8UL); __e_acsl_full_init((void *)(& path)); __e_acsl_full_init((void *)(& path)); __e_acsl_temporal_reset_parameters(); __e_acsl_temporal_reset_return(); __e_acsl_temporal_save_nreferent_parameter((void *)(& q),1U); - path = realpath((char const *)c,q); - __e_acsl_temporal_store_nblock((void *)(& path),(void *)*(& path)); + path = __gen_e_acsl_realpath((char const *)c,q); + __e_acsl_temporal_pull_return((void *)(& path)); { int __gen_e_acsl_initialized_3; int __gen_e_acsl_and_4; diff --git a/src/plugins/e-acsl/tests/temporal/oracle/t_fun_lib.res.oracle b/src/plugins/e-acsl/tests/temporal/oracle/t_fun_lib.res.oracle index f6c71b561f1..fec515bf845 100644 --- a/src/plugins/e-acsl/tests/temporal/oracle/t_fun_lib.res.oracle +++ b/src/plugins/e-acsl/tests/temporal/oracle/t_fun_lib.res.oracle @@ -1,4 +1,39 @@ [e-acsl] beginning translation. +[e-acsl] Warning: annotating undefined function `realpath': + the generated program may miss memory instrumentation + if there are memory-related annotations. +[e-acsl] FRAMAC_SHARE/libc/stdlib.h:754: Warning: + E-ACSL construct `\fresh' is not yet supported. Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/stdlib.h:755: Warning: + no assigns clause generated for function valid_read_string because pointers as arguments is not yet supported +[e-acsl] FRAMAC_SHARE/libc/__fc_string_axiomatic.h:281: Warning: + E-ACSL construct `logic functions or predicates performing read accesses' + is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/stdlib.h:763: Warning: + E-ACSL construct `logic functions or predicates performing read accesses' + is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/stdlib.h:754: Warning: + Some assumes clauses could not be translated. + Ignoring complete and disjoint behaviors annotations. +[e-acsl] FRAMAC_SHARE/libc/stdlib.h:754: Warning: + E-ACSL construct `assigns clause in behavior' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/stdlib.h:766: Warning: + E-ACSL construct `\fresh' is not yet supported. Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/stdlib.h:766: Warning: + E-ACSL construct `assigns clause in behavior' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/stdlib.h:771: Warning: + E-ACSL construct `assigns clause in behavior' is not yet supported. + Ignoring annotation. +[e-acsl] FRAMAC_SHARE/libc/stdlib.h:777: Warning: + no assigns clause generated for function valid_string because pointers as arguments is not yet supported +[e-acsl] FRAMAC_SHARE/libc/__fc_string_axiomatic.h:278: Warning: + E-ACSL construct `logic functions or predicates performing read accesses' + is not yet supported. + Ignoring annotation. [e-acsl] translation done in project "e-acsl". [eva:alarm] t_fun_lib.c:15: Warning: function __e_acsl_assert_register_ulong: precondition data->values == \null || @@ -27,20 +62,3 @@ [eva:alarm] t_fun_lib.c:15: Warning: function __e_acsl_assert_register_ulong: precondition data->values == \null || \valid(data->values) got status unknown. -[kernel:annot:missing-spec] t_fun_lib.c:19: Warning: - Neither code nor specification for function realpath, - generating default assigns. See -generated-spec-* options for more info -[eva:alarm] t_fun_lib.c:22: Warning: - function __e_acsl_assert_register_ulong: precondition data->values == \null || - \valid(data->values) got status unknown. -[eva:alarm] t_fun_lib.c:22: Warning: - function __e_acsl_assert_register_int: precondition data->values == \null || - \valid(data->values) got status unknown. -[eva:alarm] t_fun_lib.c:22: Warning: - function __e_acsl_assert_register_ptr: precondition data->values == \null || - \valid(data->values) got status unknown. -[eva:alarm] t_fun_lib.c:22: Warning: - function __e_acsl_assert_register_ulong: precondition data->values == \null || - \valid(data->values) got status unknown. -[eva:alarm] t_fun_lib.c:22: Warning: - function __e_acsl_assert, behavior blocking: precondition got status invalid. diff --git a/src/plugins/markdown-report/tests/sarif/oracle/std_string.sarif b/src/plugins/markdown-report/tests/sarif/oracle/std_string.sarif index d5f67f7b13c..c09cffbaa62 100644 --- a/src/plugins/markdown-report/tests/sarif/oracle/std_string.sarif +++ b/src/plugins/markdown-report/tests/sarif/oracle/std_string.sarif @@ -14182,6 +14182,676 @@ } ] }, + { + "ruleId": "user-spec", + "kind": "pass", + "level": "none", + "message": { + "text": "behavior allocate_resolved_name in function realpath." + }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "libc/stdlib.h", + "uriBaseId": "FRAMAC_SHARE" + }, + "region": { + "startLine": 783, + "startColumn": 12, + "endLine": 783, + "endColumn": 13, + "byteLength": 1 + } + } + } + ] + }, + { + "ruleId": "user-spec", + "kind": "pass", + "level": "none", + "message": { "text": "behavior default! in function realpath." }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "libc/stdlib.h", + "uriBaseId": "FRAMAC_SHARE" + }, + "region": { + "startLine": 783, + "startColumn": 12, + "endLine": 783, + "endColumn": 13, + "byteLength": 1 + } + } + } + ] + }, + { + "ruleId": "user-spec", + "kind": "pass", + "level": "none", + "message": { + "text": "behavior not_enough_memory in function realpath." + }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "libc/stdlib.h", + "uriBaseId": "FRAMAC_SHARE" + }, + "region": { + "startLine": 783, + "startColumn": 12, + "endLine": 783, + "endColumn": 13, + "byteLength": 1 + } + } + } + ] + }, + { + "ruleId": "user-spec", + "kind": "pass", + "level": "none", + "message": { + "text": "behavior resolved_name_buffer in function realpath." + }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "libc/stdlib.h", + "uriBaseId": "FRAMAC_SHARE" + }, + "region": { + "startLine": 783, + "startColumn": 12, + "endLine": 783, + "endColumn": 13, + "byteLength": 1 + } + } + } + ] + }, + { + "ruleId": "user-spec", + "kind": "pass", + "level": "none", + "message": { "text": "valid_file_name." }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "libc/stdlib.h", + "uriBaseId": "FRAMAC_SHARE" + }, + "region": { + "startLine": 755, + "startColumn": 28, + "endLine": 755, + "endColumn": 56, + "byteLength": 28 + } + } + } + ] + }, + { + "ruleId": "user-spec", + "kind": "pass", + "level": "none", + "message": { "text": "resolved_name_null_or_allocated." }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "libc/stdlib.h", + "uriBaseId": "FRAMAC_SHARE" + }, + "region": { + "startLine": 757, + "startColumn": 4, + "endLine": 757, + "endColumn": 66, + "byteLength": 62 + } + } + } + ] + }, + { + "ruleId": "user-spec", + "kind": "pass", + "level": "none", + "message": { "text": "resolved_name_null." }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "libc/stdlib.h", + "uriBaseId": "FRAMAC_SHARE" + }, + "region": { + "startLine": 762, + "startColumn": 32, + "endLine": 762, + "endColumn": 54, + "byteLength": 22 + } + } + } + ] + }, + { + "ruleId": "user-spec", + "kind": "pass", + "level": "none", + "message": { "text": "can_allocate." }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "libc/stdlib.h", + "uriBaseId": "FRAMAC_SHARE" + }, + "region": { + "startLine": 763, + "startColumn": 26, + "endLine": 763, + "endColumn": 44, + "byteLength": 18 + } + } + } + ] + }, + { + "ruleId": "user-spec", + "kind": "pass", + "level": "none", + "message": { "text": "resolved_name_null." }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "libc/stdlib.h", + "uriBaseId": "FRAMAC_SHARE" + }, + "region": { + "startLine": 768, + "startColumn": 32, + "endLine": 768, + "endColumn": 54, + "byteLength": 22 + } + } + } + ] + }, + { + "ruleId": "user-spec", + "kind": "pass", + "level": "none", + "message": { "text": "allocated_resolved_name_or_fail." }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "libc/stdlib.h", + "uriBaseId": "FRAMAC_SHARE" + }, + "region": { + "startLine": 774, + "startColumn": 6, + "endLine": 774, + "endColumn": 42, + "byteLength": 36 + } + } + } + ] + }, + { + "ruleId": "user-spec", + "kind": "pass", + "level": "none", + "message": { "text": "allocation." }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "libc/stdlib.h", + "uriBaseId": "FRAMAC_SHARE" + }, + "region": { + "startLine": 766, + "startColumn": 24, + "endLine": 766, + "endColumn": 44, + "byteLength": 20 + } + } + } + ] + }, + { + "ruleId": "user-spec", + "kind": "pass", + "level": "none", + "message": { "text": "null_result." }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "libc/stdlib.h", + "uriBaseId": "FRAMAC_SHARE" + }, + "region": { + "startLine": 771, + "startColumn": 25, + "endLine": 771, + "endColumn": 41, + "byteLength": 16 + } + } + } + ] + }, + { + "ruleId": "user-spec", + "kind": "pass", + "level": "none", + "message": { "text": "valid_string_resolved_name." }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "libc/stdlib.h", + "uriBaseId": "FRAMAC_SHARE" + }, + "region": { + "startLine": 777, + "startColumn": 40, + "endLine": 777, + "endColumn": 67, + "byteLength": 27 + } + } + } + ] + }, + { + "ruleId": "user-spec", + "kind": "pass", + "level": "none", + "message": { "text": "resolved_result." }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "libc/stdlib.h", + "uriBaseId": "FRAMAC_SHARE" + }, + "region": { + "startLine": 780, + "startColumn": 29, + "endLine": 780, + "endColumn": 53, + "byteLength": 24 + } + } + } + ] + }, + { + "ruleId": "user-spec", + "kind": "pass", + "level": "none", + "message": { "text": "assigns clause in function realpath." }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "libc/stdlib.h", + "uriBaseId": "FRAMAC_SHARE" + }, + "region": { + "startLine": 764, + "startColumn": 12, + "endLine": 764, + "endColumn": 28, + "byteLength": 16 + } + } + } + ] + }, + { + "ruleId": "user-spec", + "kind": "pass", + "level": "none", + "message": { "text": "assigns clause in function realpath." }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "libc/stdlib.h", + "uriBaseId": "FRAMAC_SHARE" + }, + "region": { + "startLine": 758, + "startColumn": 10, + "endLine": 758, + "endColumn": 26, + "byteLength": 16 + } + } + } + ] + }, + { + "ruleId": "user-spec", + "kind": "pass", + "level": "none", + "message": { "text": "assigns clause in function realpath." }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "libc/stdlib.h", + "uriBaseId": "FRAMAC_SHARE" + }, + "region": { + "startLine": 783, + "startColumn": 12, + "endLine": 783, + "endColumn": 13, + "byteLength": 1 + } + } + } + ] + }, + { + "ruleId": "user-spec", + "kind": "pass", + "level": "none", + "message": { "text": "assigns clause in function realpath." }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "libc/stdlib.h", + "uriBaseId": "FRAMAC_SHARE" + }, + "region": { + "startLine": 775, + "startColumn": 12, + "endLine": 775, + "endColumn": 19, + "byteLength": 7 + } + } + } + ] + }, + { + "ruleId": "user-spec", + "kind": "pass", + "level": "none", + "message": { + "text": "from clause of term __fc_heap_status in function realpath." + }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "libc/stdlib.h", + "uriBaseId": "FRAMAC_SHARE" + }, + "region": { + "startLine": 764, + "startColumn": 12, + "endLine": 764, + "endColumn": 28, + "byteLength": 16 + } + } + } + ] + }, + { + "ruleId": "user-spec", + "kind": "pass", + "level": "none", + "message": { + "text": "from clause of term \\result in function realpath." + }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "libc/stdlib.h", + "uriBaseId": "FRAMAC_SHARE" + }, + "region": { + "startLine": 765, + "startColumn": 12, + "endLine": 765, + "endColumn": 19, + "byteLength": 7 + } + } + } + ] + }, + { + "ruleId": "user-spec", + "kind": "pass", + "level": "none", + "message": { + "text": "from clause of term __fc_heap_status in function realpath." + }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "libc/stdlib.h", + "uriBaseId": "FRAMAC_SHARE" + }, + "region": { + "startLine": 758, + "startColumn": 10, + "endLine": 758, + "endColumn": 26, + "byteLength": 16 + } + } + } + ] + }, + { + "ruleId": "user-spec", + "kind": "pass", + "level": "none", + "message": { + "text": "from clause of term \\result in function realpath." + }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "libc/stdlib.h", + "uriBaseId": "FRAMAC_SHARE" + }, + "region": { + "startLine": 759, + "startColumn": 10, + "endLine": 759, + "endColumn": 17, + "byteLength": 7 + } + } + } + ] + }, + { + "ruleId": "user-spec", + "kind": "pass", + "level": "none", + "message": { + "text": "from clause of term *(resolved_name + (0 .. 4096 - 1)) in function realpath." + }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "libc/stdlib.h", + "uriBaseId": "FRAMAC_SHARE" + }, + "region": { + "startLine": 759, + "startColumn": 19, + "endLine": 759, + "endColumn": 46, + "byteLength": 27 + } + } + } + ] + }, + { + "ruleId": "user-spec", + "kind": "pass", + "level": "none", + "message": { + "text": "from clause of term \\result in function realpath." + }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "libc/stdlib.h", + "uriBaseId": "FRAMAC_SHARE" + }, + "region": { + "startLine": 769, + "startColumn": 12, + "endLine": 769, + "endColumn": 19, + "byteLength": 7 + } + } + } + ] + }, + { + "ruleId": "user-spec", + "kind": "pass", + "level": "none", + "message": { + "text": "from clause of term \\result in function realpath." + }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "libc/stdlib.h", + "uriBaseId": "FRAMAC_SHARE" + }, + "region": { + "startLine": 775, + "startColumn": 12, + "endLine": 775, + "endColumn": 19, + "byteLength": 7 + } + } + } + ] + }, + { + "ruleId": "user-spec", + "kind": "pass", + "level": "none", + "message": { + "text": "from clause of term *(resolved_name + (0 .. 4096 - 1)) in function realpath." + }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "libc/stdlib.h", + "uriBaseId": "FRAMAC_SHARE" + }, + "region": { + "startLine": 776, + "startColumn": 12, + "endLine": 776, + "endColumn": 39, + "byteLength": 27 + } + } + } + ] + }, + { + "ruleId": "user-spec", + "kind": "pass", + "level": "none", + "message": { + "text": "allocates/frees clause in function realpath." + }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "libc/stdlib.h", + "uriBaseId": "FRAMAC_SHARE" + }, + "region": { + "startLine": 783, + "startColumn": 12, + "endLine": 783, + "endColumn": 13, + "byteLength": 1 + } + } + } + ] + }, + { + "ruleId": "user-spec", + "kind": "pass", + "level": "none", + "message": { + "text": "allocates/frees clause in function realpath." + }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "libc/stdlib.h", + "uriBaseId": "FRAMAC_SHARE" + }, + "region": { + "startLine": 783, + "startColumn": 12, + "endLine": 783, + "endColumn": 13, + "byteLength": 1 + } + } + } + ] + }, { "ruleId": "user-spec", "kind": "pass", diff --git a/tests/libc/oracle/argz_c.res.oracle b/tests/libc/oracle/argz_c.res.oracle index f1c6521d1fb..38884838a6f 100644 --- a/tests/libc/oracle/argz_c.res.oracle +++ b/tests/libc/oracle/argz_c.res.oracle @@ -21,6 +21,7 @@ \return(reallocarray) == 0 (auto) \return(getenv) == 0 (auto) \return(bsearch) == 0 (auto) + \return(realpath) == 0 (auto) \return(memchr) == 0 (auto) \return(memrchr) == 0 (auto) \return(memcpy) == 0 (auto) diff --git a/tests/libc/oracle/coverage.res.oracle b/tests/libc/oracle/coverage.res.oracle index fc23e8f6baa..b53e4177747 100644 --- a/tests/libc/oracle/coverage.res.oracle +++ b/tests/libc/oracle/coverage.res.oracle @@ -28,7 +28,7 @@ main: 4 stmts out of 4 (100.0%) [metrics] Eva coverage statistics ======================= - Syntactically reachable functions = 2 (out of 98) + Syntactically reachable functions = 2 (out of 99) Semantically reached functions = 2 Coverage estimation = 100.0% [metrics] Statements analyzed by Eva diff --git a/tests/libc/oracle/fc_libc.1.res.oracle b/tests/libc/oracle/fc_libc.1.res.oracle index 06f9fb802ba..d08401adb21 100644 --- a/tests/libc/oracle/fc_libc.1.res.oracle +++ b/tests/libc/oracle/fc_libc.1.res.oracle @@ -7194,6 +7194,47 @@ int posix_memalign(void **memptr, size_t alignment, size_t size) return_label: return __retres; } +/*@ requires valid_file_name: valid_read_string(file_name); + requires + resolved_name_null_or_allocated: + resolved_name ≡ \null ∨ \valid(resolved_name + (0 .. 4096 - 1)); + assigns __fc_heap_status, \result, *(resolved_name + (0 .. 4096 - 1)); + assigns __fc_heap_status + \from (indirect: resolved_name), __fc_heap_status; + assigns \result + \from (indirect: __fc_heap_status), (indirect: resolved_name), + (indirect: *(file_name + (0 ..))); + assigns *(resolved_name + (0 .. 4096 - 1)) + \from (indirect: __fc_heap_status), (indirect: resolved_name), + (indirect: *(file_name + (0 ..))); + + behavior allocate_resolved_name: + assumes resolved_name_null: resolved_name ≡ \null; + assumes can_allocate: is_allocable(4096); + ensures allocation: \fresh{Old, Here}(\result,4096); + assigns __fc_heap_status, \result; + assigns __fc_heap_status \from __fc_heap_status; + assigns \result \from (indirect: __fc_heap_status); + + behavior not_enough_memory: + assumes resolved_name_null: resolved_name ≡ \null; + ensures null_result: \result ≡ \null; + assigns \result; + assigns \result \from \nothing; + allocates \nothing; + + behavior resolved_name_buffer: + assumes + allocated_resolved_name_or_fail: + \valid(resolved_name + (0 .. 4096 - 1)); + ensures valid_string_resolved_name: valid_string(\old(resolved_name)); + ensures resolved_result: \result ≡ \old(resolved_name); + assigns \result, *(resolved_name + (0 .. 4096 - 1)); + assigns \result \from \nothing; + assigns *(resolved_name + (0 .. 4096 - 1)) + \from (indirect: *(file_name + (0 ..))); + allocates \nothing; + */ char *realpath(char const * restrict file_name, char * restrict resolved_name) { char *__retres; diff --git a/tests/libc/oracle/netdb_c.res.oracle b/tests/libc/oracle/netdb_c.res.oracle index 860879bc5e5..55cc38194e3 100644 --- a/tests/libc/oracle/netdb_c.res.oracle +++ b/tests/libc/oracle/netdb_c.res.oracle @@ -16,6 +16,7 @@ \return(reallocarray) == 0 (auto) \return(getenv) == 0 (auto) \return(bsearch) == 0 (auto) + \return(realpath) == 0 (auto) \return(getcwd) == 0 (auto) \return(ttyname) == 0 (auto) \return(memchr) == 0 (auto) -- GitLab