mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-03 05:10:26 +08:00
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>
This commit is contained in:
parent
78a17f4452
commit
84046b192e
@ -704,66 +704,6 @@ kf_error::impl_call_pre (const call_details &cd) const
|
||||
ctxt->terminate_path ();
|
||||
}
|
||||
|
||||
/* 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;
|
||||
};
|
||||
|
||||
void
|
||||
kf_fgets::impl_call_pre (const call_details &cd) const
|
||||
{
|
||||
/* 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;
|
||||
};
|
||||
|
||||
void
|
||||
kf_fread::impl_call_pre (const call_details &cd) const
|
||||
{
|
||||
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 "free", after sm-handling.
|
||||
|
||||
If the ptr points to an underlying heap region, delete the region,
|
||||
@ -803,20 +743,6 @@ kf_free::impl_call_post (const call_details &cd) const
|
||||
}
|
||||
}
|
||||
|
||||
/* 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). */
|
||||
};
|
||||
|
||||
/* Handle the on_call_pre part of "malloc". */
|
||||
|
||||
class kf_malloc : public known_function
|
||||
@ -1455,21 +1381,6 @@ public:
|
||||
/* Currently a no-op. */
|
||||
};
|
||||
|
||||
/* 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 "strcpy" and "__builtin_strcpy_chk". */
|
||||
|
||||
class kf_strcpy : public known_function
|
||||
@ -1592,28 +1503,12 @@ register_known_functions (known_function_manager &kfm)
|
||||
kfm.add (BUILT_IN_CALLOC, make_unique<kf_calloc> ());
|
||||
kfm.add (BUILT_IN_EXPECT, make_unique<kf_expect> ());
|
||||
kfm.add (BUILT_IN_EXPECT_WITH_PROBABILITY, make_unique<kf_expect> ());
|
||||
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_FREE, make_unique<kf_free> ());
|
||||
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_MALLOC, make_unique<kf_malloc> ());
|
||||
kfm.add (BUILT_IN_MEMCPY, make_unique<kf_memcpy> ());
|
||||
kfm.add (BUILT_IN_MEMCPY_CHK, make_unique<kf_memcpy> ());
|
||||
kfm.add (BUILT_IN_MEMSET, make_unique<kf_memset> ());
|
||||
kfm.add (BUILT_IN_MEMSET_CHK, make_unique<kf_memset> ());
|
||||
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_REALLOC, make_unique<kf_realloc> ());
|
||||
kfm.add (BUILT_IN_STACK_RESTORE, make_unique<kf_stack_restore> ());
|
||||
kfm.add (BUILT_IN_STACK_SAVE, make_unique<kf_stack_save> ());
|
||||
@ -1621,8 +1516,6 @@ register_known_functions (known_function_manager &kfm)
|
||||
kfm.add (BUILT_IN_STRCPY, make_unique<kf_strcpy> (2));
|
||||
kfm.add (BUILT_IN_STRCPY_CHK, make_unique<kf_strcpy> (3));
|
||||
kfm.add (BUILT_IN_STRLEN, make_unique<kf_strlen> ());
|
||||
kfm.add (BUILT_IN_VFPRINTF, make_unique<kf_stdio_output_fn> ());
|
||||
kfm.add (BUILT_IN_VPRINTF, make_unique<kf_stdio_output_fn> ());
|
||||
|
||||
register_varargs_builtins (kfm);
|
||||
}
|
||||
@ -1650,15 +1543,11 @@ register_known_functions (known_function_manager &kfm)
|
||||
|
||||
/* Known builtins and C standard library functions. */
|
||||
{
|
||||
kfm.add ("getchar", make_unique<kf_getchar> ());
|
||||
kfm.add ("memset", make_unique<kf_memset> ());
|
||||
}
|
||||
|
||||
/* Known POSIX functions, and some non-standard extensions. */
|
||||
{
|
||||
kfm.add ("fgets", make_unique<kf_fgets> ());
|
||||
kfm.add ("fgets_unlocked", make_unique<kf_fgets> ()); // non-standard
|
||||
kfm.add ("fread", make_unique<kf_fread> ());
|
||||
kfm.add ("putenv", make_unique<kf_putenv> ());
|
||||
|
||||
register_known_fd_functions (kfm);
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user