aboutsummaryrefslogtreecommitdiff
path: root/gcc/analyzer/region-model-reachability.cc
diff options
context:
space:
mode:
authorDavid Malcolm <dmalcolm@redhat.com>2023-08-09 16:17:04 -0400
committerDavid Malcolm <dmalcolm@redhat.com>2023-08-09 16:17:04 -0400
commit73da34a538ddc2ad17e80e93b64b526f704693d2 (patch)
treedb8de59479d798a1c3ba42788cb36617c53470f3 /gcc/analyzer/region-model-reachability.cc
parente5fe7f2fd69d5a950d8c1e2a068669bda376b2d4 (diff)
downloadgcc-73da34a538ddc2ad17e80e93b64b526f704693d2.zip
gcc-73da34a538ddc2ad17e80e93b64b526f704693d2.tar.gz
gcc-73da34a538ddc2ad17e80e93b64b526f704693d2.tar.bz2
analyzer: remove default return value from region_model::on_call_pre
Previously, the code for simulating calls to external functions in region_model::on_call_pre wrote a default svalue to the LHS of the call statement, which could be further overwritten by known_function subclasses. Unfortunately, this led to messy hacks, such as when the default svalue was an allocation: the LHS would be written to with two different heap-allocated regions, requiring special-case cleanups to avoid the stray state from the first heap allocation leading to state explosions; see r14-3001-g021077b94741c9. The following patch eliminates this write of a default svalue to the LHS of callsite. Instead, all known_function implementations that have a return value are now responsible for set the LHS themselves. A new call_details::set_any_lhs_with_defaults function is provided to make it easy to get the old behavior. On working through the various known_function subclasses, I noticed that memset was using the default behavior. That patch updates this so that it's now known to return its first parameter. Cleaning this up eliminates various doubling of saved_diagnostics (e.g. for dubious_allocation_size) where it was generating a diagnostic for both writes to the LHS, deduplicating them to the first diagnostic (with the default LHS), and then failing to create a region_creation_event when emitting the diagnostic, leading to the fallback wording in dubious_allocation_size::describe_final_event, such as: (1) allocated 42 bytes and assigned to ‘int32_t *’ {aka ‘int *’} here; ‘sizeof (int32_t {aka int})’ is ‘4’ Without the double write to the LHS, it creates a region_creation_event, so we get the allocation and the assignment as two separate events in the diagnostic path, e.g.: (1) allocated 42 bytes here (2) assigned to ‘int32_t *’ {aka ‘int *’} here; ‘sizeof (int32_t {aka int})’ is ‘4’ gcc/analyzer/ChangeLog: * analyzer.h (class pure_known_function_with_default_return): New subclass. * call-details.cc (const_fn_p): Move here from region-model.cc. (maybe_get_const_fn_result): Likewise. (get_result_size_in_bytes): Likewise. (call_details::set_any_lhs_with_defaults): New function, based on code in region_model::on_call_pre. * call-details.h (call_details::set_any_lhs_with_defaults): New decl. * diagnostic-manager.cc (diagnostic_manager::emit_saved_diagnostic): Log the index of the saved_diagnostic. * kf.cc (pure_known_function_with_default_return::impl_call_pre): New. (kf_memset::impl_call_pre): Set the LHS to the first param. (kf_putenv::impl_call_pre): Call cd.set_any_lhs_with_defaults. (kf_sprintf::impl_call_pre): Call cd.set_any_lhs_with_defaults. (class kf_stack_restore): Derive from pure_known_function_with_default_return. (class kf_stack_save): Likewise. (kf_strlen::impl_call_pre): Call cd.set_any_lhs_with_defaults. * region-model-reachability.cc (reachable_regions::handle_sval): Remove logic for symbolic regions for pointers. * region-model.cc (region_model::canonicalize): Remove purging of dynamic extents workaround for surplus values from region_model::on_call_pre's default LHS code. (const_fn_p): Move to call-details.cc. (maybe_get_const_fn_result): Likewise. (get_result_size_in_bytes): Likewise. (region_model::update_for_nonzero_return): Call cd.set_any_lhs_with_defaults. (region_model::on_call_pre): Remove the assignment to the LHS of a default return value, instead requiring all known_function implementations to write to any LHS of the call. Use cd.set_any_lhs_with_defaults on the non-kf paths. * sm-fd.cc (kf_socket::outcome_of_socket::update_model): Use cd.set_any_lhs_with_defaults when failing to get at fd state. (kf_bind::outcome_of_bind::update_model): Likewise. (kf_listen::outcome_of_listen::update_model): Likewise. (kf_accept::outcome_of_accept::update_model): Likewise. (kf_connect::outcome_of_connect::update_model): Likewise. (kf_read::impl_call_pre): Use cd.set_any_lhs_with_defaults. * sm-file.cc (class kf_stdio_output_fn): Derive from pure_known_function_with_default_return. (class kf_ferror): Likewise. (class kf_fileno): Likewise. (kf_fgets::impl_call_pre): Use cd.set_any_lhs_with_defaults. (kf_read::impl_call_pre): Likewise. (class kf_getc): Derive from pure_known_function_with_default_return. (class kf_getchar): Likewise. * varargs.cc (kf_va_arg::impl_call_pre): Use cd.set_any_lhs_with_defaults. gcc/testsuite/ChangeLog: * gcc.dg/analyzer/allocation-size-1.c: Update expected results to reflect splitting of allocation size and assignment messages from a single event into pairs of events * gcc.dg/analyzer/allocation-size-2.c: Likewise. * gcc.dg/analyzer/allocation-size-3.c: Likewise. * gcc.dg/analyzer/allocation-size-4.c: Likewise. * gcc.dg/analyzer/allocation-size-multiline-1.c: Likewise. * gcc.dg/analyzer/allocation-size-multiline-2.c: Likewise. * gcc.dg/analyzer/allocation-size-multiline-3.c: Likewise. * gcc.dg/analyzer/memset-1.c (test_1): Verify that the return value is the initial argument. * gcc.dg/plugin/analyzer_kernel_plugin.c (copy_across_boundary_fn::impl_call_pre): Ensure the LHS is set on the "known zero size" case. * gcc.dg/plugin/analyzer_known_fns_plugin.c (known_function_attempt_to_copy::impl_call_pre): Likewise. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
Diffstat (limited to 'gcc/analyzer/region-model-reachability.cc')
-rw-r--r--gcc/analyzer/region-model-reachability.cc21
1 files changed, 0 insertions, 21 deletions
diff --git a/gcc/analyzer/region-model-reachability.cc b/gcc/analyzer/region-model-reachability.cc
index 1c747e1..a5c12f4 100644
--- a/gcc/analyzer/region-model-reachability.cc
+++ b/gcc/analyzer/region-model-reachability.cc
@@ -184,27 +184,6 @@ reachable_regions::handle_sval (const svalue *sval)
}
add (pointee, ptr_is_mutable);
}
- else if (sval->get_type ()
- && TREE_CODE (sval->get_type ()) == POINTER_TYPE
- && sval->get_kind () == SK_CONJURED)
- {
- /* Also add symbolic regions for pointers, but only for conjured svalues
- for the LHS of a stmt. Doing it for more leads to state explosions
- on chains of calls to external functions, due to each conjured svalue
- potentially being modified at each successive call, recursively. */
- const conjured_svalue *conjured_sval = (const conjured_svalue *)sval;
- if (conjured_sval->lhs_value_p ())
- {
- const region *pointee
- = m_model->get_manager ()->get_symbolic_region (sval);
- /* Use const-ness of pointer type to affect mutability. */
- bool ptr_is_mutable = true;
- if (TYPE_READONLY (TREE_TYPE (sval->get_type ())))
- ptr_is_mutable = false;
- add (pointee, ptr_is_mutable);
- }
- }
-
/* Treat all svalues within a compound_svalue as reachable. */
if (const compound_svalue *compound_sval
= sval->dyn_cast_compound_svalue ())