diff options
author | David Malcolm <dmalcolm@redhat.com> | 2022-11-29 19:56:27 -0500 |
---|---|---|
committer | David Malcolm <dmalcolm@redhat.com> | 2022-11-29 19:56:27 -0500 |
commit | 84046b192e568e1a0619b72a12c7263553d9610a (patch) | |
tree | 320788c07e0896ac153284256f829a96fe2b7f33 /gcc/analyzer/sm-file.cc | |
parent | 78a17f4452db9514da7cc8706c654cb98ba0a8e6 (diff) | |
download | gcc-84046b192e568e1a0619b72a12c7263553d9610a.zip gcc-84046b192e568e1a0619b72a12c7263553d9610a.tar.gz gcc-84046b192e568e1a0619b72a12c7263553d9610a.tar.bz2 |
analyzer: move stdio known fns to sm-file.cc
gcc/analyzer/ChangeLog:
* region-model-impl-calls.cc (class kf_fgets): Move to sm-file.cc.
(kf_fgets::impl_call_pre): Likewise.
(class kf_fread): Likewise.
(kf_fread::impl_call_pre): Likewise.
(class kf_getchar): Likewise.
(class kf_stdio_output_fn): Likewise.
(register_known_functions): Move registration of
BUILT_IN_FPRINTF, BUILT_IN_FPRINTF_UNLOCKED, BUILT_IN_FPUTC,
BUILT_IN_FPUTC_UNLOCKED, BUILT_IN_FPUTS, BUILT_IN_FPUTS_UNLOCKED,
BUILT_IN_FWRITE, BUILT_IN_FWRITE_UNLOCKED, BUILT_IN_PRINTF,
BUILT_IN_PRINTF_UNLOCKED, BUILT_IN_PUTC, BUILT_IN_PUTCHAR,
BUILT_IN_PUTCHAR_UNLOCKED, BUILT_IN_PUTC_UNLOCKED, BUILT_IN_PUTS,
BUILT_IN_PUTS_UNLOCKED, BUILT_IN_VFPRINTF, BUILT_IN_VPRINTF,
"getchar", "fgets", "fgets_unlocked", and "fread" to
register_known_file_functions.
* sm-file.cc (class kf_stdio_output_fn): Move here from
region-model-impl-calls.cc.
(class kf_fgets): Likewise.
(class kf_fread): Likewise.
(class kf_getchar): Likewise.
(register_known_file_functions): Move registration of
BUILT_IN_FPRINTF, BUILT_IN_FPRINTF_UNLOCKED, BUILT_IN_FPUTC,
BUILT_IN_FPUTC_UNLOCKED, BUILT_IN_FPUTS, BUILT_IN_FPUTS_UNLOCKED,
BUILT_IN_FWRITE, BUILT_IN_FWRITE_UNLOCKED, BUILT_IN_PRINTF,
BUILT_IN_PRINTF_UNLOCKED, BUILT_IN_PUTC, BUILT_IN_PUTCHAR,
BUILT_IN_PUTCHAR_UNLOCKED, BUILT_IN_PUTC_UNLOCKED, BUILT_IN_PUTS,
BUILT_IN_PUTS_UNLOCKED, BUILT_IN_VFPRINTF, BUILT_IN_VPRINTF,
"fgets", "fgets_unlocked", "fread", and "getchar" to here from
register_known_functions.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
Diffstat (limited to 'gcc/analyzer/sm-file.cc')
-rw-r--r-- | gcc/analyzer/sm-file.cc | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/gcc/analyzer/sm-file.cc b/gcc/analyzer/sm-file.cc index 083c0ec..d2dcb43 100644 --- a/gcc/analyzer/sm-file.cc +++ b/gcc/analyzer/sm-file.cc @@ -489,6 +489,21 @@ make_fileptr_state_machine (logger *logger) return new fileptr_state_machine (logger); } +/* Handler for various stdio-related builtins that merely have external + effects that are out of scope for the analyzer: we only want to model + the effects on the return value. */ + +class kf_stdio_output_fn : public known_function +{ +public: + bool matches_call_types_p (const call_details &) const final override + { + return true; + } + + /* A no-op; we just want the conjured return value. */ +}; + /* Handler for "ferror"". */ class kf_ferror : public known_function @@ -517,6 +532,60 @@ public: /* No side effects. */ }; +/* Handler for "fgets" and "fgets_unlocked". */ + +class kf_fgets : public known_function +{ +public: + bool matches_call_types_p (const call_details &cd) const final override + { + return (cd.num_args () == 3 + && cd.arg_is_pointer_p (0) + && cd.arg_is_pointer_p (2)); + } + + void impl_call_pre (const call_details &cd) const final override + { + /* Ideally we would bifurcate state here between the + error vs no error cases. */ + region_model *model = cd.get_model (); + const svalue *ptr_sval = cd.get_arg_svalue (0); + if (const region *reg = ptr_sval->maybe_get_region ()) + { + const region *base_reg = reg->get_base_region (); + const svalue *new_sval = cd.get_or_create_conjured_svalue (base_reg); + model->set_value (base_reg, new_sval, cd.get_ctxt ()); + } + } +}; + +/* Handler for "fread"". */ + +class kf_fread : public known_function +{ +public: + bool matches_call_types_p (const call_details &cd) const final override + { + return (cd.num_args () == 4 + && cd.arg_is_pointer_p (0) + && cd.arg_is_size_p (1) + && cd.arg_is_size_p (2) + && cd.arg_is_pointer_p (3)); + } + + void impl_call_pre (const call_details &cd) const final override + { + region_model *model = cd.get_model (); + const svalue *ptr_sval = cd.get_arg_svalue (0); + if (const region *reg = ptr_sval->maybe_get_region ()) + { + const region *base_reg = reg->get_base_region (); + const svalue *new_sval = cd.get_or_create_conjured_svalue (base_reg); + model->set_value (base_reg, new_sval, cd.get_ctxt ()); + } + } +}; + /* Handler for "getc"". */ class kf_getc : public known_function @@ -531,15 +600,52 @@ public: /* No side effects. */ }; +/* Handler for "getchar"". */ + +class kf_getchar : public known_function +{ +public: + bool matches_call_types_p (const call_details &cd) const final override + { + return cd.num_args () == 0; + } + + /* Empty. No side-effects (tracking stream state is out-of-scope + for the analyzer). */ +}; + /* Populate KFM with instances of known functions relating to stdio streams. */ void register_known_file_functions (known_function_manager &kfm) { + kfm.add (BUILT_IN_FPRINTF, make_unique<kf_stdio_output_fn> ()); + kfm.add (BUILT_IN_FPRINTF_UNLOCKED, make_unique<kf_stdio_output_fn> ()); + kfm.add (BUILT_IN_FPUTC, make_unique<kf_stdio_output_fn> ()); + kfm.add (BUILT_IN_FPUTC_UNLOCKED, make_unique<kf_stdio_output_fn> ()); + kfm.add (BUILT_IN_FPUTS, make_unique<kf_stdio_output_fn> ()); + kfm.add (BUILT_IN_FPUTS_UNLOCKED, make_unique<kf_stdio_output_fn> ()); + kfm.add (BUILT_IN_FWRITE, make_unique<kf_stdio_output_fn> ()); + kfm.add (BUILT_IN_FWRITE_UNLOCKED, make_unique<kf_stdio_output_fn> ()); + kfm.add (BUILT_IN_PRINTF, make_unique<kf_stdio_output_fn> ()); + kfm.add (BUILT_IN_PRINTF_UNLOCKED, make_unique<kf_stdio_output_fn> ()); + kfm.add (BUILT_IN_PUTC, make_unique<kf_stdio_output_fn> ()); + kfm.add (BUILT_IN_PUTCHAR, make_unique<kf_stdio_output_fn> ()); + kfm.add (BUILT_IN_PUTCHAR_UNLOCKED, make_unique<kf_stdio_output_fn> ()); + kfm.add (BUILT_IN_PUTC_UNLOCKED, make_unique<kf_stdio_output_fn> ()); + kfm.add (BUILT_IN_PUTS, make_unique<kf_stdio_output_fn> ()); + kfm.add (BUILT_IN_PUTS_UNLOCKED, make_unique<kf_stdio_output_fn> ()); + kfm.add (BUILT_IN_VFPRINTF, make_unique<kf_stdio_output_fn> ()); + kfm.add (BUILT_IN_VPRINTF, make_unique<kf_stdio_output_fn> ()); + kfm.add ("ferror", make_unique<kf_ferror> ()); + kfm.add ("fgets", make_unique<kf_fgets> ()); + kfm.add ("fgets_unlocked", make_unique<kf_fgets> ()); // non-standard kfm.add ("fileno", make_unique<kf_fileno> ()); + kfm.add ("fread", make_unique<kf_fread> ()); kfm.add ("getc", make_unique<kf_getc> ()); + kfm.add ("getchar", make_unique<kf_getchar> ()); } #if CHECKING_P |